diff --git a/AGENTS.md b/AGENTS.md index fd68b560..ff2aefec 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ ## Specs -The specs in `specs/` are the source of truth. Start with `specs/README.md` (reading order, conventions), then `specs/01-architecture.md` (layout, package rules, how the apps are served). App specs: `specs/wonky_write/`, `specs/wonky_sheets/`, `specs/wonky_drive/` and `specs/wonky_slides/` (v2 decisions: `specs/v2-review.md`). Cross-app features: `specs/16-bugs-and-improvements.md` (Bugs & improvements board, M12); the RevLog sync of Sheets and Slides: `specs/17-revlog-sync.md`. When implementation reveals a better approach, update the spec in the same change. +The specs in `specs/` are the source of truth. Start with `specs/README.md` (reading order, conventions), then `specs/01-architecture.md` (layout, package rules, how the apps are served). App specs: `specs/wonky_write/`, `specs/wonky_sheets/`, `specs/wonky_drive/` and `specs/wonky_slides/` (v2 decisions: `specs/v2-review.md`). Cross-app features: `specs/16-bugs-and-improvements.md` (Bugs & improvements board, M12); the RevLog sync of Sheets and Slides: `specs/17-revlog-sync.md`. Blog submissions from Wonky Write (M14, built): `specs/18-publications-and-submissions.md`; the guide for blog owners is `docs/blog-integration.md`. When implementation reveals a better approach, update the spec in the same change. Key rules from the specs: every user-visible action is a command and every state change is undoable (`specs/08-commands-and-undo.md`); single window, never open new tabs or windows (`specs/03-app-shell-and-navigation.md`); UI is built with `shad` and custom widgets in `wonky_ui` (`specs/02-design-system.md`); everything works in light and dark. diff --git a/TODO.md b/TODO.md index ef1f83dd..3a38842e 100644 --- a/TODO.md +++ b/TODO.md @@ -136,6 +136,17 @@ committed and verified). - PDF exports (client and server) cover Latin, Greek and Cyrillic with the bundled TTFs; CJK, Arabic and emoji fall back to placeholders until the fallback fonts are added. - WYSIWYG Markdown composer (`wonky_rich_editor`, specs/16 §7.3): ☐ a code block's language can only be set when typing the fence; ☐ browser check of IME typing (the first keys after a click, fixed in the widget, see §7.3), paste, copy as Markdown, the spelling menu and the link dialog in the release builds; ☐ the composer's spelling language is the device locale (no per-field language). +## Publications & submissions (M14) — open items + +Spec: `specs/18-publications-and-submissions.md` §13; guide: `docs/blog-integration.md`. + +- [ ] Light/dark goldens of the consent dialog, submit dialog, status chip and Settings › + Publications. +- [ ] E2E journey J-P1 (link → sign up → write → submit → changes requested → resubmit → + published) against a fake blog receiver, and a walkthrough against the live server. +- [ ] Moderators who sign up later get access only with the next submit or status change; grant + at sign-up instead. + ## RevLog sync — open items Sheets and Slides sync through RevLog (`specs/17-revlog-sync.md`); the CRDT engine, the sync diff --git a/docs/blog-integration.md b/docs/blog-integration.md new file mode 100644 index 00000000..312983f8 --- /dev/null +++ b/docs/blog-integration.md @@ -0,0 +1,507 @@ +# Take stories from Wonky Write on your blog + +This guide is for blog owners and their developers. It shows how to let people write a story +for your blog in [Wonky Write](https://wonky.work/write/) and send it to your review queue with +one button. + +How it works: + +1. Your blog links to Wonky Write with a **Write for us** button. +2. The contributor signs in (or signs up), agrees to send their story to your blog, and writes in + their own Wonky document. Co-authors, comments, suggestions and offline editing all work as + usual. +3. The contributor presses **Submit**. Wonky sends the story to your server as a signed webhook, + and you put it in your review queue. +4. Your moderators read the story, and can comment and suggest edits in the Wonky document. +5. Your moderation tool tells Wonky the outcome: *changes requested*, *declined* or *published*, + with an optional message. The contributor sees it in the document and gets a notification. + After changes, they press **Resubmit** and the story comes back to your queue. + +``` + Your blog Wonky Contributor + ───────── ───── ─────────── + "Write for us" link ───────────▶ /write/new?publication=pub_… ◀──── opens link, signs in + new document for the story ◀──── writes, presses Submit + webhook receiver ◀── POST ───── submission.submitted (signed) + review queue + moderator opens the document ───▶ comments / suggestions ────▶ notified + status API ── POST ────────────▶ "changesRequested" + message ────▶ notified, edits, Resubmit + webhook receiver ◀── POST ───── submission.submitted (sequence 2) + status API ── POST ────────────▶ "published" + post URL ────▶ "Published · View post" +``` + +What you need: + +- A Wonky account (free, at [wonky.work](https://wonky.work)). +- An HTTPS endpoint on your server that can receive webhooks (port 443, a public address). +- A place on your server to keep two secrets: the **signing secret** and the **API key**. Never + put them in your website's frontend code. +- Your moderators' Wonky accounts, if they should read and comment on stories in Wonky. + +The full design is in [specs/18-publications-and-submissions.md](../specs/18-publications-and-submissions.md). + +--- + +## 1. Create a publication + +In Wonky, open **Settings › Publications** (any app: account menu › *Wonky Work settings*) and +choose **New publication**. + +| Setting | What to enter | +|---------|---------------| +| Name | What contributors see, e.g. *Serverpod blog* (up to 60 characters) | +| Site URL | Your blog's address, origin only: `https://blog.example.com` | +| Webhook URL | Where Wonky sends submissions: `https://blog.example.com/api/wonky/webhook`. It must be `https` on port 443 and reachable from the internet. Wonky doesn't follow redirects | +| Terms URL | Optional. Your contributor terms. When set, contributors must agree to them before they start | +| Template | Optional. One of your own Wonky Write documents. New stories start as a copy of it (without its comments), so you can include guidelines and a suggested structure | +| Submission fields | The title is always asked for. Turn on *Summary*, *Tags* (optionally from a fixed list), *Cover image*, *Author bio* and *Note to the moderators*, each optional or required | +| Moderators | The email addresses of your moderators' Wonky accounts (up to 20). A moderator without an account gets access once they sign up with that email | + +When you create the publication, Wonky shows the **signing secret** (`whsec_…`) **once**. Copy +it into your server's secret store now. Then choose **Create API key** and store the key +(`wpk_…`) as well; it's also shown only once. + +The publication page also shows the **publication id** (`pub_…`) and the **contributor link**. +Neither is a secret. + +## 2. Verify your site + +Verification shows contributors a ✓ next to your site's name, so they know the publication is +really yours. Without it, Wonky shows your webhook's host instead of your site and a warning. + +Serve this file at `https://blog.example.com/.well-known/wonky-publications.json`: + +```json +{ "publications": ["pub_7Hk2xQ9mR4tLwP0aZc3VbN"] } +``` + +List every publication id that belongs to the site. Then choose **Verify** on the publication +page. Changing the site URL later removes the verification; verify again. + +## 3. Add the "Write for us" link + +```html +Write for us +``` + +You can add `&ref=` (up to 64 characters: letters, digits, `-` and `_`) to tell +submissions apart, for example by a call for posts: `…&ref=cfp-2026`. Wonky passes `ref` back +in every webhook. Treat it as a hint from the link, not as proof of anything. + +The link always works the same way, so it can sit on a static page. A contributor who already +has an unsubmitted story for your blog is offered to continue it. + +## 4. Receive webhooks + +Wonky sends `POST` requests with a JSON body to your webhook URL, signed per the +[Standard Webhooks](https://www.standardwebhooks.com/) specification. There are libraries for +most languages (`standardwebhooks` on npm and PyPI, and others); you can also check the +signature yourself in a few lines (below). + +### 4.1 Headers + +| Header | Value | +|--------|-------| +| `webhook-id` | `msg_…`, unique per event. A retry of the same event uses the **same id** | +| `webhook-timestamp` | Unix time in seconds when this attempt was sent | +| `webhook-signature` | `v1,`. During a secret rotation there are two, separated by a space; accept the request if either matches | +| `content-type` | `application/json` | + +### 4.2 Check the signature + +1. Take the secret without its `whsec_` prefix and base64-decode it: that's the HMAC key. +2. Build the signed content: `..`. Use the raw + body exactly as received, before any JSON parsing. +3. Compute HMAC-SHA256 with the key, base64-encode it, and compare it with each `v1,` signature + in the header using a constant-time comparison. +4. Reject the request if the timestamp is more than 5 minutes away from your clock. +5. Remember the `webhook-id`s you've handled (a day is enough) and ignore repeats. + +**Node.js** + +```js +import crypto from "node:crypto"; + +export function verifyWonkyWebhook(rawBody, headers, secret) { + const id = headers["webhook-id"]; + const timestamp = headers["webhook-timestamp"]; + const signatures = (headers["webhook-signature"] ?? "").split(" "); + if (!id || !timestamp) return false; + if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false; + const key = Buffer.from(secret.replace(/^whsec_/, ""), "base64"); + const expected = crypto + .createHmac("sha256", key) + .update(`${id}.${timestamp}.${rawBody}`) + .digest(); + return signatures.some((s) => { + const [version, value] = s.split(","); + if (version !== "v1" || !value) return false; + const given = Buffer.from(value, "base64"); + return given.length === expected.length && crypto.timingSafeEqual(given, expected); + }); +} +``` + +**Python** + +```python +import base64, hashlib, hmac, time + +def verify_wonky_webhook(raw_body: bytes, headers, secret: str) -> bool: + msg_id = headers.get("webhook-id") + timestamp = headers.get("webhook-timestamp") + if not msg_id or not timestamp or abs(time.time() - int(timestamp)) > 300: + return False + key = base64.b64decode(secret.removeprefix("whsec_")) + signed = f"{msg_id}.{timestamp}.".encode() + raw_body + expected = base64.b64encode(hmac.new(key, signed, hashlib.sha256).digest()).decode() + return any( + s.startswith("v1,") and hmac.compare_digest(s[3:], expected) + for s in headers.get("webhook-signature", "").split(" ") + ) +``` + +**Dart** + +```dart +import 'dart:convert'; +import 'package:crypto/crypto.dart'; + +bool verifyWonkyWebhook(String rawBody, Map headers, String secret) { + final id = headers['webhook-id']; + final timestamp = int.tryParse(headers['webhook-timestamp'] ?? ''); + if (id == null || timestamp == null) return false; + final now = DateTime.now().millisecondsSinceEpoch ~/ 1000; + if ((now - timestamp).abs() > 300) return false; + final key = base64.decode(secret.substring('whsec_'.length)); + final expected = Hmac(sha256, key).convert(utf8.encode('$id.$timestamp.$rawBody')).bytes; + for (final s in (headers['webhook-signature'] ?? '').split(' ')) { + if (!s.startsWith('v1,')) continue; + final given = base64.decode(s.substring(3)); + if (given.length != expected.length) continue; + var diff = 0; + for (var i = 0; i < given.length; i++) { + diff |= given[i] ^ expected[i]; + } + if (diff == 0) return true; + } + return false; +} +``` + +**Test vector.** With the secret `whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw`, the id +`msg_2KWPBgLlAfxdpx2AI54pPJ85f4W`, the timestamp `1674087231` and this body (one line, no +trailing newline): + +``` +{"type":"publication.ping","createdAt":"2023-01-19T00:13:51Z","publicationId":"pub_7Hk2xQ9mR4tLwP0aZc3VbN"} +``` + +the signature is `v1,4+meITVYE+3sv8v+3Jl0/CXDGdczBRF7SOHoZxKwobQ=` (skip the timestamp check +when you test with it). + +### 4.3 Answer quickly + +Answer with any `2xx` status within **10 seconds**; the answer's body is ignored. Store the event +and do slow work (downloading images, notifying moderators) afterwards. + +Anything else (an error status, a timeout, a redirect, a connection error) counts as not +delivered. Wonky retries with the same `webhook-id` after about 1 minute, 5 minutes, 30 minutes, +2 hours, 6 hours and 12 hours, then gives up. While it retries, the contributor sees +*Submitting…*; if every attempt fails, they're told that your blog couldn't receive the story. +You can see each attempt, and resend it, under **Deliveries** on the publication page. + +Events can arrive more than once and out of order. Use `webhook-id` to ignore repeats and +`sequence` (below) to ignore an older submit that arrives after a newer one. + +### 4.4 Events + +Every body has these fields: + +```json +{ + "type": "submission.submitted", + "createdAt": "2026-10-20T09:14:03Z", + "publicationId": "pub_7Hk2xQ9mR4tLwP0aZc3VbN" +} +``` + +| `type` | When | Other fields | +|--------|------|--------------| +| `publication.ping` | You choose *Send test*, or save a new webhook URL | — | +| `submission.submitted` | Every Submit, Resubmit and Submit update | `submission`, `sequence`, `revision`, `fields`, `markdown`, `assets`, `submittedBy` | +| `submission.withdrawn` | The contributor withdraws the story, or moves the document to the trash | `submission`, `reason`: `author` or `trashed` | +| `submission.disconnected` | The contributor disconnects the document from your blog. No more updates will come for this submission | `submission` | +| `comment.created` | Someone replies in the document's thread of your blog's messages (§6.2) | `submission`, `comment` | + +Ignore types you don't know; new ones may be added. + +### 4.5 `submission.submitted` + +```json +{ + "type": "submission.submitted", + "createdAt": "2026-10-20T09:14:03Z", + "publicationId": "pub_7Hk2xQ9mR4tLwP0aZc3VbN", + "submission": { + "id": "sub_0192a3b4-5c6d-7e8f-9012-3456789abcde", + "ref": "cfp-2026", + "status": "inReview", + "documentUrl": "https://wonky.work/write/d/0192a3b4-0000-7000-8000-000000000001" + }, + "sequence": 2, + "revision": 418, + "fields": { + "title": "How we sped up our CI three times", + "summary": "A short look at caching, sharding and one weird flag.", + "tags": ["dart", "ci"], + "coverImage": "ast_0192a3b4-1111-7000-8000-000000000002", + "authorBio": null, + "note": "Fixed the code samples, thanks!" + }, + "markdown": "# How we sped up our CI three times\n\n…\n\n![Build times](https://wonky.work/api/pub/v1/assets/ast_0192a3b4-1111-7000-8000-000000000002)\n", + "assets": [ + { + "id": "ast_0192a3b4-1111-7000-8000-000000000002", + "name": "build-times.png", + "type": "image/png", + "bytes": 48213, + "url": "https://wonky.work/api/pub/v1/assets/ast_0192a3b4-1111-7000-8000-000000000002" + } + ], + "submittedBy": { "name": "Anna Berg", "wonkyUserId": "0191f0e2-aaaa-7000-8000-000000000003" } +} +``` + +- `submission.id` is stable for the story: use it as the key of your queue entry and update the + entry on every new submit. +- `sequence` counts the submits of this submission (1, 2, …). Ignore a webhook whose `sequence` + is lower than the one you have. +- `revision` is the document revision that was sent. When you publish, publish the content of the + submit you reviewed; the contributor may keep editing in the meantime. +- `fields` holds the fields you turned on; fields you didn't turn on are `null` (`tags` is then + `[]`). `coverImage` is the id of one of the `assets`. +- `markdown` is CommonMark with GitHub tables and task lists. Open suggestions in the document are + sent as the original text; comments are never included. There is no front matter: the title + and the other fields are in `fields` (the Markdown usually starts with the title as a heading, + because that's how people write). +- Images uploaded to Wonky appear as asset URLs (§5). Images that were already on the web keep + their own `https://` URLs. +- `submittedBy.name` is the display name of the person who pressed Submit, which may be a + co-author. Ask for the byline in a field if you need one. Wonky never sends email addresses. + `wonkyUserId` is stable per Wonky account; use it to block a user (§7.6). +- `documentUrl` opens the story in Wonky. Your moderators can open it once Wonky has granted them + access (§6.1). + +### 4.6 `comment.created` + +```json +{ + "type": "comment.created", + "createdAt": "2026-10-21T08:02:11Z", + "publicationId": "pub_7Hk2xQ9mR4tLwP0aZc3VbN", + "submission": { "id": "sub_…", "ref": "cfp-2026", "status": "changesRequested", + "documentUrl": "https://wonky.work/write/d/…" }, + "comment": { + "id": "0192a3b4-2222-7000-8000-000000000004", + "body": "Done — I split the second section in two.", + "author": { "name": "Anna Berg", "wonkyUserId": "0191f0e2-…", "isModerator": false } + } +} +``` + +`body` is Markdown (bold, italic, code and links). + +## 5. Download the images + +Asset URLs need your API key: + +```bash +curl -H "Authorization: Bearer $WONKY_API_KEY" -o build-times.png \ + https://wonky.work/api/pub/v1/assets/ast_0192a3b4-1111-7000-8000-000000000002 +``` + +Download them right after you receive the webhook and host them yourself. An asset stays +available while the image exists in Wonky, but the contributor can delete it later. Only images +that were part of one of your submissions can be downloaded. + +## 6. Moderate + +### 6.1 In Wonky + +When a story is submitted for the first time, each moderator gets **comment access** to the +document. They can read it, leave comments and suggest edits; they can't change the text +directly. The access ends when the story is withdrawn, declined or disconnected. Stories you have +published keep it, so you can review updates the same way. The contributor (or a co-author) can +also remove a moderator's access in the document's *Share* dialog; it comes back with the next +submit. A moderator who creates their Wonky account later gets access with the next submit or +status change. + +Moderators don't get an email when they receive access. Link to `documentUrl` from your review +queue (*Open in Wonky*). + +### 6.2 Messages back to the contributor + +Your status calls and messages (§7.4, §7.5) appear in the document in one comment thread under +your publication's name, and every editor of the document is notified. When someone replies in +that thread, you receive `comment.created`. Comments elsewhere in the document stay in Wonky, but +your moderators can read them there. + +### 6.3 Status flow + +``` + draft ──Submit──▶ inReview ──you──▶ changesRequested ──Resubmit──▶ inReview + │ + ├──you──▶ declined (final for this submission) + └──you──▶ published ──Submit update──▶ inReview + inReview / changesRequested ──contributor withdraws──▶ withdrawn ──Submit──▶ inReview +``` + +Wonky sets `inReview` itself when you accept a `submission.submitted` webhook. You set the rest: + +| From | You may set | +|------|-------------| +| `inReview` | `inReview`, `changesRequested`, `declined`, `published` | +| `changesRequested` | `inReview`, `changesRequested`, `declined`, `published` | +| `published` | `published` (for example to change the post URL) | +| `draft`, `declined`, `withdrawn` | nothing | + +## 7. API reference + +Base URL: `https://wonky.work/api/pub/v1/` + +- **Authentication**: `Authorization: Bearer wpk_…` on every request. A key only reaches its own + publication's submissions. +- **Bodies**: JSON, at most 1 MB. +- **Rate limit**: 120 requests per minute per key. Over it you get `429` with a `retry-after` + header in seconds. +- **Errors**: a status code and `{ "error": "", "message": "" }`. + +| Status | `error` | Meaning | +|--------|---------|---------| +| 400 | `invalidArgument` | A field is missing or wrong; `message` says which | +| 401 | `unauthorized` | No key, a malformed key, or a key that was rotated or deleted | +| 404 | `notFound` | No such submission or asset for this publication | +| 409 | `invalidTransition` | The status change isn't allowed from the current status (§6.3) | +| 410 | `gone` | The submission was withdrawn or disconnected | +| 413 | `tooLarge` | The body is larger than 1 MB | +| 429 | `rateLimited` | Too many requests | + +### 7.1 List submissions + +`GET submissions?status=inReview&after=&limit=50` + +`status` is optional (`draft`, `inReview`, `changesRequested`, `declined`, `published`, +`withdrawn`); `limit` is 1–100 (default 50). The newest change comes first. Pass the answer's +`next` as `after` to get the next page; `next` is `null` on the last page. + +```json +{ + "submissions": [ + { + "id": "sub_…", "ref": "cfp-2026", "status": "inReview", + "documentUrl": "https://wonky.work/write/d/…", + "title": "How we sped up our CI three times", + "sequence": 2, "revision": 418, + "submittedAt": "2026-10-20T09:14:03Z", "updatedAt": "2026-10-20T09:14:03Z", + "publicUrl": null + } + ], + "next": null +} +``` + +Use it to catch up after downtime. It isn't needed in normal operation. + +### 7.2 Get a submission + +`GET submissions/{id}` returns one entry as in the list, plus `fields`. + +### 7.3 Get a submitted version + +`GET submissions/{id}/content?sequence=2` + +Returns the `submission.submitted` body of that submit (without `webhook-*` headers). Without +`sequence`, the latest submit. Use it when you missed a webhook. + +### 7.4 Set the status + +`POST submissions/{id}/status` + +```json +{ + "status": "changesRequested", + "message": "Thanks! Could you add a short intro and shorten the second section?" +} +``` + +| Field | | +|-------|--| +| `status` | `inReview`, `changesRequested`, `declined` or `published` (§6.3) | +| `message` | Optional Markdown, up to 10,000 characters. Shown to the contributor in the document | +| `publicUrl` | Required with `published`: the `https://` URL of the post. The contributor gets a *View post* link | + +Answers with the submission as in §7.2. + +```bash +curl -X POST https://wonky.work/api/pub/v1/submissions/sub_…/status \ + -H "Authorization: Bearer $WONKY_API_KEY" -H "content-type: application/json" \ + -d '{"status":"published","publicUrl":"https://blog.example.com/posts/faster-ci","message":"Live now 🎉"}' +``` + +### 7.5 Send a message + +`POST submissions/{id}/messages` with `{ "body": "Markdown, up to 10,000 characters" }` posts a +message without changing the status, for example "Thanks, we'll look at it this week." Answers +`{ "ok": true }`. + +### 7.6 Block a user + +`POST blocks` with `{ "wonkyUserId": "0191f0e2-…" }` stops that Wonky account from starting or +submitting stories for your publication. `DELETE blocks/{wonkyUserId}` lifts the block. Both +answer `{ "ok": true }`. + +### 7.7 Download an asset + +`GET assets/{assetId}` returns the image bytes with its content type (§5). + +## 8. Rotate secrets + +- **Signing secret**: *Rotate signing secret* shows the new secret once. For the next 24 hours + every webhook carries two signatures, one per secret, so you can deploy the new secret without + missing deliveries. +- **API key**: *Rotate API key* shows a new key once, and the old key stops working at once. + +## 9. Test your setup + +1. Choose **Send test** on the publication page. Your receiver gets a `publication.ping` and the + page shows your server's answer. +2. Open your contributor link with a second Wonky account, write a few lines, and press + **Submit**. Check your queue, then call the status API with `changesRequested` and a message, + and watch it appear in the document. +3. **Deliveries** lists the last 50 webhooks with your server's status code and any error, and + can resend one. + +## 10. Checklist + +- [ ] Publication created; signing secret and API key stored server-side. +- [ ] `/.well-known/wonky-publications.json` served and **Verify** passed. +- [ ] *Write for us* link on the blog. +- [ ] Webhook receiver: raw body kept, signature and timestamp checked, `webhook-id` deduplicated, + queue entry updated by `submission.id`, older `sequence` ignored, `2xx` within 10 seconds. +- [ ] Images downloaded with the API key and hosted by you. +- [ ] Moderation tool links to `documentUrl` and calls the status API for *Request changes*, + *Decline* and *Publish* (with the post URL). +- [ ] Moderators' emails added to the publication. + +## 11. Troubleshooting + +| Problem | What to check | +|---------|---------------| +| *Send test* says the address is blocked | The webhook host must resolve to a public address; `localhost`, private networks and non-443 ports are refused. Use a public tunnel while you develop | +| Every delivery fails with a 3xx status | Wonky doesn't follow redirects. Use the final URL (watch for `http`→`https` and trailing-slash redirects) | +| Signatures never match | Sign the **raw** body: frameworks that parse JSON first and serialize it again change the bytes. Decode the secret from base64 after removing `whsec_` | +| Valid signatures are rejected as too old | Your server's clock is off; sync it (NTP) | +| `401 unauthorized` from the API | The key was rotated, or the header isn't exactly `Authorization: Bearer wpk_…` | +| `409 invalidTransition` | The submission isn't in a status you can change (§6.3), for example because the contributor withdrew it | +| Contributors see "not verified" | Serve `/.well-known/wonky-publications.json` on the site URL's host and choose **Verify** again | diff --git a/packages/wonky_app/lib/l10n/wonky_app_en.arb b/packages/wonky_app/lib/l10n/wonky_app_en.arb index 47b5921d..3c368b21 100644 --- a/packages/wonky_app/lib/l10n/wonky_app_en.arb +++ b/packages/wonky_app/lib/l10n/wonky_app_en.arb @@ -3060,5 +3060,152 @@ "type": "String" } } - } + }, + "settingsPublications": "Publications", + "@settingsPublications": {"description": "Wonky Work settings section: blogs that take stories from Wonky Write (specs/18)."}, + "pubSectionHint": "Let people write for your blog in Wonky Write and send stories to your review queue with one button.", + "pubNew": "New publication", + "pubNewHint": "Wonky sends submitted stories to your webhook. You get the signing secret once, after you create the publication.", + "pubEdit": "Edit “{name}”", + "@pubEdit": {"placeholders": {"name": {"type": "String"}}}, + "pubEditButton": "Edit…", + "pubGuide": "Developer guide", + "@pubGuide": {"description": "Opens the integration guide for blog owners."}, + "pubEmpty": "You have no publications yet.", + "pubName": "Name", + "pubSiteUrl": "Site URL", + "pubWebhookUrl": "Webhook URL", + "pubTermsUrl": "Contributor terms URL (optional)", + "pubTemplate": "Template document (optional)", + "pubTemplateHint": "Paste a link to one of your Wonky Write documents", + "pubTemplateInvalid": "Paste the link of a Wonky Write document.", + "pubRequired": "Required.", + "pubHttpsOnly": "Use an https:// address.", + "pubFieldSummary": "Summary", + "pubFieldTags": "Tags", + "pubAllowedTags": "Allowed tags (optional)", + "pubAllowedTagsHint": "Comma separated; empty allows any tag", + "pubFieldCover": "Cover image", + "pubFieldBio": "Author bio", + "pubFieldNote": "Note to the moderators", + "pubFieldOff": "Not asked", + "pubFieldOptional": "Optional", + "pubFieldRequired": "Required", + "pubEnabled": "Accept new stories", + "pubHostVerified": "{host} ✓", + "@pubHostVerified": {"placeholders": {"host": {"type": "String"}}}, + "pubHostUnverified": "{host} (not verified)", + "@pubHostUnverified": {"placeholders": {"host": {"type": "String"}}}, + "pubDisabled": "Not accepting stories", + "pubOpenCount": "{count, plural, =0{No stories in review} =1{1 story in review} other{{count} stories in review}}", + "@pubOpenCount": {"placeholders": {"count": {"type": "int"}}}, + "pubManage": "Manage", + "pubHide": "Hide", + "pubContributorLink": "Contributor link (put it behind “Write for us”)", + "pubId": "Publication id", + "pubCopy": "Copy", + "pubCopied": "Copied", + "pubDelete": "Delete", + "pubModerators": "Moderators", + "pubModeratorsHint": "Moderators get comment access to stories when they are submitted. Enter the email addresses of their Wonky accounts, one per line.", + "pubModeratorEmails": "Email addresses", + "pubModeratorsButton": "{count, plural, =0{Add moderators…} =1{1 moderator…} other{{count} moderators…}}", + "@pubModeratorsButton": {"placeholders": {"count": {"type": "int"}}}, + "pubVerification": "Verification", + "pubVerifyHint": "Serve this at https://{host}/.well-known/wonky-publications.json, then verify. Until then contributors see your webhook's host and a warning.", + "@pubVerifyHint": {"placeholders": {"host": {"type": "String"}}}, + "pubVerifiedAt": "{host} verified {date}", + "@pubVerifiedAt": {"placeholders": {"host": {"type": "String"}, "date": {"type": "String"}}}, + "pubVerify": "Verify", + "pubVerified": "{host} is verified", + "@pubVerified": {"placeholders": {"host": {"type": "String"}}}, + "pubVerifyFailed": "Not verified", + "pubCredentials": "Signing secret and API key", + "pubSecretHint": "Webhooks are signed with the signing secret. Your server calls the publication API with the API key.", + "pubRotationActive": "The previous signing secret still signs until {date}.", + "@pubRotationActive": {"placeholders": {"date": {"type": "String"}}}, + "pubRotateSecret": "Rotate signing secret", + "pubRotateSecretBody": "You get a new secret. For 24 hours, webhooks carry signatures of the old and the new secret.", + "pubRotate": "Rotate", + "pubCreateApiKey": "Create API key", + "pubRotateApiKey": "Rotate API key", + "pubRotateApiKeyLast4": "Rotate API key (…{last4})", + "@pubRotateApiKeyLast4": {"placeholders": {"last4": {"type": "String"}}}, + "pubRotateApiKeyBody": "The current key stops working at once.", + "pubApiKey": "API key", + "pubSigningSecret": "Signing secret", + "pubSecretOnce": "Copy the {what} now. It isn't shown again.", + "@pubSecretOnce": {"placeholders": {"what": {"type": "String"}}}, + "pubSecretSaved": "I've stored it", + "pubDeliveries": "Deliveries", + "pubSendTest": "Send test", + "pubTestOk": "Your webhook accepted the test.", + "pubTestFailed": "Your webhook didn't accept the test", + "pubNoDeliveries": "No webhooks sent yet.", + "pubDelivered": "Delivered (HTTP {status_code})", + "@pubDelivered": {"placeholders": {"status_code": {"type": "int"}}}, + "pubDeliveryFailed": "Failed: {error}", + "@pubDeliveryFailed": {"placeholders": {"error": {"type": "String"}}}, + "pubDeliveryQueued": "Queued", + "pubDeliveryRetrying": "{error} · next try {date}", + "@pubDeliveryRetrying": {"placeholders": {"error": {"type": "String"}, "date": {"type": "String"}}}, + "pubResend": "Resend", + "pubDeleteTitle": "Delete “{name}”?", + "@pubDeleteTitle": {"placeholders": {"name": {"type": "String"}}}, + "pubDeleteBody": "Contributors' documents stay in their drives, but they can't submit them anymore, and moderators lose access. Your blog gets no webhook about it.", + "notifySubmissions": "Stories for publications", + "@notifySubmissions": {"description": "Notification settings: messages and status changes from blogs."}, + "notifySubmissionsHint": "Status changes and messages from blogs you write for", + "notifSubmissionChanges": "{publication} asked for changes to “{what}”", + "@notifSubmissionChanges": {"placeholders": {"publication": {"type": "String"}, "what": {"type": "String"}}}, + "notifSubmissionDeclined": "{publication} declined “{what}”", + "@notifSubmissionDeclined": {"placeholders": {"publication": {"type": "String"}, "what": {"type": "String"}}}, + "notifSubmissionPublished": "{publication} published “{what}”", + "@notifSubmissionPublished": {"placeholders": {"publication": {"type": "String"}, "what": {"type": "String"}}}, + "notifSubmissionInReview": "{publication} is reviewing “{what}”", + "@notifSubmissionInReview": {"placeholders": {"publication": {"type": "String"}, "what": {"type": "String"}}}, + "notifSubmissionMessage": "{publication} sent a message about “{what}”", + "@notifSubmissionMessage": {"placeholders": {"publication": {"type": "String"}, "what": {"type": "String"}}}, + "notifSubmissionFailed": "{publication} couldn't receive “{what}”", + "@notifSubmissionFailed": {"placeholders": {"publication": {"type": "String"}, "what": {"type": "String"}}}, + "shareModerator": "Moderator · {publication}", + "@shareModerator": {"placeholders": {"publication": {"type": "String"}}}, + "activitySubmitted": "{who} submitted it to {publication}", + "@activitySubmitted": {"placeholders": {"who": {"type": "String"}, "publication": {"type": "String"}}}, + "activitySubmissionWithdrawn": "{who} withdrew it from {publication}", + "@activitySubmissionWithdrawn": {"placeholders": {"who": {"type": "String"}, "publication": {"type": "String"}}}, + "activitySubmissionDisconnected": "{who} disconnected it from {publication}", + "@activitySubmissionDisconnected": {"placeholders": {"who": {"type": "String"}, "publication": {"type": "String"}}}, + "activitySubmissionReconnected": "{who} connected it to {publication} again", + "@activitySubmissionReconnected": {"placeholders": {"who": {"type": "String"}, "publication": {"type": "String"}}}, + "activitySubmissionStatus": "{publication}: {status}", + "@activitySubmissionStatus": {"placeholders": {"publication": {"type": "String"}, "status": {"type": "String"}}}, + "submissionStatusDraft": "Draft", + "@submissionStatusDraft": {"description": "Status of a story for a publication."}, + "submissionStatusInReview": "In review", + "submissionStatusChangesRequested": "Changes requested", + "submissionStatusDeclined": "Declined", + "submissionStatusPublished": "Published", + "submissionStatusWithdrawn": "Withdrawn", + "pubStartTitle": "Write for {name}", + "@pubStartTitle": {"description": "Consent dialog of a contributor link (specs/18 §3).", "placeholders": {"name": {"type": "String"}}}, + "pubStartHostVerified": "{host} ✓", + "@pubStartHostVerified": {"placeholders": {"host": {"type": "String"}}}, + "pubStartHostUnverified": "Wonky hasn't verified that this publication belongs to {site}. Your story is sent to {webhook}.", + "@pubStartHostUnverified": {"placeholders": {"site": {"type": "String"}, "webhook": {"type": "String"}}}, + "pubStartConsent": "You'll write in your own Wonky document. When you press Submit, {name} receives the text and images of the document, the fields you fill in and your display name, and its moderators can read and comment on the document.", + "@pubStartConsent": {"placeholders": {"name": {"type": "String"}}}, + "pubStartWhich": "Story", + "pubStartContinue": "Continue “{name}”", + "@pubStartContinue": {"placeholders": {"name": {"type": "String"}}}, + "pubStartNew": "Start a new story", + "pubStartTerms": "I agree to {name}'s contributor terms ({url})", + "@pubStartTerms": {"placeholders": {"name": {"type": "String"}, "url": {"type": "String"}}}, + "pubStartTermsRequired": "Agree to {name}'s contributor terms to start.", + "@pubStartTermsRequired": {"placeholders": {"name": {"type": "String"}}}, + "pubStartButton": "Start writing", + "pubStartBlocked": "{name} isn't accepting stories from you.", + "@pubStartBlocked": {"placeholders": {"name": {"type": "String"}}}, + "pubStartClosed": "{name} isn't accepting stories right now.", + "@pubStartClosed": {"placeholders": {"name": {"type": "String"}}} } diff --git a/packages/wonky_app/lib/l10n/wonky_app_en_XA.arb b/packages/wonky_app/lib/l10n/wonky_app_en_XA.arb index 7a144d50..05033ee4 100644 --- a/packages/wonky_app/lib/l10n/wonky_app_en_XA.arb +++ b/packages/wonky_app/lib/l10n/wonky_app_en_XA.arb @@ -1316,5 +1316,112 @@ "boardReviewSpecs": "[Šþéçš on]", "boardReviewRisks": "[Ŕîšķš on]", "boardReviewUnrelated": "[Çĥåñĝéš ţĥé ţåšķ ðîðñ'ţ åšķ ƒöŕ one two th]", - "boardReviewedSha": "[Ŕéṽîéŵéð åţ {sha} one]" + "boardReviewedSha": "[Ŕéṽîéŵéð åţ {sha} one]", + "settingsPublications": "[Þûƀļîçåţîöñš one t]", + "pubSectionHint": "[Ļéţ þéöþļé ŵŕîţé ƒöŕ ýöûŕ ƀļöĝ îñ Ŵöñķý Ŵŕîţé åñð šéñð šţöŕîéš ţö ýöûŕ ŕéṽîéŵ ǫûéûé ŵîţĥ öñé ƀûţţöñ. one two three four five six s]", + "pubNew": "[Ñéŵ þûƀļîçåţîöñ one t]", + "pubNewHint": "[Ŵöñķý šéñðš šûƀɱîţţéð šţöŕîéš ţö ýöûŕ ŵéƀĥööķ. Ýöû ĝéţ ţĥé šîĝñîñĝ šéçŕéţ öñçé, åƒţéŕ ýöû çŕéåţé ţĥé þûƀļîçåţîöñ. one two three four five six seven]", + "pubEdit": "[Éðîţ “{name}” one]", + "pubEditButton": "[Éðîţ… on]", + "pubGuide": "[Ðéṽéļöþéŕ ĝûîðé one t]", + "pubEmpty": "[Ýöû ĥåṽé ñö þûƀļîçåţîöñš ýéţ. one two t]", + "pubName": "[Ñåɱé on]", + "pubSiteUrl": "[Šîţé ÛŔĻ one]", + "pubWebhookUrl": "[Ŵéƀĥööķ ÛŔĻ one]", + "pubTermsUrl": "[Çöñţŕîƀûţöŕ ţéŕɱš ÛŔĻ (öþţîöñåļ) one two thr]", + "pubTemplate": "[Ţéɱþļåţé ðöçûɱéñţ (öþţîöñåļ) one two th]", + "pubTemplateHint": "[Þåšţé å ļîñķ ţö öñé öƒ ýöûŕ Ŵöñķý Ŵŕîţé ðöçûɱéñţš one two three]", + "pubTemplateInvalid": "[Þåšţé ţĥé ļîñķ öƒ å Ŵöñķý Ŵŕîţé ðöçûɱéñţ. one two thre]", + "pubRequired": "[Ŕéǫûîŕéð. one]", + "pubHttpsOnly": "[Ûšé åñ ĥţţþš:// åððŕéšš. one two]", + "pubFieldSummary": "[Šûɱɱåŕý one]", + "pubFieldTags": "[Ţåĝš on]", + "pubAllowedTags": "[Åļļöŵéð ţåĝš (öþţîöñåļ) one two]", + "pubAllowedTagsHint": "[Çöɱɱå šéþåŕåţéð; éɱþţý åļļöŵš åñý ţåĝ one two thre]", + "pubFieldCover": "[Çöṽéŕ îɱåĝé one]", + "pubFieldBio": "[Åûţĥöŕ ƀîö one]", + "pubFieldNote": "[Ñöţé ţö ţĥé ɱöðéŕåţöŕš one two]", + "pubFieldOff": "[Ñöţ åšķéð one]", + "pubFieldOptional": "[Öþţîöñåļ one]", + "pubFieldRequired": "[Ŕéǫûîŕéð one]", + "pubEnabled": "[Åççéþţ ñéŵ šţöŕîéš one tw]", + "pubHostVerified": "[{host} ✓ o]", + "pubHostUnverified": "[{host} (ñöţ ṽéŕîƒîéð) one t]", + "pubDisabled": "[Ñöţ åççéþţîñĝ šţöŕîéš one two]", + "pubOpenCount": "[{count, plural, =0{Ñö šţöŕîéš îñ ŕéṽîéŵ} =1{1 šţöŕý îñ ŕéṽîéŵ} other{{count} šţöŕîéš îñ ŕéṽîéŵ}} one two three fou]", + "pubManage": "[Ṁåñåĝé one]", + "pubHide": "[Ĥîðé on]", + "pubContributorLink": "[Çöñţŕîƀûţöŕ ļîñķ (þûţ îţ ƀéĥîñð “Ŵŕîţé ƒöŕ ûš”) one two three]", + "pubId": "[Þûƀļîçåţîöñ îð one t]", + "pubCopy": "[Çöþý on]", + "pubCopied": "[Çöþîéð one]", + "pubDelete": "[Ðéļéţé one]", + "pubModerators": "[Ṁöðéŕåţöŕš one]", + "pubModeratorsHint": "[Ṁöðéŕåţöŕš ĝéţ çöɱɱéñţ åççéšš ţö šţöŕîéš ŵĥéñ ţĥéý åŕé šûƀɱîţţéð. Éñţéŕ ţĥé éɱåîļ åððŕéššéš öƒ ţĥéîŕ Ŵöñķý åççöûñţš, öñé þéŕ ļîñé. one two three four five six seven eight]", + "pubModeratorEmails": "[Éɱåîļ åððŕéššéš one t]", + "pubModeratorsButton": "[{count, plural, =0{Åðð ɱöðéŕåţöŕš…} =1{1 ɱöðéŕåţöŕ…} other{{count} ɱöðéŕåţöŕš…}} one two three]", + "pubVerification": "[Ṽéŕîƒîçåţîöñ one t]", + "pubVerifyHint": "[Šéŕṽé ţĥîš åţ ĥţţþš://{host}/.ŵéļļ-ķñöŵñ/ŵöñķý-þûƀļîçåţîöñš.ĵšöñ, ţĥéñ ṽéŕîƒý. Ûñţîļ ţĥéñ çöñţŕîƀûţöŕš šéé ýöûŕ ŵéƀĥööķ'š ĥöšţ åñð å ŵåŕñîñĝ. one two three four five six seven eight ni]", + "pubVerifiedAt": "[{host} ṽéŕîƒîéð {date} one]", + "pubVerify": "[Ṽéŕîƒý one]", + "pubVerified": "[{host} îš ṽéŕîƒîéð one]", + "pubVerifyFailed": "[Ñöţ ṽéŕîƒîéð one]", + "pubCredentials": "[Šîĝñîñĝ šéçŕéţ åñð ÅÞÎ ķéý one two]", + "pubSecretHint": "[Ŵéƀĥööķš åŕé šîĝñéð ŵîţĥ ţĥé šîĝñîñĝ šéçŕéţ. Ýöûŕ šéŕṽéŕ çåļļš ţĥé þûƀļîçåţîöñ ÅÞÎ ŵîţĥ ţĥé ÅÞÎ ķéý. one two three four five six se]", + "pubRotationActive": "[Ţĥé þŕéṽîöûš šîĝñîñĝ šéçŕéţ šţîļļ šîĝñš ûñţîļ {date}. one two three]", + "pubRotateSecret": "[Ŕöţåţé šîĝñîñĝ šéçŕéţ one two]", + "pubRotateSecretBody": "[Ýöû ĝéţ å ñéŵ šéçŕéţ. Ƒöŕ 24 ĥöûŕš, ŵéƀĥööķš çåŕŕý šîĝñåţûŕéš öƒ ţĥé öļð åñð ţĥé ñéŵ šéçŕéţ. one two three four five six]", + "pubRotate": "[Ŕöţåţé one]", + "pubCreateApiKey": "[Çŕéåţé ÅÞÎ ķéý one t]", + "pubRotateApiKey": "[Ŕöţåţé ÅÞÎ ķéý one t]", + "pubRotateApiKeyLast4": "[Ŕöţåţé ÅÞÎ ķéý (…{last4}) one tw]", + "pubRotateApiKeyBody": "[Ţĥé çûŕŕéñţ ķéý šţöþš ŵöŕķîñĝ åţ öñçé. one two thre]", + "pubApiKey": "[ÅÞÎ ķéý one]", + "pubSigningSecret": "[Šîĝñîñĝ šéçŕéţ one t]", + "pubSecretOnce": "[Çöþý ţĥé {what} ñöŵ. Îţ îšñ'ţ šĥöŵñ åĝåîñ. one two thr]", + "pubSecretSaved": "[Î'ṽé šţöŕéð îţ one t]", + "pubDeliveries": "[Ðéļîṽéŕîéš one]", + "pubSendTest": "[Šéñð ţéšţ one]", + "pubTestOk": "[Ýöûŕ ŵéƀĥööķ åççéþţéð ţĥé ţéšţ. one two th]", + "pubTestFailed": "[Ýöûŕ ŵéƀĥööķ ðîðñ'ţ åççéþţ ţĥé ţéšţ one two thr]", + "pubNoDeliveries": "[Ñö ŵéƀĥööķš šéñţ ýéţ. one two]", + "pubDelivered": "[Ðéļîṽéŕéð (ĤŢŢÞ {status_code}) one tw]", + "pubDeliveryFailed": "[Ƒåîļéð: {error} one]", + "pubDeliveryQueued": "[Ǫûéûéð one]", + "pubDeliveryRetrying": "[{error} · ñéẋţ ţŕý {date} one]", + "pubResend": "[Ŕéšéñð one]", + "pubDeleteTitle": "[Ðéļéţé “{name}”? one]", + "pubDeleteBody": "[Çöñţŕîƀûţöŕš' ðöçûɱéñţš šţåý îñ ţĥéîŕ ðŕîṽéš, ƀûţ ţĥéý çåñ'ţ šûƀɱîţ ţĥéɱ åñýɱöŕé, åñð ɱöðéŕåţöŕš ļöšé åççéšš. Ýöûŕ ƀļöĝ ĝéţš ñö ŵéƀĥööķ åƀöûţ îţ. one two three four five six seven eight nine]", + "notifySubmissions": "[Šţöŕîéš ƒöŕ þûƀļîçåţîöñš one two]", + "notifySubmissionsHint": "[Šţåţûš çĥåñĝéš åñð ɱéššåĝéš ƒŕöɱ ƀļöĝš ýöû ŵŕîţé ƒöŕ one two three fo]", + "notifSubmissionChanges": "[{publication} åšķéð ƒöŕ çĥåñĝéš ţö “{what}” one two]", + "notifSubmissionDeclined": "[{publication} ðéçļîñéð “{what}” one]", + "notifSubmissionPublished": "[{publication} þûƀļîšĥéð “{what}” one]", + "notifSubmissionInReview": "[{publication} îš ŕéṽîéŵîñĝ “{what}” one t]", + "notifSubmissionMessage": "[{publication} šéñţ å ɱéššåĝé åƀöûţ “{what}” one two]", + "notifSubmissionFailed": "[{publication} çöûļðñ'ţ ŕéçéîṽé “{what}” one tw]", + "shareModerator": "[Ṁöðéŕåţöŕ · {publication} one]", + "activitySubmitted": "[{who} šûƀɱîţţéð îţ ţö {publication} one t]", + "activitySubmissionWithdrawn": "[{who} ŵîţĥðŕéŵ îţ ƒŕöɱ {publication} one t]", + "activitySubmissionDisconnected": "[{who} ðîšçöññéçţéð îţ ƒŕöɱ {publication} one two]", + "activitySubmissionReconnected": "[{who} çöññéçţéð îţ ţö {publication} åĝåîñ one two]", + "activitySubmissionStatus": "[{publication}: {status} o]", + "submissionStatusDraft": "[Ðŕåƒţ on]", + "submissionStatusInReview": "[Îñ ŕéṽîéŵ one]", + "submissionStatusChangesRequested": "[Çĥåñĝéš ŕéǫûéšţéð one tw]", + "submissionStatusDeclined": "[Ðéçļîñéð one]", + "submissionStatusPublished": "[Þûƀļîšĥéð one]", + "submissionStatusWithdrawn": "[Ŵîţĥðŕåŵñ one]", + "pubStartTitle": "[Ŵŕîţé ƒöŕ {name} one]", + "pubStartHostVerified": "[{host} ✓ o]", + "pubStartHostUnverified": "[Ŵöñķý ĥåšñ'ţ ṽéŕîƒîéð ţĥåţ ţĥîš þûƀļîçåţîöñ ƀéļöñĝš ţö {site}. Ýöûŕ šţöŕý îš šéñţ ţö {webhook}. one two three four five]", + "pubStartConsent": "[Ýöû'ļļ ŵŕîţé îñ ýöûŕ öŵñ Ŵöñķý ðöçûɱéñţ. Ŵĥéñ ýöû þŕéšš Šûƀɱîţ, {name} ŕéçéîṽéš ţĥé ţéẋţ åñð îɱåĝéš öƒ ţĥé ðöçûɱéñţ, ţĥé ƒîéļðš ýöû ƒîļļ îñ åñð ýöûŕ ðîšþļåý ñåɱé, åñð îţš ɱöðéŕåţöŕš çåñ ŕéåð åñð çöɱɱéñţ öñ ţĥé ðöçûɱéñţ. one two three four five six seven eight nine ten one two three]", + "pubStartWhich": "[Šţöŕý on]", + "pubStartContinue": "[Çöñţîñûé “{name}” one]", + "pubStartNew": "[Šţåŕţ å ñéŵ šţöŕý one t]", + "pubStartTerms": "[Î åĝŕéé ţö {name}'š çöñţŕîƀûţöŕ ţéŕɱš ({url}) one two th]", + "pubStartTermsRequired": "[Åĝŕéé ţö {name}'š çöñţŕîƀûţöŕ ţéŕɱš ţö šţåŕţ. one two thre]", + "pubStartButton": "[Šţåŕţ ŵŕîţîñĝ one t]", + "pubStartBlocked": "[{name} îšñ'ţ åççéþţîñĝ šţöŕîéš ƒŕöɱ ýöû. one two thr]", + "pubStartClosed": "[{name} îšñ'ţ åççéþţîñĝ šţöŕîéš ŕîĝĥţ ñöŵ. one two thr]" } diff --git a/packages/wonky_app/lib/src/activity/activity_feed.dart b/packages/wonky_app/lib/src/activity/activity_feed.dart index 0cc0f27c..382fac12 100644 --- a/packages/wonky_app/lib/src/activity/activity_feed.dart +++ b/packages/wonky_app/lib/src/activity/activity_feed.dart @@ -216,6 +216,7 @@ IconData activityIcon(ActivityType t) => switch (t) { ActivityType.restored => LucideIcons.archiveRestore, ActivityType.exported => LucideIcons.download, ActivityType.uploaded => LucideIcons.upload, + ActivityType.submission => LucideIcons.send, }; class _EventAvatar extends StatelessWidget { diff --git a/packages/wonky_app/lib/src/comments/comment_thread_actions.dart b/packages/wonky_app/lib/src/comments/comment_thread_actions.dart index c653aa03..1921679c 100644 --- a/packages/wonky_app/lib/src/comments/comment_thread_actions.dart +++ b/packages/wonky_app/lib/src/comments/comment_thread_actions.dart @@ -93,7 +93,8 @@ class ThreadComment { return ThreadComment( id: '${cm.id}', authorId: cm.author?.id, - authorName: cm.author?.displayName, + // A publication's messages carry its name (specs/18 §5.2). + authorName: cm.authorLabel ?? cm.author?.displayName, authorColor: cm.author?.avatarColor, authorAvatarUrl: cm.author?.avatarUrl, authorIsAgent: cm.authorKind.name != 'user', diff --git a/packages/wonky_app/lib/src/config/home_scope.dart b/packages/wonky_app/lib/src/config/home_scope.dart index 3dd5707e..9f5b959c 100644 --- a/packages/wonky_app/lib/src/config/home_scope.dart +++ b/packages/wonky_app/lib/src/config/home_scope.dart @@ -194,19 +194,32 @@ class HomeNavSpec { /// The query of `/new?folder=&template=` (suite 03 §2, v2). @immutable class NewItemRequest { - const NewItemRequest({this.folderUuid, this.templateUuid, this.name}); + const NewItemRequest({ + this.folderUuid, + this.templateUuid, + this.name, + this.publicationId, + this.ref, + }); /// Parses the route's query parameters (invalid uuids are ignored). factory NewItemRequest.fromQuery(Map query) => NewItemRequest( folderUuid: _uuid(query['folder']), templateUuid: _uuid(query['template']), name: query['name'], + publicationId: query['publication'], + ref: query['ref'], ); final UuidValue? folderUuid; final UuidValue? templateUuid; final String? name; + /// (M14) A contributor link: start a story for this publication + /// (`pub_…`, specs/18 §3), with the blog's optional [ref]. + final String? publicationId; + final String? ref; + /// The `/new` route of this request (relative to the app's base href): /// `/new?folder=&template=`. String get path { @@ -214,6 +227,8 @@ class NewItemRequest { if (folderUuid != null) 'folder': folderUuid!.uuid, if (templateUuid != null) 'template': templateUuid!.uuid, if (name != null && name!.isNotEmpty) 'name': name!, + 'publication': ?publicationId, + 'ref': ?ref, }; return q.isEmpty ? '/new' diff --git a/packages/wonky_app/lib/src/config/wonky_app_config.dart b/packages/wonky_app/lib/src/config/wonky_app_config.dart index 135b08e5..2c0fb8a2 100644 --- a/packages/wonky_app/lib/src/config/wonky_app_config.dart +++ b/packages/wonky_app/lib/src/config/wonky_app_config.dart @@ -8,6 +8,7 @@ import '../bootstrap/app_urls.dart'; import '../commands/command.dart'; import '../mcp_bridge/ui_tool.dart'; import '../menus/shell_menus.dart'; +import '../publications/start_story.dart'; import '../shell/shell_services.dart'; import '../versions/version_renderer.dart'; import 'home_scope.dart'; @@ -228,12 +229,23 @@ abstract class WonkyAppConfig { /// [createItem]; null (Drive) = the app has no `/new` route. NewItemRouteHandler? get newItemRoute => primaryKind == null ? null - : (context, services, request) => createItem( - services, - parentUuid: request.folderUuid, - templateUuid: request.templateUuid, - name: request.name, - ); + : (context, services, request) => + // A contributor link starts a story (Write, specs/18 §3). + request.publicationId != null && + primaryKind == DriveItemKind.document && + services.repositories.hasPublications + ? startPublicationStory( + context, + services, + request.publicationId!, + ref: request.ref, + ) + : createItem( + services, + parentUuid: request.folderUuid, + templateUuid: request.templateUuid, + name: request.name, + ); /// Handles `/import?file=` (*Open with*, Drive 02 §7.2); /// null = the app has no import route (Drive, Slides). Write and Sheets diff --git a/packages/wonky_app/lib/src/l10n/wonky_app_localizations.dart b/packages/wonky_app/lib/src/l10n/wonky_app_localizations.dart index 54345271..350f7ad7 100644 --- a/packages/wonky_app/lib/src/l10n/wonky_app_localizations.dart +++ b/packages/wonky_app/lib/src/l10n/wonky_app_localizations.dart @@ -7995,6 +7995,648 @@ abstract class WonkyAppLocalizations { /// In en, this message translates to: /// **'Reviewed at {sha}'** String boardReviewedSha(String sha); + + /// Wonky Work settings section: blogs that take stories from Wonky Write (specs/18). + /// + /// In en, this message translates to: + /// **'Publications'** + String get settingsPublications; + + /// No description provided for @pubSectionHint. + /// + /// In en, this message translates to: + /// **'Let people write for your blog in Wonky Write and send stories to your review queue with one button.'** + String get pubSectionHint; + + /// No description provided for @pubNew. + /// + /// In en, this message translates to: + /// **'New publication'** + String get pubNew; + + /// No description provided for @pubNewHint. + /// + /// In en, this message translates to: + /// **'Wonky sends submitted stories to your webhook. You get the signing secret once, after you create the publication.'** + String get pubNewHint; + + /// No description provided for @pubEdit. + /// + /// In en, this message translates to: + /// **'Edit “{name}”'** + String pubEdit(String name); + + /// No description provided for @pubEditButton. + /// + /// In en, this message translates to: + /// **'Edit…'** + String get pubEditButton; + + /// Opens the integration guide for blog owners. + /// + /// In en, this message translates to: + /// **'Developer guide'** + String get pubGuide; + + /// No description provided for @pubEmpty. + /// + /// In en, this message translates to: + /// **'You have no publications yet.'** + String get pubEmpty; + + /// No description provided for @pubName. + /// + /// In en, this message translates to: + /// **'Name'** + String get pubName; + + /// No description provided for @pubSiteUrl. + /// + /// In en, this message translates to: + /// **'Site URL'** + String get pubSiteUrl; + + /// No description provided for @pubWebhookUrl. + /// + /// In en, this message translates to: + /// **'Webhook URL'** + String get pubWebhookUrl; + + /// No description provided for @pubTermsUrl. + /// + /// In en, this message translates to: + /// **'Contributor terms URL (optional)'** + String get pubTermsUrl; + + /// No description provided for @pubTemplate. + /// + /// In en, this message translates to: + /// **'Template document (optional)'** + String get pubTemplate; + + /// No description provided for @pubTemplateHint. + /// + /// In en, this message translates to: + /// **'Paste a link to one of your Wonky Write documents'** + String get pubTemplateHint; + + /// No description provided for @pubTemplateInvalid. + /// + /// In en, this message translates to: + /// **'Paste the link of a Wonky Write document.'** + String get pubTemplateInvalid; + + /// No description provided for @pubRequired. + /// + /// In en, this message translates to: + /// **'Required.'** + String get pubRequired; + + /// No description provided for @pubHttpsOnly. + /// + /// In en, this message translates to: + /// **'Use an https:// address.'** + String get pubHttpsOnly; + + /// No description provided for @pubFieldSummary. + /// + /// In en, this message translates to: + /// **'Summary'** + String get pubFieldSummary; + + /// No description provided for @pubFieldTags. + /// + /// In en, this message translates to: + /// **'Tags'** + String get pubFieldTags; + + /// No description provided for @pubAllowedTags. + /// + /// In en, this message translates to: + /// **'Allowed tags (optional)'** + String get pubAllowedTags; + + /// No description provided for @pubAllowedTagsHint. + /// + /// In en, this message translates to: + /// **'Comma separated; empty allows any tag'** + String get pubAllowedTagsHint; + + /// No description provided for @pubFieldCover. + /// + /// In en, this message translates to: + /// **'Cover image'** + String get pubFieldCover; + + /// No description provided for @pubFieldBio. + /// + /// In en, this message translates to: + /// **'Author bio'** + String get pubFieldBio; + + /// No description provided for @pubFieldNote. + /// + /// In en, this message translates to: + /// **'Note to the moderators'** + String get pubFieldNote; + + /// No description provided for @pubFieldOff. + /// + /// In en, this message translates to: + /// **'Not asked'** + String get pubFieldOff; + + /// No description provided for @pubFieldOptional. + /// + /// In en, this message translates to: + /// **'Optional'** + String get pubFieldOptional; + + /// No description provided for @pubFieldRequired. + /// + /// In en, this message translates to: + /// **'Required'** + String get pubFieldRequired; + + /// No description provided for @pubEnabled. + /// + /// In en, this message translates to: + /// **'Accept new stories'** + String get pubEnabled; + + /// No description provided for @pubHostVerified. + /// + /// In en, this message translates to: + /// **'{host} ✓'** + String pubHostVerified(String host); + + /// No description provided for @pubHostUnverified. + /// + /// In en, this message translates to: + /// **'{host} (not verified)'** + String pubHostUnverified(String host); + + /// No description provided for @pubDisabled. + /// + /// In en, this message translates to: + /// **'Not accepting stories'** + String get pubDisabled; + + /// No description provided for @pubOpenCount. + /// + /// In en, this message translates to: + /// **'{count, plural, =0{No stories in review} =1{1 story in review} other{{count} stories in review}}'** + String pubOpenCount(int count); + + /// No description provided for @pubManage. + /// + /// In en, this message translates to: + /// **'Manage'** + String get pubManage; + + /// No description provided for @pubHide. + /// + /// In en, this message translates to: + /// **'Hide'** + String get pubHide; + + /// No description provided for @pubContributorLink. + /// + /// In en, this message translates to: + /// **'Contributor link (put it behind “Write for us”)'** + String get pubContributorLink; + + /// No description provided for @pubId. + /// + /// In en, this message translates to: + /// **'Publication id'** + String get pubId; + + /// No description provided for @pubCopy. + /// + /// In en, this message translates to: + /// **'Copy'** + String get pubCopy; + + /// No description provided for @pubCopied. + /// + /// In en, this message translates to: + /// **'Copied'** + String get pubCopied; + + /// No description provided for @pubDelete. + /// + /// In en, this message translates to: + /// **'Delete'** + String get pubDelete; + + /// No description provided for @pubModerators. + /// + /// In en, this message translates to: + /// **'Moderators'** + String get pubModerators; + + /// No description provided for @pubModeratorsHint. + /// + /// In en, this message translates to: + /// **'Moderators get comment access to stories when they are submitted. Enter the email addresses of their Wonky accounts, one per line.'** + String get pubModeratorsHint; + + /// No description provided for @pubModeratorEmails. + /// + /// In en, this message translates to: + /// **'Email addresses'** + String get pubModeratorEmails; + + /// No description provided for @pubModeratorsButton. + /// + /// In en, this message translates to: + /// **'{count, plural, =0{Add moderators…} =1{1 moderator…} other{{count} moderators…}}'** + String pubModeratorsButton(int count); + + /// No description provided for @pubVerification. + /// + /// In en, this message translates to: + /// **'Verification'** + String get pubVerification; + + /// No description provided for @pubVerifyHint. + /// + /// In en, this message translates to: + /// **'Serve this at https://{host}/.well-known/wonky-publications.json, then verify. Until then contributors see your webhook\'s host and a warning.'** + String pubVerifyHint(String host); + + /// No description provided for @pubVerifiedAt. + /// + /// In en, this message translates to: + /// **'{host} verified {date}'** + String pubVerifiedAt(String host, String date); + + /// No description provided for @pubVerify. + /// + /// In en, this message translates to: + /// **'Verify'** + String get pubVerify; + + /// No description provided for @pubVerified. + /// + /// In en, this message translates to: + /// **'{host} is verified'** + String pubVerified(String host); + + /// No description provided for @pubVerifyFailed. + /// + /// In en, this message translates to: + /// **'Not verified'** + String get pubVerifyFailed; + + /// No description provided for @pubCredentials. + /// + /// In en, this message translates to: + /// **'Signing secret and API key'** + String get pubCredentials; + + /// No description provided for @pubSecretHint. + /// + /// In en, this message translates to: + /// **'Webhooks are signed with the signing secret. Your server calls the publication API with the API key.'** + String get pubSecretHint; + + /// No description provided for @pubRotationActive. + /// + /// In en, this message translates to: + /// **'The previous signing secret still signs until {date}.'** + String pubRotationActive(String date); + + /// No description provided for @pubRotateSecret. + /// + /// In en, this message translates to: + /// **'Rotate signing secret'** + String get pubRotateSecret; + + /// No description provided for @pubRotateSecretBody. + /// + /// In en, this message translates to: + /// **'You get a new secret. For 24 hours, webhooks carry signatures of the old and the new secret.'** + String get pubRotateSecretBody; + + /// No description provided for @pubRotate. + /// + /// In en, this message translates to: + /// **'Rotate'** + String get pubRotate; + + /// No description provided for @pubCreateApiKey. + /// + /// In en, this message translates to: + /// **'Create API key'** + String get pubCreateApiKey; + + /// No description provided for @pubRotateApiKey. + /// + /// In en, this message translates to: + /// **'Rotate API key'** + String get pubRotateApiKey; + + /// No description provided for @pubRotateApiKeyLast4. + /// + /// In en, this message translates to: + /// **'Rotate API key (…{last4})'** + String pubRotateApiKeyLast4(String last4); + + /// No description provided for @pubRotateApiKeyBody. + /// + /// In en, this message translates to: + /// **'The current key stops working at once.'** + String get pubRotateApiKeyBody; + + /// No description provided for @pubApiKey. + /// + /// In en, this message translates to: + /// **'API key'** + String get pubApiKey; + + /// No description provided for @pubSigningSecret. + /// + /// In en, this message translates to: + /// **'Signing secret'** + String get pubSigningSecret; + + /// No description provided for @pubSecretOnce. + /// + /// In en, this message translates to: + /// **'Copy the {what} now. It isn\'t shown again.'** + String pubSecretOnce(String what); + + /// No description provided for @pubSecretSaved. + /// + /// In en, this message translates to: + /// **'I\'ve stored it'** + String get pubSecretSaved; + + /// No description provided for @pubDeliveries. + /// + /// In en, this message translates to: + /// **'Deliveries'** + String get pubDeliveries; + + /// No description provided for @pubSendTest. + /// + /// In en, this message translates to: + /// **'Send test'** + String get pubSendTest; + + /// No description provided for @pubTestOk. + /// + /// In en, this message translates to: + /// **'Your webhook accepted the test.'** + String get pubTestOk; + + /// No description provided for @pubTestFailed. + /// + /// In en, this message translates to: + /// **'Your webhook didn\'t accept the test'** + String get pubTestFailed; + + /// No description provided for @pubNoDeliveries. + /// + /// In en, this message translates to: + /// **'No webhooks sent yet.'** + String get pubNoDeliveries; + + /// No description provided for @pubDelivered. + /// + /// In en, this message translates to: + /// **'Delivered (HTTP {status_code})'** + String pubDelivered(int status_code); + + /// No description provided for @pubDeliveryFailed. + /// + /// In en, this message translates to: + /// **'Failed: {error}'** + String pubDeliveryFailed(String error); + + /// No description provided for @pubDeliveryQueued. + /// + /// In en, this message translates to: + /// **'Queued'** + String get pubDeliveryQueued; + + /// No description provided for @pubDeliveryRetrying. + /// + /// In en, this message translates to: + /// **'{error} · next try {date}'** + String pubDeliveryRetrying(String error, String date); + + /// No description provided for @pubResend. + /// + /// In en, this message translates to: + /// **'Resend'** + String get pubResend; + + /// No description provided for @pubDeleteTitle. + /// + /// In en, this message translates to: + /// **'Delete “{name}”?'** + String pubDeleteTitle(String name); + + /// No description provided for @pubDeleteBody. + /// + /// In en, this message translates to: + /// **'Contributors\' documents stay in their drives, but they can\'t submit them anymore, and moderators lose access. Your blog gets no webhook about it.'** + String get pubDeleteBody; + + /// Notification settings: messages and status changes from blogs. + /// + /// In en, this message translates to: + /// **'Stories for publications'** + String get notifySubmissions; + + /// No description provided for @notifySubmissionsHint. + /// + /// In en, this message translates to: + /// **'Status changes and messages from blogs you write for'** + String get notifySubmissionsHint; + + /// No description provided for @notifSubmissionChanges. + /// + /// In en, this message translates to: + /// **'{publication} asked for changes to “{what}”'** + String notifSubmissionChanges(String publication, String what); + + /// No description provided for @notifSubmissionDeclined. + /// + /// In en, this message translates to: + /// **'{publication} declined “{what}”'** + String notifSubmissionDeclined(String publication, String what); + + /// No description provided for @notifSubmissionPublished. + /// + /// In en, this message translates to: + /// **'{publication} published “{what}”'** + String notifSubmissionPublished(String publication, String what); + + /// No description provided for @notifSubmissionInReview. + /// + /// In en, this message translates to: + /// **'{publication} is reviewing “{what}”'** + String notifSubmissionInReview(String publication, String what); + + /// No description provided for @notifSubmissionMessage. + /// + /// In en, this message translates to: + /// **'{publication} sent a message about “{what}”'** + String notifSubmissionMessage(String publication, String what); + + /// No description provided for @notifSubmissionFailed. + /// + /// In en, this message translates to: + /// **'{publication} couldn\'t receive “{what}”'** + String notifSubmissionFailed(String publication, String what); + + /// No description provided for @shareModerator. + /// + /// In en, this message translates to: + /// **'Moderator · {publication}'** + String shareModerator(String publication); + + /// No description provided for @activitySubmitted. + /// + /// In en, this message translates to: + /// **'{who} submitted it to {publication}'** + String activitySubmitted(String who, String publication); + + /// No description provided for @activitySubmissionWithdrawn. + /// + /// In en, this message translates to: + /// **'{who} withdrew it from {publication}'** + String activitySubmissionWithdrawn(String who, String publication); + + /// No description provided for @activitySubmissionDisconnected. + /// + /// In en, this message translates to: + /// **'{who} disconnected it from {publication}'** + String activitySubmissionDisconnected(String who, String publication); + + /// No description provided for @activitySubmissionReconnected. + /// + /// In en, this message translates to: + /// **'{who} connected it to {publication} again'** + String activitySubmissionReconnected(String who, String publication); + + /// No description provided for @activitySubmissionStatus. + /// + /// In en, this message translates to: + /// **'{publication}: {status}'** + String activitySubmissionStatus(String publication, String status); + + /// Status of a story for a publication. + /// + /// In en, this message translates to: + /// **'Draft'** + String get submissionStatusDraft; + + /// No description provided for @submissionStatusInReview. + /// + /// In en, this message translates to: + /// **'In review'** + String get submissionStatusInReview; + + /// No description provided for @submissionStatusChangesRequested. + /// + /// In en, this message translates to: + /// **'Changes requested'** + String get submissionStatusChangesRequested; + + /// No description provided for @submissionStatusDeclined. + /// + /// In en, this message translates to: + /// **'Declined'** + String get submissionStatusDeclined; + + /// No description provided for @submissionStatusPublished. + /// + /// In en, this message translates to: + /// **'Published'** + String get submissionStatusPublished; + + /// No description provided for @submissionStatusWithdrawn. + /// + /// In en, this message translates to: + /// **'Withdrawn'** + String get submissionStatusWithdrawn; + + /// Consent dialog of a contributor link (specs/18 §3). + /// + /// In en, this message translates to: + /// **'Write for {name}'** + String pubStartTitle(String name); + + /// No description provided for @pubStartHostVerified. + /// + /// In en, this message translates to: + /// **'{host} ✓'** + String pubStartHostVerified(String host); + + /// No description provided for @pubStartHostUnverified. + /// + /// In en, this message translates to: + /// **'Wonky hasn\'t verified that this publication belongs to {site}. Your story is sent to {webhook}.'** + String pubStartHostUnverified(String site, String webhook); + + /// No description provided for @pubStartConsent. + /// + /// In en, this message translates to: + /// **'You\'ll write in your own Wonky document. When you press Submit, {name} receives the text and images of the document, the fields you fill in and your display name, and its moderators can read and comment on the document.'** + String pubStartConsent(String name); + + /// No description provided for @pubStartWhich. + /// + /// In en, this message translates to: + /// **'Story'** + String get pubStartWhich; + + /// No description provided for @pubStartContinue. + /// + /// In en, this message translates to: + /// **'Continue “{name}”'** + String pubStartContinue(String name); + + /// No description provided for @pubStartNew. + /// + /// In en, this message translates to: + /// **'Start a new story'** + String get pubStartNew; + + /// No description provided for @pubStartTerms. + /// + /// In en, this message translates to: + /// **'I agree to {name}\'s contributor terms ({url})'** + String pubStartTerms(String name, String url); + + /// No description provided for @pubStartTermsRequired. + /// + /// In en, this message translates to: + /// **'Agree to {name}\'s contributor terms to start.'** + String pubStartTermsRequired(String name); + + /// No description provided for @pubStartButton. + /// + /// In en, this message translates to: + /// **'Start writing'** + String get pubStartButton; + + /// No description provided for @pubStartBlocked. + /// + /// In en, this message translates to: + /// **'{name} isn\'t accepting stories from you.'** + String pubStartBlocked(String name); + + /// No description provided for @pubStartClosed. + /// + /// In en, this message translates to: + /// **'{name} isn\'t accepting stories right now.'** + String pubStartClosed(String name); } class _WonkyAppLocalizationsDelegate diff --git a/packages/wonky_app/lib/src/l10n/wonky_app_localizations_en.dart b/packages/wonky_app/lib/src/l10n/wonky_app_localizations_en.dart index 3dca68a9..90b75c80 100644 --- a/packages/wonky_app/lib/src/l10n/wonky_app_localizations_en.dart +++ b/packages/wonky_app/lib/src/l10n/wonky_app_localizations_en.dart @@ -4608,4685 +4608,5521 @@ class WonkyAppLocalizationsEn extends WonkyAppLocalizations { String boardReviewedSha(String sha) { return 'Reviewed at $sha'; } -} - -/// The translations for English (`en_XA`). -class WonkyAppLocalizationsEnXa extends WonkyAppLocalizationsEn { - WonkyAppLocalizationsEnXa() : super('en_XA'); @override - String get aboutAppVersion => '[Åþþ ṽéŕšîöñ one]'; + String get settingsPublications => 'Publications'; @override - String get aboutLicenses => '[Öþéñ šöûŕçé ļîçéñšéš one two]'; + String get pubSectionHint => + 'Let people write for your blog in Wonky Write and send stories to your review queue with one button.'; @override - String get aboutProtocol => '[Þŕöţöçöļ one]'; + String get pubNew => 'New publication'; @override - String get aboutRunMode => '[Šéŕṽéŕ ɱöðé one]'; + String get pubNewHint => + 'Wonky sends submitted stories to your webhook. You get the signing secret once, after you create the publication.'; @override - String get aboutServerVersion => '[Šéŕṽéŕ ṽéŕšîöñ one t]'; + String pubEdit(String name) { + return 'Edit “$name”'; + } @override - String get accountMenu => '[Åççöûñţ one]'; + String get pubEditButton => 'Edit…'; @override - String get actionBack => '[Ɓåçķ on]'; + String get pubGuide => 'Developer guide'; @override - String get actionCancel => '[Çåñçéļ one]'; + String get pubEmpty => 'You have no publications yet.'; @override - String get actionClear => '[Çļéåŕ on]'; + String get pubName => 'Name'; @override - String get actionClose => '[Çļöšé on]'; + String get pubSiteUrl => 'Site URL'; @override - String get actionCopy => '[Çöþý on]'; + String get pubWebhookUrl => 'Webhook URL'; @override - String get actionCreate => '[Çŕéåţé one]'; + String get pubTermsUrl => 'Contributor terms URL (optional)'; @override - String get actionDone => '[Ðöñé on]'; + String get pubTemplate => 'Template document (optional)'; @override - String get actionOk => '[ÖĶ o]'; + String get pubTemplateHint => + 'Paste a link to one of your Wonky Write documents'; @override - String get actionOpen => '[Öþéñ on]'; + String get pubTemplateInvalid => 'Paste the link of a Wonky Write document.'; @override - String get actionReload => '[Ŕéļöåð one]'; + String get pubRequired => 'Required.'; @override - String get actionRetry => '[Ŕéţŕý on]'; + String get pubHttpsOnly => 'Use an https:// address.'; @override - String get actionSave => '[Šåṽé on]'; + String get pubFieldSummary => 'Summary'; @override - String get actionSend => '[Šéñð on]'; + String get pubFieldTags => 'Tags'; @override - String get actionShare => '[Šĥåŕé on]'; + String get pubAllowedTags => 'Allowed tags (optional)'; @override - String get actionStop => '[Šţöþ on]'; + String get pubAllowedTagsHint => 'Comma separated; empty allows any tag'; @override - String get actionUndo => '[Ûñðö on]'; + String get pubFieldCover => 'Cover image'; @override - String activityCommented(String who) { - return '[$who çöɱɱéñţéð one]'; - } + String get pubFieldBio => 'Author bio'; @override - String activityCreated(String who) { - return '[$who çŕéåţéð ţĥîš one]'; - } + String get pubFieldNote => 'Note to the moderators'; @override - String activityEdited(String who) { - return '[$who éðîţéð one]'; - } + String get pubFieldOff => 'Not asked'; @override - String get activityEmpty => '[Ñö åçţîṽîţý ýéţ. one t]'; + String get pubFieldOptional => 'Optional'; @override - String activityExported(String who) { - return '[$who éẋþöŕţéð one]'; - } + String get pubFieldRequired => 'Required'; @override - String activityMoved(String who) { - return '[$who ɱöṽéð ţĥîš one]'; - } + String get pubEnabled => 'Accept new stories'; @override - String activityRenamed(String who) { - return '[$who ŕéñåɱéð ţĥîš one]'; + String pubHostVerified(String host) { + return '$host ✓'; } @override - String activityRestored(String who) { - return '[$who ŕéšţöŕéð ţĥîš ƒŕöɱ ţĥé ţŕåšĥ one two t]'; + String pubHostUnverified(String host) { + return '$host (not verified)'; } @override - String activityRestoredVersion(String who) { - return '[$who ŕéšţöŕéð å ṽéŕšîöñ one tw]'; - } + String get pubDisabled => 'Not accepting stories'; @override - String activityShared(String who) { - return '[$who šĥåŕéð ţĥîš one]'; + String pubOpenCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count stories in review', + one: '1 story in review', + zero: 'No stories in review', + ); + return '$_temp0'; } @override - String get activitySystem => '[Ŵöñķý Ŵöŕķ one]'; + String get pubManage => 'Manage'; @override - String activityTrashed(String who) { - return '[$who ɱöṽéð ţĥîš ţö ţĥé ţŕåšĥ one two]'; - } + String get pubHide => 'Hide'; @override - String activityUnshared(String who) { - return '[$who ŕéɱöṽéð åççéšš one t]'; - } + String get pubContributorLink => + 'Contributor link (put it behind “Write for us”)'; @override - String activityUploaded(String who) { - return '[$who ûþļöåðéð ţĥîš one t]'; - } + String get pubId => 'Publication id'; @override - String get addShortcutAction => '[Åðð šĥöŕţçûţ one]'; + String get pubCopy => 'Copy'; @override - String get addShortcutTitle => '[Åðð šĥöŕţçûţ ţö Ṁý Ðŕîṽé one two]'; + String get pubCopied => 'Copied'; @override - String agentUndoLabel(String label) { - return '[ÅÎ: $label on]'; - } + String get pubDelete => 'Delete'; @override - String get aiEnable => '[Éñåƀļé ţĥé åššîšţåñţ one two]'; + String get pubModerators => 'Moderators'; @override - String get authBackToSignIn => '[Ɓåçķ ţö šîĝñ îñ one t]'; + String get pubModeratorsHint => + 'Moderators get comment access to stories when they are submitted. Enter the email addresses of their Wonky accounts, one per line.'; @override - String get authBackToSignUp => '[Ɓåçķ ţö šîĝñ ûþ one t]'; + String get pubModeratorEmails => 'Email addresses'; @override - String get authChangeEmail => '[Çĥåñĝé éɱåîļ åððŕéšš one two]'; + String pubModeratorsButton(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count moderators…', + one: '1 moderator…', + zero: 'Add moderators…', + ); + return '$_temp0'; + } @override - String get authCodeResent => '[Å ñéŵ çöðé îš öñ îţš ŵåý. one two]'; + String get pubVerification => 'Verification'; @override - String get authConfirmPassword => '[Çöñƒîŕɱ þåššŵöŕð one tw]'; + String pubVerifyHint(String host) { + return 'Serve this at https://$host/.well-known/wonky-publications.json, then verify. Until then contributors see your webhook\'s host and a warning.'; + } @override - String get authCreateAccount => '[Çŕéåţé åççöûñţ one t]'; + String pubVerifiedAt(String host, String date) { + return '$host verified $date'; + } @override - String get authDisplayName => '[Ñåɱé on]'; + String get pubVerify => 'Verify'; @override - String get authEmail => '[Éɱåîļ on]'; + String pubVerified(String host) { + return '$host is verified'; + } @override - String get authErrorCodeLength => '[Éñţéŕ ţĥé 6-ðîĝîţ çöðé. one two]'; + String get pubVerifyFailed => 'Not verified'; @override - String get authErrorEmail => '[Éñţéŕ å ṽåļîð éɱåîļ åððŕéšš. one two t]'; + String get pubCredentials => 'Signing secret and API key'; @override - String get authErrorExpiredCode => - '[Ţĥîš çöðé ĥåš éẋþîŕéð. Ŕéǫûéšţ å ñéŵ öñé. one two thre]'; + String get pubSecretHint => + 'Webhooks are signed with the signing secret. Your server calls the publication API with the API key.'; @override - String get authErrorInvalidCode => - '[Ţĥåţ çöðé îš ñöţ ŕîĝĥţ. Çĥéçķ îţ åñð ţŕý åĝåîñ. one two three]'; + String pubRotationActive(String date) { + return 'The previous signing secret still signs until $date.'; + } @override - String get authErrorInvalidCredentials => - '[Ŵŕöñĝ éɱåîļ öŕ þåššŵöŕð. one two]'; + String get pubRotateSecret => 'Rotate signing secret'; @override - String get authErrorNetwork => - '[Çåñ\'ţ ŕéåçĥ ţĥé šéŕṽéŕ. Çĥéçķ ýöûŕ çöññéçţîöñ åñð ţŕý åĝåîñ. one two three four]'; + String get pubRotateSecretBody => + 'You get a new secret. For 24 hours, webhooks carry signatures of the old and the new secret.'; @override - String get authErrorPasswordMismatch => - '[Ţĥé þåššŵöŕðš ðöñ\'ţ ɱåţçĥ. one two t]'; + String get pubRotate => 'Rotate'; @override - String get authErrorPasswordPolicy => - '[Ţĥîš þåššŵöŕð ðöéšñ\'ţ ɱééţ ţĥé ŕéǫûîŕéɱéñţš. Çĥööšé å ļöñĝéŕ öŕ ɱöŕé ṽåŕîéð þåššŵöŕð. one two three four five si]'; + String get pubCreateApiKey => 'Create API key'; @override - String get authErrorPasswordShort => '[Ûšé åţ ļéåšţ 8 çĥåŕåçţéŕš. one two]'; + String get pubRotateApiKey => 'Rotate API key'; @override - String get authErrorPasswordWeak => - '[Ţĥîš þåššŵöŕð îš ţöö éåšý ţö ĝûéšš. one two thr]'; + String pubRotateApiKeyLast4(String last4) { + return 'Rotate API key (…$last4)'; + } @override - String get authErrorTerms => - '[Þļéåšé åççéþţ ţĥé ţéŕɱš ţö çöñţîñûé. one two thr]'; + String get pubRotateApiKeyBody => 'The current key stops working at once.'; @override - String get authErrorTooManyAttempts => - '[Ţöö ɱåñý åţţéɱþţš. Ŵåîţ å ɱöɱéñţ åñð ţŕý åĝåîñ. one two three]'; + String get pubApiKey => 'API key'; @override - String get authContinueWithGoogle => '[Çöñţîñûé ŵîţĥ Ĝööĝļé one two]'; + String get pubSigningSecret => 'Signing secret'; @override - String get authOr => '[öŕ o]'; + String pubSecretOnce(String what) { + return 'Copy the $what now. It isn\'t shown again.'; + } @override - String get authGoogleTerms => - '[Ɓý çöñţîñûîñĝ ŵîţĥ Ĝööĝļé, ýöû åĝŕéé ţö ţĥé ţéŕɱš öƒ šéŕṽîçé åñð ţĥé þŕîṽåçý þöļîçý. one two three four five s]'; + String get pubSecretSaved => 'I\'ve stored it'; @override - String get authErrorGoogleUnavailable => - '[Šîĝñ îñ ŵîţĥ Ĝööĝļé îšñ\'ţ šéţ ûþ öñ ţĥîš šéŕṽéŕ. one two three]'; + String get pubDeliveries => 'Deliveries'; @override - String get authErrorPopupBlocked => - '[Ýöûŕ ƀŕöŵšéŕ ƀļöçķéð ţĥé Ĝööĝļé šîĝñ-îñ ŵîñðöŵ. Åļļöŵ þöþ-ûþš ƒöŕ ţĥîš šîţé åñð ţŕý åĝåîñ. one two three four five six]'; + String get pubSendTest => 'Send test'; @override - String get authErrorUnknown => - '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ. Þļéåšé ţŕý åĝåîñ. one two thre]'; + String get pubTestOk => 'Your webhook accepted the test.'; @override - String get authForgotPassword => '[Ƒöŕĝöţ þåššŵöŕð? one tw]'; + String get pubTestFailed => 'Your webhook didn\'t accept the test'; @override - String get authHaveAccount => '[Åļŕéåðý ĥåṽé åñ åççöûñţ? one two]'; + String get pubNoDeliveries => 'No webhooks sent yet.'; @override - String get authHidePassword => '[Ĥîðé þåššŵöŕð one t]'; + String pubDelivered(int status_code) { + return 'Delivered (HTTP $status_code)'; + } @override - String get authNewPassword => '[Ñéŵ þåššŵöŕð one]'; + String pubDeliveryFailed(String error) { + return 'Failed: $error'; + } @override - String get authNewPasswordSubtitle => - '[Çĥööšé å ñéŵ þåššŵöŕð ƒöŕ ýöûŕ åççöûñţ. one two thre]'; + String get pubDeliveryQueued => 'Queued'; @override - String get authNoAccount => '[Ñéŵ ţö Ŵöñķý Ŵöŕķ? one tw]'; + String pubDeliveryRetrying(String error, String date) { + return '$error · next try $date'; + } @override - String get authPassword => '[Þåššŵöŕð one]'; + String get pubResend => 'Resend'; @override - String get authRememberMe => '[Ķééþ ɱé šîĝñéð îñ one t]'; + String pubDeleteTitle(String name) { + return 'Delete “$name”?'; + } @override - String get authResendCode => '[Ŕéšéñð çöðé one]'; + String get pubDeleteBody => + 'Contributors\' documents stay in their drives, but they can\'t submit them anymore, and moderators lose access. Your blog gets no webhook about it.'; @override - String authResendIn(int seconds) { - return '[Ŕéšéñð çöðé îñ $seconds š one t]'; - } + String get notifySubmissions => 'Stories for publications'; @override - String get authResetSubtitle => - '[Ŵé\'ļļ éɱåîļ ýöû å çöðé ţö ŕéšéţ ýöûŕ þåššŵöŕð. one two three]'; + String get notifySubmissionsHint => + 'Status changes and messages from blogs you write for'; @override - String get authResetTitle => '[Ŕéšéţ ýöûŕ þåššŵöŕð one tw]'; + String notifSubmissionChanges(String publication, String what) { + return '$publication asked for changes to “$what”'; + } @override - String get authSendCode => '[Šéñð çöðé one]'; + String notifSubmissionDeclined(String publication, String what) { + return '$publication declined “$what”'; + } @override - String get authSetPassword => '[Šéţ þåššŵöŕð åñð šîĝñ îñ one two]'; + String notifSubmissionPublished(String publication, String what) { + return '$publication published “$what”'; + } @override - String get authShowPassword => '[Šĥöŵ þåššŵöŕð one t]'; + String notifSubmissionInReview(String publication, String what) { + return '$publication is reviewing “$what”'; + } @override - String get authSignIn => '[Šîĝñ îñ one]'; + String notifSubmissionMessage(String publication, String what) { + return '$publication sent a message about “$what”'; + } @override - String get authSignInSubtitle => - '[Öñé åççöûñţ ƒöŕ éṽéŕý Ŵöñķý Ŵöŕķ åþþ. one two thr]'; + String notifSubmissionFailed(String publication, String what) { + return '$publication couldn\'t receive “$what”'; + } @override - String get authSignInTitle => '[Šîĝñ îñ one]'; + String shareModerator(String publication) { + return 'Moderator · $publication'; + } @override - String get authSignUpSubtitle => - '[Çŕéåţé öñé åççöûñţ ƒöŕ éṽéŕý Ŵöñķý Ŵöŕķ åþþ. one two three]'; + String activitySubmitted(String who, String publication) { + return '$who submitted it to $publication'; + } @override - String get authSignUpTitle => '[Çŕéåţé ýöûŕ åççöûñţ one tw]'; + String activitySubmissionWithdrawn(String who, String publication) { + return '$who withdrew it from $publication'; + } @override - String get authTerms => - '[Î åĝŕéé ţö ţĥé ţéŕɱš öƒ šéŕṽîçé åñð þŕîṽåçý þöļîçý one two three f]'; + String activitySubmissionDisconnected(String who, String publication) { + return '$who disconnected it from $publication'; + } @override - String get authTermsLink => '[Ţéŕɱš öƒ šéŕṽîçé one t]'; + String activitySubmissionReconnected(String who, String publication) { + return '$who connected it to $publication again'; + } @override - String get authPrivacyLink => '[Þŕîṽåçý þöļîçý one t]'; + String activitySubmissionStatus(String publication, String status) { + return '$publication: $status'; + } @override - String get authVerify => '[Ṽéŕîƒý one]'; + String get submissionStatusDraft => 'Draft'; @override - String get authVerifyNoDraft => - '[Šţåŕţ ţĥé šîĝñ-ûþ åĝåîñ ţö ĝéţ å ñéŵ çöðé. one two thre]'; + String get submissionStatusInReview => 'In review'; @override - String authVerifySubtitle(String email) { - return '[Ŵé šéñţ å 6-ðîĝîţ çöðé ţö $email. one two]'; - } + String get submissionStatusChangesRequested => 'Changes requested'; @override - String get authVerifyTitle => '[Ṽéŕîƒý ýöûŕ éɱåîļ one tw]'; + String get submissionStatusDeclined => 'Declined'; @override - String get badgeCommentOnly => '[Çöɱɱéñţ öñļý one]'; + String get submissionStatusPublished => 'Published'; @override - String get badgeOffline => '[Åṽåîļåƀļé öƒƒļîñé one tw]'; + String get submissionStatusWithdrawn => 'Withdrawn'; @override - String get badgeShared => '[Šĥåŕéð one]'; + String pubStartTitle(String name) { + return 'Write for $name'; + } @override - String get badgeViewOnly => '[Ṽîéŵ öñļý one]'; + String pubStartHostVerified(String host) { + return '$host ✓'; + } @override - String get categoryAccount => '[Åççöûñţ one]'; + String pubStartHostUnverified(String site, String webhook) { + return 'Wonky hasn\'t verified that this publication belongs to $site. Your story is sent to $webhook.'; + } @override - String get categoryComments => '[Çöɱɱéñţš one]'; + String pubStartConsent(String name) { + return 'You\'ll write in your own Wonky document. When you press Submit, $name receives the text and images of the document, the fields you fill in and your display name, and its moderators can read and comment on the document.'; + } @override - String get categoryDrive => '[Ðŕîṽé on]'; + String get pubStartWhich => 'Story'; @override - String get categoryEdit => '[Éðîţ on]'; + String pubStartContinue(String name) { + return 'Continue “$name”'; + } @override - String get categoryFile => '[Ƒîļé on]'; + String get pubStartNew => 'Start a new story'; @override - String get categoryHelp => '[Ĥéļþ on]'; + String pubStartTerms(String name, String url) { + return 'I agree to $name\'s contributor terms ($url)'; + } @override - String get categoryNavigation => '[Ñåṽîĝåţîöñ one]'; + String pubStartTermsRequired(String name) { + return 'Agree to $name\'s contributor terms to start.'; + } @override - String get categoryOther => '[Öţĥéŕ on]'; + String get pubStartButton => 'Start writing'; @override - String get categorySharing => '[Šĥåŕîñĝ one]'; + String pubStartBlocked(String name) { + return '$name isn\'t accepting stories from you.'; + } @override - String get categoryTools => '[Ţööļš on]'; + String pubStartClosed(String name) { + return '$name isn\'t accepting stories right now.'; + } +} + +/// The translations for English (`en_XA`). +class WonkyAppLocalizationsEnXa extends WonkyAppLocalizationsEn { + WonkyAppLocalizationsEnXa() : super('en_XA'); @override - String get categoryVersions => '[Ṽéŕšîöñ ĥîšţöŕý one t]'; + String get aboutAppVersion => '[Åþþ ṽéŕšîöñ one]'; @override - String get categoryView => '[Ṽîéŵ on]'; + String get aboutLicenses => '[Öþéñ šöûŕçé ļîçéñšéš one two]'; @override - String get cmdAbout => '[Åƀöûţ on]'; + String get aboutProtocol => '[Þŕöţöçöļ one]'; @override - String get cmdAddShortcut => '[Åðð šĥöŕţçûţ ţö Ðŕîṽé one two]'; + String get aboutRunMode => '[Šéŕṽéŕ ɱöðé one]'; @override - String cmdAppSettings(String app) { - return '[$app šéţţîñĝš one]'; - } + String get aboutServerVersion => '[Šéŕṽéŕ ṽéŕšîöñ one t]'; @override - String get cmdAssistant => '[Åššîšţåñţ one]'; + String get accountMenu => '[Åççöûñţ one]'; @override - String get cmdAssistantNewThread => '[Ñéŵ åššîšţåñţ çĥåţ one tw]'; + String get actionBack => '[Ɓåçķ on]'; @override - String get cmdAssistantSend => '[Šéñð ţö åššîšţåñţ one tw]'; + String get actionCancel => '[Çåñçéļ one]'; @override - String get cmdAssistantStop => '[Šţöþ åššîšţåñţ one t]'; + String get actionClear => '[Çļéåŕ on]'; @override - String get cmdBack => '[Ɓåçķ on]'; + String get actionClose => '[Çļöšé on]'; @override - String get cmdClosePanel => '[Çļöšé þåñéļ one]'; + String get actionCopy => '[Çöþý on]'; @override - String get cmdCommandPalette => '[Çöɱɱåñð þåļéţţé one t]'; + String get actionCreate => '[Çŕéåţé one]'; @override - String get cmdComment => '[Çöɱɱéñţ one]'; + String get actionDone => '[Ðöñé on]'; @override - String get cmdCommentsPanel => '[Çöɱɱéñţš one]'; + String get actionOk => '[ÖĶ o]'; @override - String get cmdCopy => '[Çöþý on]'; + String get actionOpen => '[Öþéñ on]'; @override - String get cmdCopyLink => '[Çöþý ļîñķ one]'; + String get actionReload => '[Ŕéļöåð one]'; @override - String get cmdCopyMcpConfig => '[Çöþý ṀÇÞ çöññéçţîöñ šéţţîñĝš one two t]'; + String get actionRetry => '[Ŕéţŕý on]'; @override - String get cmdCut => '[Çûţ on]'; + String get actionSave => '[Šåṽé on]'; @override - String get cmdDeleteComment => '[Ðéļéţé çöɱɱéñţ one t]'; + String get actionSend => '[Šéñð on]'; @override - String get cmdDeleteForever => '[Ðéļéţé ƒöŕéṽéŕ one t]'; + String get actionShare => '[Šĥåŕé on]'; @override - String get cmdDetails => '[Ðéţåîļš one]'; + String get actionStop => '[Šţöþ on]'; @override - String get cmdDownload => '[Ðöŵñļöåð one]'; + String get actionUndo => '[Ûñðö on]'; @override - String get cmdEmptyTrash => '[Éɱþţý ţŕåšĥ one]'; + String activityCommented(String who) { + return '[$who çöɱɱéñţéð one]'; + } @override - String get cmdFocusSearch => '[Šéåŕçĥ îñ Ðŕîṽé one t]'; + String activityCreated(String who) { + return '[$who çŕéåţéð ţĥîš one]'; + } @override - String get cmdForward => '[Ƒöŕŵåŕð one]'; + String activityEdited(String who) { + return '[$who éðîţéð one]'; + } @override - String get cmdHome => '[Ĥöɱé on]'; + String get activityEmpty => '[Ñö åçţîṽîţý ýéţ. one t]'; @override - String get cmdImport => '[Îɱþöŕţ… one]'; + String activityExported(String who) { + return '[$who éẋþöŕţéð one]'; + } @override - String get cmdKeyboardShortcuts => '[Ķéýƀöåŕð šĥöŕţçûţš one tw]'; + String activityMoved(String who) { + return '[$who ɱöṽéð ţĥîš one]'; + } @override - String get cmdMakeAvailableOffline => '[Ṁåķé åṽåîļåƀļé öƒƒļîñé one two]'; + String activityRenamed(String who) { + return '[$who ŕéñåɱéð ţĥîš one]'; + } @override - String get cmdMakeCopy => '[Ṁåķé å çöþý one]'; + String activityRestored(String who) { + return '[$who ŕéšţöŕéð ţĥîš ƒŕöɱ ţĥé ţŕåšĥ one two t]'; + } @override - String get cmdManageStorage => '[Ṁåñåĝé šţöŕåĝé one t]'; + String activityRestoredVersion(String who) { + return '[$who ŕéšţöŕéð å ṽéŕšîöñ one tw]'; + } @override - String get cmdMove => '[Ṁöṽé on]'; + String activityShared(String who) { + return '[$who šĥåŕéð ţĥîš one]'; + } @override - String get cmdMoveToTrash => '[Ṁöṽé ţö ţŕåšĥ one]'; + String get activitySystem => '[Ŵöñķý Ŵöŕķ one]'; @override - String get cmdNameCurrentVersion => '[Ñåɱé çûŕŕéñţ ṽéŕšîöñ one two]'; + String activityTrashed(String who) { + return '[$who ɱöṽéð ţĥîš ţö ţĥé ţŕåšĥ one two]'; + } @override - String get cmdNewDocument => '[Ñéŵ ðöçûɱéñţ one]'; + String activityUnshared(String who) { + return '[$who ŕéɱöṽéð åççéšš one t]'; + } @override - String get cmdNewFile => '[Ñéŵ ƒîļé one]'; + String activityUploaded(String who) { + return '[$who ûþļöåðéð ţĥîš one t]'; + } @override - String get cmdNewFolder => '[Ñéŵ ƒöļðéŕ one]'; + String get addShortcutAction => '[Åðð šĥöŕţçûţ one]'; @override - String get cmdNewFromTemplate => '[Ƒŕöɱ ţéɱþļåţé… one t]'; + String get addShortcutTitle => '[Åðð šĥöŕţçûţ ţö Ṁý Ðŕîṽé one two]'; @override - String get cmdNewSpreadsheet => '[Ñéŵ šþŕéåðšĥééţ one t]'; + String agentUndoLabel(String label) { + return '[ÅÎ: $label on]'; + } @override - String get cmdNextPanel => '[Ñéẋţ þåñéļ one]'; + String get aiEnable => '[Éñåƀļé ţĥé åššîšţåñţ one two]'; @override - String get cmdNextRegion => '[Ƒöçûš ñéẋţ ŕéĝîöñ one tw]'; + String get authBackToSignIn => '[Ɓåçķ ţö šîĝñ îñ one t]'; @override - String get cmdOpen => '[Öþéñ on]'; + String get authBackToSignUp => '[Ɓåçķ ţö šîĝñ ûþ one t]'; @override - String get cmdOpenComment => '[Öþéñ çöɱɱéñţ one]'; + String get authChangeEmail => '[Çĥåñĝé éɱåîļ åððŕéšš one two]'; @override - String get cmdOpenFile => '[Öþéñ… on]'; + String get authCodeResent => '[Å ñéŵ çöðé îš öñ îţš ŵåý. one two]'; @override - String get cmdOpenInDrive => '[Öþéñ îñ Ŵöñķý Ðŕîṽé one tw]'; + String get authConfirmPassword => '[Çöñƒîŕɱ þåššŵöŕð one tw]'; @override - String get cmdOpenPanel => '[Öþéñ þåñéļ one]'; + String get authCreateAccount => '[Çŕéåţé åççöûñţ one t]'; @override - String get cmdOpenSheets => '[Öþéñ Ŵöñķý Šĥééţš one tw]'; + String get authDisplayName => '[Ñåɱé on]'; @override - String get cmdOpenWrite => '[Öþéñ Ŵöñķý Ŵŕîţé one t]'; + String get authEmail => '[Éɱåîļ on]'; @override - String get cmdPaste => '[Þåšţé on]'; + String get authErrorCodeLength => '[Éñţéŕ ţĥé 6-ðîĝîţ çöðé. one two]'; @override - String get cmdPastePlain => '[Þåšţé ŵîţĥöûţ ƒöŕɱåţţîñĝ one two]'; + String get authErrorEmail => '[Éñţéŕ å ṽåļîð éɱåîļ åððŕéšš. one two t]'; @override - String get cmdPreviousPanel => '[Þŕéṽîöûš þåñéļ one t]'; + String get authErrorExpiredCode => + '[Ţĥîš çöðé ĥåš éẋþîŕéð. Ŕéǫûéšţ å ñéŵ öñé. one two thre]'; @override - String get cmdPreviousRegion => '[Ƒöçûš þŕéṽîöûš ŕéĝîöñ one two]'; + String get authErrorInvalidCode => + '[Ţĥåţ çöðé îš ñöţ ŕîĝĥţ. Çĥéçķ îţ åñð ţŕý åĝåîñ. one two three]'; @override - String get cmdPrint => '[Þŕîñţ on]'; + String get authErrorInvalidCredentials => + '[Ŵŕöñĝ éɱåîļ öŕ þåššŵöŕð. one two]'; @override - String get cmdQuickSwitcher => '[Ĝö ţö ƒîļé… one]'; + String get authErrorNetwork => + '[Çåñ\'ţ ŕéåçĥ ţĥé šéŕṽéŕ. Çĥéçķ ýöûŕ çöññéçţîöñ åñð ţŕý åĝåîñ. one two three four]'; @override - String get cmdRedo => '[Ŕéðö on]'; + String get authErrorPasswordMismatch => + '[Ţĥé þåššŵöŕðš ðöñ\'ţ ɱåţçĥ. one two t]'; @override - String cmdRedoLabel(String label) { - return '[Ŕéðö $label on]'; - } + String get authErrorPasswordPolicy => + '[Ţĥîš þåššŵöŕð ðöéšñ\'ţ ɱééţ ţĥé ŕéǫûîŕéɱéñţš. Çĥööšé å ļöñĝéŕ öŕ ɱöŕé ṽåŕîéð þåššŵöŕð. one two three four five si]'; @override - String get cmdRename => '[Ŕéñåɱé one]'; + String get authErrorPasswordShort => '[Ûšé åţ ļéåšţ 8 çĥåŕåçţéŕš. one two]'; @override - String get cmdReopen => '[Ŕéöþéñ one]'; + String get authErrorPasswordWeak => + '[Ţĥîš þåššŵöŕð îš ţöö éåšý ţö ĝûéšš. one two thr]'; @override - String get cmdReply => '[Ŕéþļý on]'; + String get authErrorTerms => + '[Þļéåšé åççéþţ ţĥé ţéŕɱš ţö çöñţîñûé. one two thr]'; @override - String get cmdReportBug => '[Ŕéþöŕţ å ƀûĝ one]'; + String get authErrorTooManyAttempts => + '[Ţöö ɱåñý åţţéɱþţš. Ŵåîţ å ɱöɱéñţ åñð ţŕý åĝåîñ. one two three]'; @override - String get cmdReportProblem => '[Ŕéþöŕţ å þŕöƀļéɱ one t]'; + String get authContinueWithGoogle => '[Çöñţîñûé ŵîţĥ Ĝööĝļé one two]'; @override - String get cmdRequestAccess => '[Ŕéǫûéšţ åççéšš one t]'; + String get authOr => '[öŕ o]'; @override - String get cmdResolve => '[Ŕéšöļṽé one]'; + String get authGoogleTerms => + '[Ɓý çöñţîñûîñĝ ŵîţĥ Ĝööĝļé, ýöû åĝŕéé ţö ţĥé ţéŕɱš öƒ šéŕṽîçé åñð ţĥé þŕîṽåçý þöļîçý. one two three four five s]'; @override - String get cmdRestore => '[Ŕéšţöŕé one]'; + String get authErrorGoogleUnavailable => + '[Šîĝñ îñ ŵîţĥ Ĝööĝļé îšñ\'ţ šéţ ûþ öñ ţĥîš šéŕṽéŕ. one two three]'; @override - String get cmdRestoreVersion => '[Ŕéšţöŕé ţĥîš ṽéŕšîöñ one two]'; + String get authErrorPopupBlocked => + '[Ýöûŕ ƀŕöŵšéŕ ƀļöçķéð ţĥé Ĝööĝļé šîĝñ-îñ ŵîñðöŵ. Åļļöŵ þöþ-ûþš ƒöŕ ţĥîš šîţé åñð ţŕý åĝåîñ. one two three four five six]'; @override - String get cmdSeeVersionHistory => '[Šéé ṽéŕšîöñ ĥîšţöŕý one tw]'; + String get authErrorUnknown => + '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ. Þļéåšé ţŕý åĝåîñ. one two thre]'; @override - String get cmdSelectAll => '[Šéļéçţ åļļ one]'; + String get authForgotPassword => '[Ƒöŕĝöţ þåššŵöŕð? one tw]'; @override - String get cmdSetDescription => '[Éðîţ ðéšçŕîþţîöñ one tw]'; + String get authHaveAccount => '[Åļŕéåðý ĥåṽé åñ åççöûñţ? one two]'; @override - String get cmdSetTheme => '[Åþþ ţĥéɱé one]'; + String get authHidePassword => '[Ĥîðé þåššŵöŕð one t]'; @override - String get cmdSettings => '[Šéţţîñĝš one]'; + String get authNewPassword => '[Ñéŵ þåššŵöŕð one]'; @override - String get cmdShare => '[Šĥåŕé on]'; + String get authNewPasswordSubtitle => + '[Çĥööšé å ñéŵ þåššŵöŕð ƒöŕ ýöûŕ åççöûñţ. one two thre]'; @override - String get cmdSignOut => '[Šîĝñ öûţ one]'; + String get authNoAccount => '[Ñéŵ ţö Ŵöñķý Ŵöŕķ? one tw]'; @override - String get cmdStar => '[Šţåŕ on]'; + String get authPassword => '[Þåššŵöŕð one]'; @override - String get cmdStopAgent => '[Šţöþ åĝéñţ çöñţŕöļ one tw]'; + String get authRememberMe => '[Ķééþ ɱé šîĝñéð îñ one t]'; @override - String get cmdTogglePanel => '[Ţöĝĝļé þåñéļ one]'; + String get authResendCode => '[Ŕéšéñð çöðé one]'; @override - String get cmdToggleUiBridge => - '[Åļļöŵ ṀÇÞ ţö çöñţŕöļ ţĥîš ŵîñðöŵ one two th]'; + String authResendIn(int seconds) { + return '[Ŕéšéñð çöðé îñ $seconds š one t]'; + } @override - String get cmdUndo => '[Ûñðö on]'; + String get authResetSubtitle => + '[Ŵé\'ļļ éɱåîļ ýöû å çöðé ţö ŕéšéţ ýöûŕ þåššŵöŕð. one two three]'; @override - String get cmdUndoHistory => '[Ûñðö ĥîšţöŕý… one t]'; + String get authResetTitle => '[Ŕéšéţ ýöûŕ þåššŵöŕð one tw]'; @override - String cmdUndoLabel(String label) { - return '[Ûñðö $label on]'; - } + String get authSendCode => '[Šéñð çöðé one]'; @override - String get cmdUndoTo => '[Ûñðö ţö šţéþ one]'; + String get authSetPassword => '[Šéţ þåššŵöŕð åñð šîĝñ îñ one two]'; @override - String get cmdUnstar => '[Ŕéɱöṽé šţåŕ one]'; + String get authShowPassword => '[Šĥöŵ þåššŵöŕð one t]'; @override - String get cmdUpload => '[Ûþļöåð ƒîļé… one]'; + String get authSignIn => '[Šîĝñ îñ one]'; @override - String get cmdVersionsPanel => '[Ṽéŕšîöñ ĥîšţöŕý þåñéļ one two]'; + String get authSignInSubtitle => + '[Öñé åççöûñţ ƒöŕ éṽéŕý Ŵöñķý Ŵöŕķ åþþ. one two thr]'; @override - String get cmdWhatsNew => '[Ŵĥåţ\'š ñéŵ one]'; + String get authSignInTitle => '[Šîĝñ îñ one]'; @override - String get cmdWorkSettings => '[Ŵöñķý Ŵöŕķ šéţţîñĝš one tw]'; + String get authSignUpSubtitle => + '[Çŕéåţé öñé åççöûñţ ƒöŕ éṽéŕý Ŵöñķý Ŵöŕķ åþþ. one two three]'; @override - String get cmdZoom => '[Žööɱ on]'; + String get authSignUpTitle => '[Çŕéåţé ýöûŕ åççöûñţ one tw]'; @override - String get collapseFolders => '[Çöļļåþšé ƒöļðéŕš one tw]'; + String get authTerms => + '[Î åĝŕéé ţö ţĥé ţéŕɱš öƒ šéŕṽîçé åñð þŕîṽåçý þöļîçý one two three f]'; @override - String get columnModified => '[Ļåšţ ɱöðîƒîéð one t]'; + String get authTermsLink => '[Ţéŕɱš öƒ šéŕṽîçé one t]'; @override - String get columnName => '[Ñåɱé on]'; + String get authPrivacyLink => '[Þŕîṽåçý þöļîçý one t]'; @override - String get columnOwner => '[Öŵñéŕ on]'; + String get authVerify => '[Ṽéŕîƒý one]'; @override - String get columnSize => '[Ƒîļé šîžé one]'; + String get authVerifyNoDraft => + '[Šţåŕţ ţĥé šîĝñ-ûþ åĝåîñ ţö ĝéţ å ñéŵ çöðé. one two thre]'; @override - String commandFailed(String title) { - return '[“$title” ƒåîļéð one]'; + String authVerifySubtitle(String email) { + return '[Ŵé šéñţ å 6-ðîĝîţ çöðé ţö $email. one two]'; } @override - String get commentAction => '[Çöɱɱéñţ one]'; + String get authVerifyTitle => '[Ṽéŕîƒý ýöûŕ éɱåîļ one tw]'; @override - String commentAssign(String name) { - return '[Åššîĝñ ţö $name one]'; - } + String get badgeCommentOnly => '[Çöɱɱéñţ öñļý one]'; @override - String get commentDelete => '[Ðéļéţé one]'; + String get badgeOffline => '[Åṽåîļåƀļé öƒƒļîñé one tw]'; @override - String get commentDeleteThread => '[Ðéļéţé ţĥŕéåð one t]'; + String get badgeShared => '[Šĥåŕéð one]'; @override - String get commentDeleted => '[Çöɱɱéñţ ðéļéţéð one t]'; + String get badgeViewOnly => '[Ṽîéŵ öñļý one]'; @override - String get commentEdit => '[Éðîţ on]'; + String get categoryAccount => '[Åççöûñţ one]'; @override - String get commentEdited => '[éðîţéð one]'; + String get categoryComments => '[Çöɱɱéñţš one]'; @override - String get commentEventAssigned => '[åššîĝñéð ţĥé çöɱɱéñţ one two]'; + String get categoryDrive => '[Ðŕîṽé on]'; @override - String get commentEventOrphaned => - '[ðéļéţéð ţĥé çöɱɱéñţéð çöñţéñţ one two th]'; + String get categoryEdit => '[Éðîţ on]'; @override - String get commentEventOrphanedBySystem => - '[Ţĥé çöɱɱéñţéð çöñţéñţ ŵåš ðéļéţéð one two thr]'; + String get categoryFile => '[Ƒîļé on]'; @override - String get commentEventRestoredBySystem => - '[Ţĥé çöɱɱéñţéð çöñţéñţ ŵåš ŕéšţöŕéð one two thr]'; + String get categoryHelp => '[Ĥéļþ on]'; @override - String get commentEventReopened => '[ŕéöþéñéð one]'; + String get categoryNavigation => '[Ñåṽîĝåţîöñ one]'; @override - String get commentEventResolved => '[ɱåŕķéð åš ŕéšöļṽéð one tw]'; + String get categoryOther => '[Öţĥéŕ on]'; @override - String get commentEventSuggestionAccepted => - '[åççéþţéð ţĥé šûĝĝéšţîöñ one two]'; + String get categorySharing => '[Šĥåŕîñĝ one]'; @override - String get commentEventSuggestionRejected => - '[ŕéĵéçţéð ţĥé šûĝĝéšţîöñ one two]'; + String get categoryTools => '[Ţööļš on]'; @override - String get commentEventSuggestionReopened => - '[ŕéöþéñéð ţĥé šûĝĝéšţîöñ one two]'; + String get categoryVersions => '[Ṽéŕšîöñ ĥîšţöŕý one t]'; @override - String get commentEventSuggestionSuperseded => - '[ŕéþļåçéð ţĥé šûĝĝéšţîöñ one two]'; + String get categoryView => '[Ṽîéŵ on]'; @override - String get commentEventSuggestionWithdrawn => - '[ŵîţĥðŕéŵ ţĥé šûĝĝéšţîöñ one two]'; + String get cmdAbout => '[Åƀöûţ on]'; @override - String get commentFailed => '[Ţĥé çöɱɱéñţ çöûļð ñöţ ƀé šåṽéð one two t]'; + String get cmdAddShortcut => '[Åðð šĥöŕţçûţ ţö Ðŕîṽé one two]'; @override - String get commentPending => - '[Þéñðîñĝ — ŵîļļ ƀé þöšţéð ŵĥéñ ýöû\'ŕé öñļîñé one two three]'; + String cmdAppSettings(String app) { + return '[$app šéţţîñĝš one]'; + } @override - String get commentLink => '[Ļîñķ ţö çöɱɱéñţ one t]'; + String get cmdAssistant => '[Åššîšţåñţ one]'; @override - String get commentOrphaned => '[Öŕîĝîñåļ çöñţéñţ ðéļéţéð one two]'; + String get cmdAssistantNewThread => '[Ñéŵ åššîšţåñţ çĥåţ one tw]'; @override - String get commentPlaceholder => '[Çöɱɱéñţ öŕ åðð öţĥéŕš ŵîţĥ @ one two t]'; + String get cmdAssistantSend => '[Šéñð ţö åššîšţåñţ one tw]'; @override - String get commentShow => '[Šĥöŵ on]'; + String get cmdAssistantStop => '[Šţöþ åššîšţåñţ one t]'; @override - String commentsEmptyBody(String shortcut) { - return '[Šéļéçţ çöñţéñţ åñð þŕéšš $shortcut ţö åðð å çöɱɱéñţ. one two three]'; - } + String get cmdBack => '[Ɓåçķ on]'; @override - String get commentsEmptyTitle => '[Ñö çöɱɱéñţš ýéţ one t]'; + String get cmdClosePanel => '[Çļöšé þåñéļ one]'; @override - String get commentsForYou => '[Ƒöŕ ýöû one]'; + String get cmdCommandPalette => '[Çöɱɱåñð þåļéţţé one t]'; @override - String get commentsOpen => '[Öþéñ on]'; + String get cmdComment => '[Çöɱɱéñţ one]'; @override - String get commentsSort => '[Šöŕţ on]'; + String get cmdCommentsPanel => '[Çöɱɱéñţš one]'; @override - String get commentsSortDate => '[Šöŕţ ƀý ðåţé one]'; + String get cmdCopy => '[Çöþý on]'; @override - String get commentsSortPosition => '[Šöŕţ ƀý þöšîţîöñ one t]'; + String get cmdCopyLink => '[Çöþý ļîñķ one]'; @override - String get copyAction => '[Ṁåķé å çöþý one]'; + String get cmdCopyMcpConfig => '[Çöþý ṀÇÞ çöññéçţîöñ šéţţîñĝš one two t]'; @override - String get copyComments => '[Çöþý çöɱɱéñţš one t]'; + String get cmdCut => '[Çûţ on]'; @override - String get copyName => '[Ñåɱé on]'; + String get cmdDeleteComment => '[Ðéļéţé çöɱɱéñţ one t]'; @override - String copyOfName(String name) { - return '[Çöþý öƒ $name one]'; - } + String get cmdDeleteForever => '[Ðéļéţé ƒöŕéṽéŕ one t]'; @override - String get copySharing => '[Šĥåŕé îţ ŵîţĥ ţĥé šåɱé þéöþļé one two t]'; + String get cmdDetails => '[Ðéţåîļš one]'; @override - String get copyTitle => '[Ṁåķé å çöþý one]'; + String get cmdDownload => '[Ðöŵñļöåð one]'; @override - String get dateYesterday => '[Ýéšţéŕðåý one]'; + String get cmdEmptyTrash => '[Éɱþţý ţŕåšĥ one]'; @override - String get deleteAccountAction => '[Ðéļéţé åççöûñţ one t]'; + String get cmdFocusSearch => '[Šéåŕçĥ îñ Ðŕîṽé one t]'; @override - String deleteAccountBody(String email) { - return '[Ţĥîš þéŕɱåñéñţļý ðéļéţéš ýöûŕ åççöûñţ $email. Ţĥîš çåññöţ ƀé ûñðöñé. one two three four]'; - } + String get cmdForward => '[Ƒöŕŵåŕð one]'; @override - String deleteAccountConfirmLabel(String email) { - return '[Ţýþé $email ţö çöñƒîŕɱ one t]'; - } + String get cmdHome => '[Ĥöɱé on]'; @override - String deleteAccountCounts(int documents, int spreadsheets, int folders) { - return '[Ýöû öŵñ $documents ðöçûɱéñţš, $spreadsheets šþŕéåðšĥééţš åñð $folders ƒöļðéŕš. one two three]'; - } + String get cmdImport => '[Îɱþöŕţ… one]'; @override - String get deleteAccountHint => - '[Ðéļéţé ýöûŕ åççöûñţ åñð ţĥé ƒîļéš ýöû öŵñ. one two three]'; + String get cmdKeyboardShortcuts => '[Ķéýƀöåŕð šĥöŕţçûţš one tw]'; @override - String get deleteAccountMismatch => - '[Ţĥåţ\'š ñöţ ýöûŕ éɱåîļ åððŕéšš. one two th]'; + String get cmdMakeAvailableOffline => '[Ṁåķé åṽåîļåƀļé öƒƒļîñé one two]'; @override - String get deleteAccountTitle => '[Ðéļéţé åççöûñţ one t]'; + String get cmdMakeCopy => '[Ṁåķé å çöþý one]'; @override - String get deleteForeverAction => '[Ðéļéţé ƒöŕéṽéŕ one t]'; + String get cmdManageStorage => '[Ṁåñåĝé šţöŕåĝé one t]'; @override - String get deleteForeverBody => - '[Ţĥéšé îţéɱš ŵîļļ ƀé ðéļéţéð þéŕɱåñéñţļý. Ţĥîš çåñ\'ţ ƀé ûñðöñé. one two three four]'; + String get cmdMove => '[Ṁöṽé on]'; @override - String deleteForeverTitle(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: 'Ðéļéţé $count îţéɱš ƒöŕéṽéŕ?', - one: 'Ðéļéţé ƒöŕéṽéŕ?', - ); - return '[$_temp0 one two thre]'; - } + String get cmdMoveToTrash => '[Ṁöṽé ţö ţŕåšĥ one]'; @override - String get densityComfortable => '[Çöɱƒöŕţåƀļé one]'; + String get cmdNameCurrentVersion => '[Ñåɱé çûŕŕéñţ ṽéŕšîöñ one two]'; @override - String get densityCompact => '[Çöɱþåçţ one]'; + String get cmdNewDocument => '[Ñéŵ ðöçûɱéñţ one]'; @override - String get detailsAccess => '[Ŵĥö ĥåš åççéšš one t]'; + String get cmdNewFile => '[Ñéŵ ƒîļé one]'; @override - String get detailsActivity => '[Åçţîṽîţý one]'; + String get cmdNewFolder => '[Ñéŵ ƒöļðéŕ one]'; @override - String get detailsCreated => '[Çŕéåţéð one]'; + String get cmdNewFromTemplate => '[Ƒŕöɱ ţéɱþļåţé… one t]'; @override - String get detailsDescription => '[Ðéšçŕîþţîöñ one]'; + String get cmdNewSpreadsheet => '[Ñéŵ šþŕéåðšĥééţ one t]'; @override - String get detailsDescriptionHint => '[Åðð å ðéšçŕîþţîöñ one tw]'; + String get cmdNextPanel => '[Ñéẋţ þåñéļ one]'; @override - String get detailsLocation => '[Ļöçåţîöñ one]'; + String get cmdNextRegion => '[Ƒöçûš ñéẋţ ŕéĝîöñ one tw]'; @override - String get detailsModified => '[Ṁöðîƒîéð one]'; + String get cmdOpen => '[Öþéñ on]'; @override - String get detailsNothingSelected => - '[Šéļéçţ å ƒîļé ţö šéé îţš ðéţåîļš one two th]'; + String get cmdOpenComment => '[Öþéñ çöɱɱéñţ one]'; @override - String get detailsOpened => '[Öþéñéð ƀý ɱé one]'; + String get cmdOpenFile => '[Öþéñ… on]'; @override - String get detailsOwner => '[Öŵñéŕ on]'; + String get cmdOpenInDrive => '[Öþéñ îñ Ŵöñķý Ðŕîṽé one tw]'; @override - String get detailsPrivate => '[Þŕîṽåţé ţö ýöû one t]'; + String get cmdOpenPanel => '[Öþéñ þåñéļ one]'; @override - String get detailsRole => '[Ýöûŕ åççéšš one]'; + String get cmdOpenSheets => '[Öþéñ Ŵöñķý Šĥééţš one tw]'; @override - String get detailsShared => '[Šĥåŕéð one]'; + String get cmdOpenWrite => '[Öþéñ Ŵöñķý Ŵŕîţé one t]'; @override - String get detailsType => '[Ţýþé on]'; + String get cmdPaste => '[Þåšţé on]'; @override - String get driveListLabel => '[Ƒîļéš on]'; + String get cmdPastePlain => '[Þåšţé ŵîţĥöûţ ƒöŕɱåţţîñĝ one two]'; @override - String get driveOfflineBody => - '[Ƒîļéš ýöû öþéñéð ŕéçéñţļý öŕ ɱåðé åṽåîļåƀļé öƒƒļîñé åŕé ļîšţéð ŵĥéñ ýöû\'ŕé öƒƒļîñé. one two three four five s]'; + String get cmdPreviousPanel => '[Þŕéṽîöûš þåñéļ one t]'; @override - String get driveOfflineTitle => '[Ýöû\'ŕé öƒƒļîñé one t]'; + String get cmdPreviousRegion => '[Ƒöçûš þŕéṽîöûš ŕéĝîöñ one two]'; @override - String get dropToUpload => '[Ðŕöþ ƒîļéš ţö ûþļöåð one tw]'; + String get cmdPrint => '[Þŕîñţ on]'; @override - String get editorOfflineTitle => - '[Ţĥîš ƒîļé îšñ\'ţ åṽåîļåƀļé öƒƒļîñé one two thr]'; + String get cmdQuickSwitcher => '[Ĝö ţö ƒîļé… one]'; @override - String get emptyFolderBody => - '[Ðŕöþ ƒîļéš ĥéŕé öŕ ûšé ţĥé Ñéŵ ƀûţţöñ. one two thr]'; + String get cmdRedo => '[Ŕéðö on]'; @override - String get emptyFolderTitle => '[Ţĥîš ƒöļðéŕ îš éɱþţý one tw]'; + String cmdRedoLabel(String label) { + return '[Ŕéðö $label on]'; + } @override - String get emptyHomeBody => - '[Çŕéåţé å ðöçûɱéñţ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû. one two three]'; + String get cmdRename => '[Ŕéñåɱé one]'; @override - String get emptyHomeTitle => '[Ŵéļçöɱé ţö ýöûŕ ðŕîṽé one two]'; + String get cmdReopen => '[Ŕéöþéñ one]'; @override - String emptyAppHomeTitle(String appName) { - return '[Ŵéļçöɱé ţö $appName one]'; - } + String get cmdReply => '[Ŕéþļý on]'; @override - String emptyAppHomeBody(String kind) { - String _temp0 = intl.Intl.selectLogic(kind, { - 'spreadsheet': 'Çŕéåţé å šþŕéåðšĥééţ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû.', - 'presentation': 'Çŕéåţé å þŕéšéñţåţîöñ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû.', - 'all': 'Çŕéåţé å ðöçûɱéñţ, šþŕéåðšĥééţ öŕ þŕéšéñţåţîöñ, öŕ ûþļöåð ƒîļéš.', - 'other': 'Çŕéåţé å ðöçûɱéñţ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû.', - }); - return '[$_temp0 one two three four five six seven eight nine ten one two three]'; - } + String get cmdReportBug => '[Ŕéþöŕţ å ƀûĝ one]'; @override - String get emptyOfflineBody => - '[Ûšé “Ṁåķé åṽåîļåƀļé öƒƒļîñé” öñ ƒîļéš ýöû ñééð ŵîţĥöûţ å çöññéçţîöñ. one two three four fi]'; + String get cmdReportProblem => '[Ŕéþöŕţ å þŕöƀļéɱ one t]'; @override - String get emptyOfflineTitle => '[Ñö öƒƒļîñé ƒîļéš one t]'; + String get cmdRequestAccess => '[Ŕéǫûéšţ åççéšš one t]'; @override - String get emptySearchBody => - '[Ţŕý öţĥéŕ ŵöŕðš öŕ ƒéŵéŕ ƒîļţéŕš. one two th]'; + String get cmdResolve => '[Ŕéšöļṽé one]'; @override - String get emptySearchTitle => '[Ñö ŕéšûļţš one]'; + String get cmdRestore => '[Ŕéšţöŕé one]'; @override - String get emptySharedBody => - '[Ƒîļéš öţĥéŕš šĥåŕé ŵîţĥ ýöû ŵîļļ šĥöŵ ûþ ĥéŕé. one two three]'; + String get cmdRestoreVersion => '[Ŕéšţöŕé ţĥîš ṽéŕšîöñ one two]'; @override - String get emptySharedTitle => '[Ñöţĥîñĝ šĥåŕéð ŵîţĥ ýöû ýéţ one two t]'; + String get cmdSeeVersionHistory => '[Šéé ṽéŕšîöñ ĥîšţöŕý one tw]'; @override - String get emptyStarredBody => - '[Åðð šţåŕš ţö ţĥîñĝš ýöû ŵåñţ ţö ƒîñð éåšîļý ļåţéŕ. one two three f]'; + String get cmdSelectAll => '[Šéļéçţ åļļ one]'; @override - String get emptyStarredTitle => '[Ñö šţåŕŕéð ƒîļéš ýéţ one tw]'; + String get cmdSetDescription => '[Éðîţ ðéšçŕîþţîöñ one tw]'; @override - String get emptyTrashAction => '[Éɱþţý ţŕåšĥ one]'; + String get cmdSetTheme => '[Åþþ ţĥéɱé one]'; @override - String get emptyTrashBody => - '[Åļļ îţéɱš îñ ţĥé ţŕåšĥ ŵîļļ ƀé ðéļéţéð ƒöŕéṽéŕ. Ţĥîš çåñ\'ţ ƀé ûñðöñé. one two three four f]'; + String get cmdSettings => '[Šéţţîñĝš one]'; @override - String get emptyTrashTitle => '[Éɱþţý ţŕåšĥ? one]'; + String get cmdShare => '[Šĥåŕé on]'; @override - String get emptyTrashViewBody => - '[Îţéɱš îñ ţĥé ţŕåšĥ åŕé ðéļéţéð ƒöŕéṽéŕ åƒţéŕ 30 ðåýš. one two three fo]'; + String get cmdSignOut => '[Šîĝñ öûţ one]'; @override - String get emptyTrashViewTitle => '[Ţŕåšĥ îš éɱþţý one t]'; + String get cmdStar => '[Šţåŕ on]'; @override - String get errorBoundaryBody => - '[Ţĥîš þåŕţ öƒ ţĥé åþþ ĥîţ åñ ûñéẋþéçţéð éŕŕöŕ. Ýöûŕ ŵöŕķ îš šåṽéð. one two three four]'; + String get cmdStopAgent => '[Šţöþ åĝéñţ çöñţŕöļ one tw]'; @override - String get errorBoundaryTitle => '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ one two]'; + String get cmdTogglePanel => '[Ţöĝĝļé þåñéļ one]'; @override - String get errorCopyDetails => '[Çöþý éŕŕöŕ ðéţåîļš one tw]'; + String get cmdToggleUiBridge => + '[Åļļöŵ ṀÇÞ ţö çöñţŕöļ ţĥîš ŵîñðöŵ one two th]'; @override - String get errorGeneric => '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ one two]'; + String get cmdUndo => '[Ûñðö on]'; @override - String get errorNameSlash => '[Ñåɱéš çåñ\'ţ çöñţåîñ “/”. one two]'; + String get cmdUndoHistory => '[Ûñðö ĥîšţöŕý… one t]'; @override - String get errorNameTooLong => '[Ûšé åţ ɱöšţ 255 çĥåŕåçţéŕš. one two t]'; + String cmdUndoLabel(String label) { + return '[Ûñðö $label on]'; + } @override - String get errorRequired => '[Ŕéǫûîŕéð one]'; + String get cmdUndoTo => '[Ûñðö ţö šţéþ one]'; @override - String get expandFolders => '[Éẋþåñð ƒöļðéŕš one t]'; + String get cmdUnstar => '[Ŕéɱöṽé šţåŕ one]'; @override - String get externalLinkOpen => '[Öþéñ on]'; + String get cmdUpload => '[Ûþļöåð ƒîļé… one]'; @override - String get externalLinkTitle => '[Öþéñ éẋţéŕñåļ ļîñķ? one tw]'; + String get cmdVersionsPanel => '[Ṽéŕšîöñ ĥîšţöŕý þåñéļ one two]'; @override - String get fileCategoryArchives => '[Åŕçĥîṽéš one]'; + String get cmdWhatsNew => '[Ŵĥåţ\'š ñéŵ one]'; @override - String get fileCategoryAudio => '[Åûðîö on]'; + String get cmdWorkSettings => '[Ŵöñķý Ŵöŕķ šéţţîñĝš one tw]'; @override - String get fileCategoryImages => '[Îɱåĝéš one]'; + String get cmdZoom => '[Žööɱ on]'; @override - String get fileCategoryOther => '[Öţĥéŕ ƒîļéš one]'; + String get collapseFolders => '[Çöļļåþšé ƒöļðéŕš one tw]'; @override - String get fileCategoryPdfs => '[ÞÐƑš on]'; + String get columnModified => '[Ļåšţ ɱöðîƒîéð one t]'; @override - String get fileCategoryText => '[Ţéẋţ & çöðé one]'; + String get columnName => '[Ñåɱé on]'; @override - String get fileCategoryVideo => '[Ṽîðéöš one]'; + String get columnOwner => '[Öŵñéŕ on]'; @override - String get folderTree => '[Ƒöļðéŕš one]'; + String get columnSize => '[Ƒîļé šîžé one]'; @override - String get foldersOnTop => '[Ƒöļðéŕš öñ ţöþ one t]'; + String commandFailed(String title) { + return '[“$title” ƒåîļéð one]'; + } @override - String get goHome => '[Ĝö ţö Ĥöɱé one]'; + String get commentAction => '[Çöɱɱéñţ one]'; @override - String get groupEarlier => '[Éåŕļîéŕ one]'; + String commentAssign(String name) { + return '[Åššîĝñ ţö $name one]'; + } @override - String get groupThisWeek => '[Éåŕļîéŕ ţĥîš ŵééķ one tw]'; + String get commentDelete => '[Ðéļéţé one]'; @override - String get groupToday => '[Ţöðåý on]'; + String get commentDeleteThread => '[Ðéļéţé ţĥŕéåð one t]'; @override - String get groupYesterday => '[Ýéšţéŕðåý one]'; + String get commentDeleted => '[Çöɱɱéñţ ðéļéţéð one t]'; @override - String get historyBack => '[Ɓåçķ ţö éðîţîñĝ one t]'; + String get commentEdit => '[Éðîţ on]'; @override - String get historyNoRenderer => - '[Þŕéṽîéŵš öƒ ṽéŕšîöñš åŕéñ\'ţ åṽåîļåƀļé ƒöŕ ţĥîš ƒîļé ţýþé. one two three four]'; + String get commentEdited => '[éðîţéð one]'; @override - String get historyRestoreThis => '[Ŕéšţöŕé ţĥîš ṽéŕšîöñ one two]'; + String get commentEventAssigned => '[åššîĝñéð ţĥé çöɱɱéñţ one two]'; @override - String get historyShowChanges => '[Šĥöŵ çĥåñĝéš one]'; + String get commentEventOrphaned => + '[ðéļéţéð ţĥé çöɱɱéñţéð çöñţéñţ one two th]'; @override - String get importFailed => '[Ţĥé îɱþöŕţ ƒåîļéð one tw]'; + String get commentEventOrphanedBySystem => + '[Ţĥé çöɱɱéñţéð çöñţéñţ ŵåš ðéļéţéð one two thr]'; @override - String get importUnsupported => - '[Ţĥéšé ƒîļéš çåñ\'ţ ƀé îɱþöŕţéð ĥéŕé one two thr]'; + String get commentEventRestoredBySystem => + '[Ţĥé çöɱɱéñţéð çöñţéñţ ŵåš ŕéšţöŕéð one two thr]'; @override - String get inviteInvalid => '[Ţĥîš ļîñķ îš ñöţ ṽåļîð one two]'; + String get commentEventReopened => '[ŕéöþéñéð one]'; @override - String get inviteTitle => '[Öþéñîñĝ šĥåŕéð ƒîļé one tw]'; + String get commentEventResolved => '[ɱåŕķéð åš ŕéšöļṽéð one tw]'; @override - String get kindDocument => '[Ðöçûɱéñţ one]'; + String get commentEventSuggestionAccepted => + '[åççéþţéð ţĥé šûĝĝéšţîöñ one two]'; @override - String get kindFile => '[Ƒîļé on]'; + String get commentEventSuggestionRejected => + '[ŕéĵéçţéð ţĥé šûĝĝéšţîöñ one two]'; @override - String get kindFolder => '[Ƒöļðéŕ one]'; + String get commentEventSuggestionReopened => + '[ŕéöþéñéð ţĥé šûĝĝéšţîöñ one two]'; @override - String get kindPresentation => '[Þŕéšéñţåţîöñ one t]'; + String get commentEventSuggestionSuperseded => + '[ŕéþļåçéð ţĥé šûĝĝéšţîöñ one two]'; @override - String get kindSpreadsheet => '[Šþŕéåðšĥééţ one]'; - - @override - String get layoutGrid => '[Ĝŕîð ṽîéŵ one]'; + String get commentEventSuggestionWithdrawn => + '[ŵîţĥðŕéŵ ţĥé šûĝĝéšţîöñ one two]'; @override - String get layoutList => '[Ļîšţ ṽîéŵ one]'; + String get commentFailed => '[Ţĥé çöɱɱéñţ çöûļð ñöţ ƀé šåṽéð one two t]'; @override - String get mcpAllowControl => '[Åļļöŵ ṀÇÞ ţö çöñţŕöļ ţĥîš ŵîñðöŵ one two th]'; + String get commentPending => + '[Þéñðîñĝ — ŵîļļ ƀé þöšţéð ŵĥéñ ýöû\'ŕé öñļîñé one two three]'; @override - String get mcpControlling => - '[Åñ åĝéñţ îš çöñţŕöļļîñĝ ţĥîš ŵîñðöŵ one two thr]'; + String get commentLink => '[Ļîñķ ţö çöɱɱéñţ one t]'; @override - String get mcpHint => - '[Ûšé ţĥîš çöñƒîĝûŕåţîöñ îñ Çļåûðé Ðéšķţöþ öŕ Çļåûðé Çöðé ŵîţĥ öñé öƒ ýöûŕ ţöķéñš. one two three four five]'; + String get commentOrphaned => '[Öŕîĝîñåļ çöñţéñţ ðéļéţéð one two]'; @override - String get mcpTitle => '[ṀÇÞ çöññéçţîöñ one t]'; + String get commentPlaceholder => '[Çöɱɱéñţ öŕ åðð öţĥéŕš ŵîţĥ @ one two t]'; @override - String get menuAccessibility => '[Åççéššîƀîļîţý šéţţîñĝš one two]'; + String get commentShow => '[Šĥöŵ on]'; @override - String get menuAppTheme => '[Åþþ ţĥéɱé one]'; + String commentsEmptyBody(String shortcut) { + return '[Šéļéçţ çöñţéñţ åñð þŕéšš $shortcut ţö åðð å çöɱɱéñţ. one two three]'; + } @override - String get menuDownload => '[Ðöŵñļöåð one]'; + String get commentsEmptyTitle => '[Ñö çöɱɱéñţš ýéţ one t]'; @override - String get menuEdit => '[Éðîţ on]'; + String get commentsForYou => '[Ƒöŕ ýöû one]'; @override - String get menuExplore => '[Éẋþļöŕé one]'; + String get commentsOpen => '[Öþéñ on]'; @override - String get menuFile => '[Ƒîļé on]'; + String get commentsSort => '[Šöŕţ on]'; @override - String get menuFileUpload => '[Ƒîļé ûþļöåð one]'; + String get commentsSortDate => '[Šöŕţ ƀý ðåţé one]'; @override - String get menuHelp => '[Ĥéļþ on]'; + String get commentsSortPosition => '[Šöŕţ ƀý þöšîţîöñ one t]'; @override - String get menuImportFile => '[Îɱþöŕţ ƒîļé… one]'; + String get copyAction => '[Ṁåķé å çöþý one]'; @override - String get menuMakeCopy => '[Ṁåķé å çöþý one]'; + String get copyComments => '[Çöþý çöɱɱéñţš one t]'; @override - String get menuMode => '[Ṁöðé on]'; + String get copyName => '[Ñåɱé on]'; @override - String get menuNew => '[Ñéŵ on]'; + String copyOfName(String name) { + return '[Çöþý öƒ $name one]'; + } @override - String get menuNewDocument => '[Ðöçûɱéñţ one]'; + String get copySharing => '[Šĥåŕé îţ ŵîţĥ ţĥé šåɱé þéöþļé one two t]'; @override - String get menuNewPresentation => '[Þŕéšéñţåţîöñ one t]'; + String get copyTitle => '[Ṁåķé å çöþý one]'; @override - String get menuNewSpreadsheet => '[Šþŕéåðšĥééţ one]'; + String get dateYesterday => '[Ýéšţéŕðåý one]'; @override - String get menuOpenApp => '[Öþéñ on]'; + String get deleteAccountAction => '[Ðéļéţé åççöûñţ one t]'; @override - String get menuPanels => '[Þåñéļš one]'; + String deleteAccountBody(String email) { + return '[Ţĥîš þéŕɱåñéñţļý ðéļéţéš ýöûŕ åççöûñţ $email. Ţĥîš çåññöţ ƀé ûñðöñé. one two three four]'; + } @override - String get menuPreferences => '[Þŕéƒéŕéñçéš one]'; + String deleteAccountConfirmLabel(String email) { + return '[Ţýþé $email ţö çöñƒîŕɱ one t]'; + } @override - String get menuShare => '[Šĥåŕé on]'; + String deleteAccountCounts(int documents, int spreadsheets, int folders) { + return '[Ýöû öŵñ $documents ðöçûɱéñţš, $spreadsheets šþŕéåðšĥééţš åñð $folders ƒöļðéŕš. one two three]'; + } @override - String get menuTools => '[Ţööļš on]'; + String get deleteAccountHint => + '[Ðéļéţé ýöûŕ åççöûñţ åñð ţĥé ƒîļéš ýöû öŵñ. one two three]'; @override - String get menuVersionHistory => '[Ṽéŕšîöñ ĥîšţöŕý one t]'; + String get deleteAccountMismatch => + '[Ţĥåţ\'š ñöţ ýöûŕ éɱåîļ åððŕéšš. one two th]'; @override - String get menuView => '[Ṽîéŵ on]'; + String get deleteAccountTitle => '[Ðéļéţé åççöûñţ one t]'; @override - String get menuZoom => '[Žööɱ on]'; + String get deleteForeverAction => '[Ðéļéţé ƒöŕéṽéŕ one t]'; @override - String get menus => '[Ṁéñûš on]'; + String get deleteForeverBody => + '[Ţĥéšé îţéɱš ŵîļļ ƀé ðéļéţéð þéŕɱåñéñţļý. Ţĥîš çåñ\'ţ ƀé ûñðöñé. one two three four]'; @override - String get moreActions => '[Ṁöŕé åçţîöñš one]'; + String deleteForeverTitle(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'Ðéļéţé $count îţéɱš ƒöŕéṽéŕ?', + one: 'Ðéļéţé ƒöŕéṽéŕ?', + ); + return '[$_temp0 one two thre]'; + } @override - String get moveHere => '[Ṁöṽé ĥéŕé one]'; + String get densityComfortable => '[Çöɱƒöŕţåƀļé one]'; @override - String get moveNoFolders => '[Ñö ƒöļðéŕš ĥéŕé one t]'; + String get densityCompact => '[Çöɱþåçţ one]'; @override - String get moveNoPermission => - '[Ýöû ðöñ\'ţ ĥåṽé þéŕɱîššîöñ ţö åðð îţéɱš ţö ţĥîš ƒöļðéŕ. one two three fo]'; + String get detailsAccess => '[Ŵĥö ĥåš åççéšš one t]'; @override - String moveTitleMany(int count) { - return '[Ṁöṽé $count îţéɱš one]'; - } + String get detailsActivity => '[Åçţîṽîţý one]'; @override - String moveTitleOne(String name) { - return '[Ṁöṽé “$name” one]'; - } + String get detailsCreated => '[Çŕéåţéð one]'; @override - String get nameVersionLabel => '[Ṽéŕšîöñ ñåɱé one]'; + String get detailsDescription => '[Ðéšçŕîþţîöñ one]'; @override - String get nameVersionTitle => '[Ñåɱé ţĥîš ṽéŕšîöñ one tw]'; + String get detailsDescriptionHint => '[Åðð å ðéšçŕîþţîöñ one tw]'; @override - String get navApps => '[Åþþš on]'; + String get detailsLocation => '[Ļöçåţîöñ one]'; @override - String get navHome => '[Ĥöɱé on]'; + String get detailsModified => '[Ṁöðîƒîéð one]'; @override - String get navMyDrive => '[Ṁý Ðŕîṽé one]'; + String get detailsNothingSelected => + '[Šéļéçţ å ƒîļé ţö šéé îţš ðéţåîļš one two th]'; @override - String get navMyFiles => '[Ṁý ƒîļéš one]'; + String get detailsOpened => '[Öþéñéð ƀý ɱé one]'; @override - String get navOffline => '[Öƒƒļîñé one]'; + String get detailsOwner => '[Öŵñéŕ on]'; @override - String get navRecent => '[Ŕéçéñţ one]'; + String get detailsPrivate => '[Þŕîṽåţé ţö ýöû one t]'; @override - String get navShared => '[Šĥåŕéð ŵîţĥ ɱé one t]'; + String get detailsRole => '[Ýöûŕ åççéšš one]'; @override - String get navStarred => '[Šţåŕŕéð one]'; + String get detailsShared => '[Šĥåŕéð one]'; @override - String get navStorage => '[Šţöŕåĝé one]'; + String get detailsType => '[Ţýþé on]'; @override - String get navTrash => '[Ţŕåšĥ on]'; + String get driveListLabel => '[Ƒîļéš on]'; @override - String get newButton => '[Ñéŵ on]'; + String get driveOfflineBody => + '[Ƒîļéš ýöû öþéñéð ŕéçéñţļý öŕ ɱåðé åṽåîļåƀļé öƒƒļîñé åŕé ļîšţéð ŵĥéñ ýöû\'ŕé öƒƒļîñé. one two three four five s]'; @override - String get newFolderLabel => '[Ƒöļðéŕ ñåɱé one]'; + String get driveOfflineTitle => '[Ýöû\'ŕé öƒƒļîñé one t]'; @override - String get newFolderTitle => '[Ñéŵ ƒöļðéŕ one]'; + String get dropToUpload => '[Ðŕöþ ƒîļéš ţö ûþļöåð one tw]'; @override - String noAccessBody(String email) { - return '[Ýöû ñééð åççéšš ţö öþéñ ţĥîš ƒîļé. Ýöû\'ŕé šîĝñéð îñ åš $email. one two three fo]'; - } + String get editorOfflineTitle => + '[Ţĥîš ƒîļé îšñ\'ţ åṽåîļåƀļé öƒƒļîñé one two thr]'; @override - String get noAccessTitle => '[Ýöû ñééð åççéšš one t]'; + String get emptyFolderBody => + '[Ðŕöþ ƒîļéš ĥéŕé öŕ ûšé ţĥé Ñéŵ ƀûţţöñ. one two thr]'; @override - String get notAllowed => '[Ñöţ åļļöŵéð one]'; + String get emptyFolderTitle => '[Ţĥîš ƒöļðéŕ îš éɱþţý one tw]'; @override - String get notFoundBody => - '[Ţĥé þåĝé ýöû\'ŕé ļööķîñĝ ƒöŕ ðöéšñ\'ţ éẋîšţ. one two three]'; + String get emptyHomeBody => + '[Çŕéåţé å ðöçûɱéñţ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû. one two three]'; @override - String get notFoundTitle => '[Þåĝé ñöţ ƒöûñð one t]'; + String get emptyHomeTitle => '[Ŵéļçöɱé ţö ýöûŕ ðŕîṽé one two]'; @override - String notifAccessRequest(String who, String item) { - return '[$who åšķéð ƒöŕ åççéšš ţö $item one tw]'; + String emptyAppHomeTitle(String appName) { + return '[Ŵéļçöɱé ţö $appName one]'; } @override - String notifAssigned(String who, String item) { - return '[$who åššîĝñéð ýöû å çöɱɱéñţ îñ $item one two]'; + String emptyAppHomeBody(String kind) { + String _temp0 = intl.Intl.selectLogic(kind, { + 'spreadsheet': 'Çŕéåţé å šþŕéåðšĥééţ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû.', + 'presentation': 'Çŕéåţé å þŕéšéñţåţîöñ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû.', + 'all': 'Çŕéåţé å ðöçûɱéñţ, šþŕéåðšĥééţ öŕ þŕéšéñţåţîöñ, öŕ ûþļöåð ƒîļéš.', + 'other': 'Çŕéåţé å ðöçûɱéñţ öŕ öþéñ öñé šĥåŕéð ŵîţĥ ýöû.', + }); + return '[$_temp0 one two three four five six seven eight nine ten one two three]'; } @override - String notifMention(String who, String item) { - return '[$who ɱéñţîöñéð ýöû îñ $item one t]'; - } + String get emptyOfflineBody => + '[Ûšé “Ṁåķé åṽåîļåƀļé öƒƒļîñé” öñ ƒîļéš ýöû ñééð ŵîţĥöûţ å çöññéçţîöñ. one two three four fi]'; @override - String notifOwnership(String who, String item) { - return '[$who ŵåñţš ţö ɱåķé ýöû ţĥé öŵñéŕ öƒ $item one two t]'; - } + String get emptyOfflineTitle => '[Ñö öƒƒļîñé ƒîļéš one t]'; @override - String notifReply(String who, String item) { - return '[$who ŕéþļîéð îñ $item one]'; - } + String get emptySearchBody => + '[Ţŕý öţĥéŕ ŵöŕðš öŕ ƒéŵéŕ ƒîļţéŕš. one two th]'; @override - String notifScriptFailure(String item) { - return '[Å šçŕîþţ ƒåîļéð îñ $item one tw]'; - } + String get emptySearchTitle => '[Ñö ŕéšûļţš one]'; @override - String notifShared(String who, String item) { - return '[$who šĥåŕéð $item ŵîţĥ ýöû one t]'; - } + String get emptySharedBody => + '[Ƒîļéš öţĥéŕš šĥåŕé ŵîţĥ ýöû ŵîļļ šĥöŵ ûþ ĥéŕé. one two three]'; @override - String get notifStorage => - '[Ýöûŕ Ŵöñķý Ŵöŕķ šţöŕåĝé ñééðš åţţéñţîöñ one two thre]'; + String get emptySharedTitle => '[Ñöţĥîñĝ šĥåŕéð ŵîţĥ ýöû ýéţ one two t]'; @override - String notifBoardReply(String who, String title) { - return '[$who çöɱɱéñţéð öñ “$title” one t]'; - } + String get emptyStarredBody => + '[Åðð šţåŕš ţö ţĥîñĝš ýöû ŵåñţ ţö ƒîñð éåšîļý ļåţéŕ. one two three f]'; @override - String notifBoardUpdate(String title) { - return '[Ûþðåţé öñ “$title” one]'; - } + String get emptyStarredTitle => '[Ñö šţåŕŕéð ƒîļéš ýéţ one tw]'; @override - String notifSuggestion(String who, String item) { - return '[$who šûĝĝéšţéð åñ éðîţ îñ $item one tw]'; - } + String get emptyTrashAction => '[Éɱþţý ţŕåšĥ one]'; @override - String notifSuggestionDecided(String who, String item) { - return '[$who ŕéṽîéŵéð ýöûŕ šûĝĝéšţîöñ îñ $item one two t]'; - } + String get emptyTrashBody => + '[Åļļ îţéɱš îñ ţĥé ţŕåšĥ ŵîļļ ƀé ðéļéţéð ƒöŕéṽéŕ. Ţĥîš çåñ\'ţ ƀé ûñðöñé. one two three four f]'; @override - String get notificationsEmpty => '[Ýöû\'ŕé åļļ çåûĝĥţ ûþ one tw]'; + String get emptyTrashTitle => '[Éɱþţý ţŕåšĥ? one]'; @override - String get notificationsMarkAllRead => '[Ṁåŕķ åļļ åš ŕéåð one t]'; + String get emptyTrashViewBody => + '[Îţéɱš îñ ţĥé ţŕåšĥ åŕé ðéļéţéð ƒöŕéṽéŕ åƒţéŕ 30 ðåýš. one two three fo]'; @override - String get notificationsTitle => '[Ñöţîƒîçåţîöñš one t]'; + String get emptyTrashViewTitle => '[Ţŕåšĥ îš éɱþţý one t]'; @override - String notificationsUnread(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count ûñŕéåð ñöţîƒîçåţîöñš', - one: '1 ûñŕéåð ñöţîƒîçåţîöñ', - ); - return '[$_temp0 one two three]'; - } + String get errorBoundaryBody => + '[Ţĥîš þåŕţ öƒ ţĥé åþþ ĥîţ åñ ûñéẋþéçţéð éŕŕöŕ. Ýöûŕ ŵöŕķ îš šåṽéð. one two three four]'; @override - String get notifyEmail => '[Îñ-åþþ åñð éɱåîļ one t]'; + String get errorBoundaryTitle => '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ one two]'; @override - String get notifyInApp => '[Îñ-åþþ one]'; + String get errorCopyDetails => '[Çöþý éŕŕöŕ ðéţåîļš one tw]'; @override - String get notifyMentions => '[Ṁéñţîöñš one]'; + String get errorGeneric => '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ one two]'; @override - String get notifyOff => '[Öƒƒ on]'; + String get errorNameSlash => '[Ñåɱéš çåñ\'ţ çöñţåîñ “/”. one two]'; @override - String get notifyReplies => '[Ŕéþļîéš ţö ɱý çöɱɱéñţš one two]'; + String get errorNameTooLong => '[Ûšé åţ ɱöšţ 255 çĥåŕåçţéŕš. one two t]'; @override - String get notifyShares => '[Ƒîļéš šĥåŕéð ŵîţĥ ɱé one tw]'; + String get errorRequired => '[Ŕéǫûîŕéð one]'; @override - String get offlineBanner => - '[Ýöû\'ŕé öƒƒļîñé. Çĥåñĝéš åŕé šåṽéð öñ ţĥîš ðéṽîçé åñð ŵîļļ šýñç ŵĥéñ ýöû\'ŕé ƀåçķ öñļîñé. one two three four five si]'; + String get expandFolders => '[Éẋþåñð ƒöļðéŕš one t]'; @override - String get offlineClear => '[Çļéåŕ ļöçåļ ðåţå one t]'; + String get externalLinkOpen => '[Öþéñ on]'; @override - String get offlineClearHint => - '[Ŕéɱöṽéš çåçĥéð ƒîļéš åñð þéñðîñĝ çĥåñĝéš ƒŕöɱ ţĥîš ðéṽîçé. one two three four]'; + String get externalLinkTitle => '[Öþéñ éẋţéŕñåļ ļîñķ? one tw]'; @override - String get offlineCleared => '[Ļöçåļ ðåţå çļéåŕéð one tw]'; + String get fileCategoryArchives => '[Åŕçĥîṽéš one]'; @override - String get offlinePending => '[Çĥåñĝéš ŵåîţîñĝ ţö šýñç one two]'; + String get fileCategoryAudio => '[Åûðîö on]'; @override - String get badgeOfflineRecent => - '[Åṽåîļåƀļé öƒƒļîñé (öþéñéð ŕéçéñţļý) one two thre]'; + String get fileCategoryImages => '[Îɱåĝéš one]'; @override - String get badgeOfflinePending => '[Ðöŵñļöåðîñĝ ƒöŕ öƒƒļîñé ûšé… one two t]'; + String get fileCategoryOther => '[Öţĥéŕ ƒîļéš one]'; @override - String get offlineUnavailable => - '[Ţĥîš ƒîļé îšñ\'ţ åṽåîļåƀļé öƒƒļîñé one two thr]'; + String get fileCategoryPdfs => '[ÞÐƑš on]'; @override - String get offlineDocuments => '[Ƒîļéš öñ ţĥîš ðéṽîçé one tw]'; + String get fileCategoryText => '[Ţéẋţ & çöðé one]'; @override - String offlineDocumentsValue(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count ƒîļéš', - one: '1 ƒîļé', - zero: 'Ñöñé', - ); - return '[$_temp0 one t]'; - } + String get fileCategoryVideo => '[Ṽîðéöš one]'; @override - String offlinePinnedCount(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count ɱåðé åṽåîļåƀļé öƒƒļîñé', - one: '1 ɱåðé åṽåîļåƀļé öƒƒļîñé', - zero: 'Ñö ƒîļéš ɱåðé åṽåîļåƀļé öƒƒļîñé', - ); - return '[$_temp0 one two three four five]'; - } + String get folderTree => '[Ƒöļðéŕš one]'; @override - String get offlineUploads => '[Îɱåĝéš ŵåîţîñĝ ţö ûþļöåð one two]'; + String get foldersOnTop => '[Ƒöļðéŕš öñ ţöþ one t]'; @override - String get offlineStorageUsed => '[Šţöŕåĝé ûšéð one]'; + String get goHome => '[Ĝö ţö Ĥöɱé one]'; @override - String offlineClearUnsynced(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count çĥåñĝéš ĥåṽéñ\'ţ šýñçéð ýéţ åñð ŵîļļ ƀé ļöšţ.', - one: '1 çĥåñĝé ĥåšñ\'ţ šýñçéð ýéţ åñð ŵîļļ ƀé ļöšţ.', - ); - return '[$_temp0 one two three four five si]'; - } + String get groupEarlier => '[Éåŕļîéŕ one]'; @override - String get offlineSimulate => '[Šîɱûļåţé öƒƒļîñé one tw]'; + String get groupThisWeek => '[Éåŕļîéŕ ţĥîš ŵééķ one tw]'; @override - String get offlineSimulateHint => - '[Ðîšçöññéçţš ƒŕöɱ ţĥé šéŕṽéŕ ţö ţŕý öƒƒļîñé éðîţîñĝ (ðéṽéļöþéŕ šéţţîñĝ). one two three four fiv]'; + String get groupToday => '[Ţöðåý on]'; @override - String get ownerAnyone => '[Öŵñéð ƀý åñýöñé one t]'; + String get groupYesterday => '[Ýéšţéŕðåý one]'; @override - String get ownerMe => '[ɱé o]'; + String get historyBack => '[Ɓåçķ ţö éðîţîñĝ one t]'; @override - String get ownerMeFilter => '[Öŵñéð ƀý ɱé one]'; + String get historyNoRenderer => + '[Þŕéṽîéŵš öƒ ṽéŕšîöñš åŕéñ\'ţ åṽåîļåƀļé ƒöŕ ţĥîš ƒîļé ţýþé. one two three four]'; @override - String get ownerNotMe => '[Ñöţ öŵñéð ƀý ɱé one t]'; + String get historyRestoreThis => '[Ŕéšţöŕé ţĥîš ṽéŕšîöñ one two]'; @override - String get paletteAllCommands => '[Åļļ çöɱɱåñðš one]'; + String get historyShowChanges => '[Šĥöŵ çĥåñĝéš one]'; @override - String get paletteCommands => '[Çöɱɱåñðš one]'; + String get importFailed => '[Ţĥé îɱþöŕţ ƒåîļéð one tw]'; @override - String get paletteEmpty => '[Ñöţĥîñĝ ƒöûñð one t]'; + String get importUnsupported => + '[Ţĥéšé ƒîļéš çåñ\'ţ ƀé îɱþöŕţéð ĥéŕé one two thr]'; @override - String get paletteFiles => '[Ƒîļéš on]'; + String get inviteInvalid => '[Ţĥîš ļîñķ îš ñöţ ṽåļîð one two]'; @override - String get paletteGoToFile => '[Öþéñ ƒîļé one]'; + String get inviteTitle => '[Öþéñîñĝ šĥåŕéð ƒîļé one tw]'; @override - String get palettePlaceholder => - '[Ţýþé å çöɱɱåñð öŕ šéåŕçĥ ƒîļéš… one two th]'; + String get kindDocument => '[Ðöçûɱéñţ one]'; @override - String get paletteRecent => '[Ŕéçéñţ one]'; + String get kindFile => '[Ƒîļé on]'; @override - String get panelComments => '[Çöɱɱéñţš one]'; + String get kindFolder => '[Ƒöļðéŕ one]'; @override - String get panelHistory => '[Ṽéŕšîöñ ĥîšţöŕý one t]'; + String get kindPresentation => '[Þŕéšéñţåţîöñ one t]'; @override - String presenceJoined(String name) { - return '[$name ĵöîñéð one]'; - } + String get kindSpreadsheet => '[Šþŕéåðšĥééţ one]'; @override - String presenceLeft(String name) { - return '[$name ļéƒţ on]'; - } + String get layoutGrid => '[Ĝŕîð ṽîéŵ one]'; @override - String get quickSwitcherEmpty => '[Ñö ƒîļéš ƒöûñð one t]'; + String get layoutList => '[Ļîšţ ṽîéŵ one]'; @override - String get quickSwitcherPlaceholder => - '[Šéåŕçĥ ðöçûɱéñţš åñð šþŕéåðšĥééţš… one two thr]'; + String get mcpAllowControl => '[Åļļöŵ ṀÇÞ ţö çöñţŕöļ ţĥîš ŵîñðöŵ one two th]'; @override - String get quickSwitcherRecent => '[Ŕéçéñţ ƒîļéš one]'; + String get mcpControlling => + '[Åñ åĝéñţ îš çöñţŕöļļîñĝ ţĥîš ŵîñðöŵ one two thr]'; @override - String get quickSwitcherResults => '[Ŕéšûļţš one]'; + String get mcpHint => + '[Ûšé ţĥîš çöñƒîĝûŕåţîöñ îñ Çļåûðé Ðéšķţöþ öŕ Çļåûðé Çöðé ŵîţĥ öñé öƒ ýöûŕ ţöķéñš. one two three four five]'; @override - String get renameLabel => '[Ñåɱé on]'; + String get mcpTitle => '[ṀÇÞ çöññéçţîöñ one t]'; @override - String get renameTitle => '[Ŕéñåɱé one]'; + String get menuAccessibility => '[Åççéššîƀîļîţý šéţţîñĝš one two]'; @override - String get replyPlaceholder => '[Ŕéþļý öŕ åðð öţĥéŕš ŵîţĥ @ one two]'; + String get menuAppTheme => '[Åþþ ţĥéɱé one]'; @override - String get reportBugNote => - '[Κšûéš öñ ĜîţĤûƀ åŕé þûƀļîç: ðöñ\'ţ îñçļûðé þŕîṽåţé çöñţéñţ. one two three four]'; + String get menuDownload => '[Ðöŵñļöåð one]'; @override - String get requestAccessDescription => - '[Ţĥé öŵñéŕ ŵîļļ ƀé ñöţîƒîéð åñð çåñ šĥåŕé ţĥé ƒîļé ŵîţĥ ýöû. one two three fou]'; + String get menuEdit => '[Éðîţ on]'; @override - String get requestAccessFailed => '[Ţĥé ŕéǫûéšţ çöûļð ñöţ ƀé šéñţ one two t]'; + String get menuExplore => '[Éẋþļöŕé one]'; @override - String get requestAccessMessage => '[Ṁéššåĝé (öþţîöñåļ) one tw]'; + String get menuFile => '[Ƒîļé on]'; @override - String get requestAccessRole => '[Åççéšš one]'; + String get menuFileUpload => '[Ƒîļé ûþļöåð one]'; @override - String get requestAccessSend => '[Ŕéǫûéšţ åççéšš one t]'; + String get menuHelp => '[Ĥéļþ on]'; @override - String get requestAccessTitle => '[Ŕéǫûéšţ åççéšš one t]'; + String get menuImportFile => '[Îɱþöŕţ ƒîļé… one]'; @override - String get restoreVersionAction => '[Ŕéšţöŕé one]'; + String get menuMakeCopy => '[Ṁåķé å çöþý one]'; @override - String get restoreVersionBody => - '[Ţĥé çûŕŕéñţ ṽéŕšîöñ îš ķéþţ îñ ţĥé ĥîšţöŕý, šö ýöû çåñ šŵîţçĥ ƀåçķ åţ åñý ţîɱé. one two three four five]'; + String get menuMode => '[Ṁöðé on]'; @override - String get restoreVersionTitle => '[Ŕéšţöŕé ţĥîš ṽéŕšîöñ? one two]'; + String get menuNew => '[Ñéŵ on]'; @override - String get roleCommenter => '[Çöɱɱéñţéŕ one]'; + String get menuNewDocument => '[Ðöçûɱéñţ one]'; @override - String get roleEditor => '[Éðîţöŕ one]'; + String get menuNewPresentation => '[Þŕéšéñţåţîöñ one t]'; @override - String get roleOwner => '[Öŵñéŕ on]'; + String get menuNewSpreadsheet => '[Šþŕéåðšĥééţ one]'; @override - String get roleViewer => '[Ṽîéŵéŕ one]'; + String get menuOpenApp => '[Öþéñ on]'; @override - String get routeCreating => '[Çŕéåţîñĝ… one]'; + String get menuPanels => '[Þåñéļš one]'; @override - String get routeImportInvalid => - '[Ţĥîš ļîñķ ðöéšñ\'ţ ñåɱé å ƒîļé ţö îɱþöŕţ. one two thre]'; + String get menuPreferences => '[Þŕéƒéŕéñçéš one]'; @override - String get routeImporting => '[Îɱþöŕţîñĝ… one]'; + String get menuShare => '[Šĥåŕé on]'; @override - String searchAllDrive(String query) { - return '[Šéåŕçĥ åļļ öƒ Ŵöñķý Ðŕîṽé ƒöŕ “$query” one two th]'; - } + String get menuTools => '[Ţööļš on]'; @override - String searchFor(String query) { - return '[Šéåŕçĥ ƒöŕ “$query” one]'; - } + String get menuVersionHistory => '[Ṽéŕšîöñ ĥîšţöŕý one t]'; @override - String get searchHint => '[Šéåŕçĥ ƀý ñåɱé öŕ çöñţéñţ one two]'; + String get menuView => '[Ṽîéŵ on]'; @override - String get searchPlaceholder => '[Šéåŕçĥ îñ Ðŕîṽé one t]'; + String get menuZoom => '[Žööɱ on]'; @override - String searchResultsFor(String query) { - return '[Ŕéšûļţš ƒöŕ “$query” one t]'; - } + String get menus => '[Ṁéñûš on]'; @override - String selectedCount(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count šéļéçţéð', - one: '1 šéļéçţéð', - ); - return '[$_temp0 one tw]'; - } + String get moreActions => '[Ṁöŕé åçţîöñš one]'; @override - String get sessionExpiredBody => - '[Šîĝñ îñ åĝåîñ ţö çöñţîñûé. Ýöûŕ ŵöŕķ îš ķéþţ. one two three]'; + String get moveHere => '[Ṁöṽé ĥéŕé one]'; @override - String get sessionExpiredTitle => '[Ýöûŕ šéššîöñ éẋþîŕéð one two]'; + String get moveNoFolders => '[Ñö ƒöļðéŕš ĥéŕé one t]'; @override - String get settingsAbout => '[Åƀöûţ on]'; + String get moveNoPermission => + '[Ýöû ðöñ\'ţ ĥåṽé þéŕɱîššîöñ ţö åðð îţéɱš ţö ţĥîš ƒöļðéŕ. one two three fo]'; @override - String get settingsAccent => '[Åççéñţ çöļöŕ one]'; + String moveTitleMany(int count) { + return '[Ṁöṽé $count îţéɱš one]'; + } @override - String get settingsAccentNeutral => '[Ñéûţŕåļ one]'; + String moveTitleOne(String name) { + return '[Ṁöṽé “$name” one]'; + } @override - String get settingsAccount => '[Åççöûñţ one]'; + String get nameVersionLabel => '[Ṽéŕšîöñ ñåɱé one]'; @override - String get settingsAi => '[ÅÎ o]'; + String get nameVersionTitle => '[Ñåɱé ţĥîš ṽéŕšîöñ one tw]'; @override - String get settingsAiProviders => '[ÅÎ þŕöṽîðéŕš one]'; + String get navApps => '[Åþþš on]'; @override - String get settingsAiHint => - '[Ţĥé åššîšţåñţ ĥéļþš ýöû ŵŕîţé åñð åñåļýžé. Îţ öñļý šééš ƒîļéš ýöû öþéñ ŵîţĥ îţ. one two three four five]'; + String get navHome => '[Ĥöɱé on]'; @override - String get settingsAppearance => '[Åþþéåŕåñçé one]'; + String get navMyDrive => '[Ṁý Ðŕîṽé one]'; @override - String get settingsChangePassword => '[Çĥåñĝé þåššŵöŕð one t]'; + String get navMyFiles => '[Ṁý ƒîļéš one]'; @override - String get settingsDensity => '[Ðéñšîţý one]'; + String get navOffline => '[Öƒƒļîñé one]'; @override - String get settingsDeveloper => '[Ðéṽéļöþéŕ & ṀÇÞ one t]'; + String get navRecent => '[Ŕéçéñţ one]'; @override - String get settingsServerTitle => '[Šéŕṽéŕ one]'; + String get navShared => '[Šĥåŕéð ŵîţĥ ɱé one t]'; @override - String get settingsRedis => '[Ŕéðîš on]'; + String get navStarred => '[Šţåŕŕéð one]'; @override - String get settingsRedisHint => - '[Ṁéššåĝîñĝ ƀéţŵééñ šéŕṽéŕ îñšţåñçéš; ñééðéð ŵĥéñ ɱöŕé ţĥåñ öñé ŕûñš. one two three four fi]'; + String get navStorage => '[Šţöŕåĝé one]'; @override - String get redisConnected => '[Çöññéçţéð one]'; + String get navTrash => '[Ţŕåšĥ on]'; @override - String get redisNotReachable => '[Ñöţ ŕéåçĥåƀļé one t]'; + String get newButton => '[Ñéŵ on]'; @override - String get redisNotConfigured => '[Ñöţ çöñƒîĝûŕéð one t]'; + String get newFolderLabel => '[Ƒöļðéŕ ñåɱé one]'; @override - String get settingsKeyboard => '[Ķéýƀöåŕð šĥöŕţçûţš one tw]'; + String get newFolderTitle => '[Ñéŵ ƒöļðéŕ one]'; @override - String get settingsLanguage => '[Ļåñĝûåĝé & ŕéĝîöñ one tw]'; + String noAccessBody(String email) { + return '[Ýöû ñééð åççéšš ţö öþéñ ţĥîš ƒîļé. Ýöû\'ŕé šîĝñéð îñ åš $email. one two three fo]'; + } @override - String get settingsLanguageHint => - '[Ûšéð ƒöŕ ðåţéš, ñûɱƀéŕš åñð ñéŵ šþŕéåðšĥééţš. one two three]'; + String get noAccessTitle => '[Ýöû ñééð åççéšš one t]'; @override - String get settingsLayout => '[Ļåýöûţ one]'; + String get notAllowed => '[Ñöţ åļļöŵéð one]'; @override - String get settingsNotifications => '[Ñöţîƒîçåţîöñš one t]'; + String get notFoundBody => + '[Ţĥé þåĝé ýöû\'ŕé ļööķîñĝ ƒöŕ ðöéšñ\'ţ éẋîšţ. one two three]'; @override - String get settingsOffline => '[Öƒƒļîñé & ðéṽîçé ðåţå one two]'; + String get notFoundTitle => '[Þåĝé ñöţ ƒöûñð one t]'; @override - String get settingsOfflineHint => - '[Ƒîļéš ýöû öþéñ ŕéçéñţļý šţåý åṽåîļåƀļé öñ ţĥîš ðéṽîçé. one two three fou]'; + String notifAccessRequest(String who, String item) { + return '[$who åšķéð ƒöŕ åççéšš ţö $item one tw]'; + } @override - String get settingsPasswordHint => - '[Ŵé\'ļļ éɱåîļ ýöû å çöðé ţö šéţ å ñéŵ þåššŵöŕð. one two three]'; + String notifAssigned(String who, String item) { + return '[$who åššîĝñéð ýöû å çöɱɱéñţ îñ $item one two]'; + } @override - String get settingsProfile => '[Þŕöƒîļé one]'; + String notifMention(String who, String item) { + return '[$who ɱéñţîöñéð ýöû îñ $item one t]'; + } @override - String get settingsReduceMotion => '[Ŕéðûçé ɱöţîöñ one t]'; + String notifOwnership(String who, String item) { + return '[$who ŵåñţš ţö ɱåķé ýöû ţĥé öŵñéŕ öƒ $item one two t]'; + } @override - String get settingsReduceMotionHint => - '[Ţûŕñš öƒƒ ñöñ-éššéñţîåļ åñîɱåţîöñš. one two thre]'; + String notifReply(String who, String item) { + return '[$who ŕéþļîéð îñ $item one]'; + } @override - String get settingsAccountProfile => '[Åççöûñţ & þŕöƒîļé one tw]'; + String notifScriptFailure(String item) { + return '[Å šçŕîþţ ƒåîļéð îñ $item one tw]'; + } @override - String settingsOpeningOtherApp(String settings) { - return '[Öþéñîñĝ $settings… one]'; + String notifShared(String who, String item) { + return '[$who šĥåŕéð $item ŵîţĥ ýöû one t]'; } @override - String get settingsOtherApps => '[Šéţţîñĝš öƒ öţĥéŕ åþþš one two]'; + String get notifStorage => + '[Ýöûŕ Ŵöñķý Ŵöŕķ šţöŕåĝé ñééðš åţţéñţîöñ one two thre]'; @override - String get settingsSectionPicker => '[Šéţţîñĝš šéçţîöñ one tw]'; + String notifBoardReply(String who, String title) { + return '[$who çöɱɱéñţéð öñ “$title” one t]'; + } @override - String get settingsStorage => '[Šţöŕåĝé one]'; + String notifBoardUpdate(String title) { + return '[Ûþðåţé öñ “$title” one]'; + } @override - String get settingsStorageDocuments => '[Ðöçûɱéñţš one]'; + String notifSuggestion(String who, String item) { + return '[$who šûĝĝéšţéð åñ éðîţ îñ $item one tw]'; + } @override - String get settingsStorageFiles => '[Ƒîļéš on]'; + String notifSuggestionDecided(String who, String item) { + return '[$who ŕéṽîéŵéð ýöûŕ šûĝĝéšţîöñ îñ $item one two t]'; + } @override - String get settingsStorageLoading => '[Ļöåðîñĝ šţöŕåĝé… one tw]'; + String get notificationsEmpty => '[Ýöû\'ŕé åļļ çåûĝĥţ ûþ one tw]'; @override - String get settingsStorageManage => - '[Ṁåñåĝé šţöŕåĝé îñ Ŵöñķý Ðŕîṽé one two t]'; + String get notificationsMarkAllRead => '[Ṁåŕķ åļļ åš ŕéåð one t]'; @override - String get settingsStoragePresentations => '[Þŕéšéñţåţîöñš one t]'; + String get notificationsTitle => '[Ñöţîƒîçåţîöñš one t]'; @override - String get settingsStorageQuota => '[Ýöûŕ šţöŕåĝé one]'; + String notificationsUnread(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ûñŕéåð ñöţîƒîçåţîöñš', + one: '1 ûñŕéåð ñöţîƒîçåţîöñ', + ); + return '[$_temp0 one two three]'; + } @override - String get settingsStorageQuotaHint => - '[Öñé ǫûöţå ƒöŕ åļļ Ŵöñķý Ŵöŕķ åþþš. one two th]'; + String get notifyEmail => '[Îñ-åþþ åñð éɱåîļ one t]'; @override - String get settingsStorageSpreadsheets => '[Šþŕéåðšĥééţš one t]'; + String get notifyInApp => '[Îñ-åþþ one]'; @override - String get settingsStorageTrash => '[Ţŕåšĥ on]'; + String get notifyMentions => '[Ṁéñţîöñš one]'; @override - String get settingsStorageUnavailable => - '[Šţöŕåĝé ûšåĝé îšñ\'ţ åṽåîļåƀļé ŕîĝĥţ ñöŵ. one two three]'; + String get notifyOff => '[Öƒƒ on]'; @override - String get settingsStorageWhatCounts => '[Ŵĥåţ çöûñţš one]'; + String get notifyReplies => '[Ŕéþļîéš ţö ɱý çöɱɱéñţš one two]'; @override - String get settingsStorageWhatCountsBody => - '[Ðöçûɱéñţš, šþŕéåðšĥééţš, þŕéšéñţåţîöñš, ûþļöåðéð ƒîļéš åñð îɱåĝéš îñ ýöûŕ ƒîļéš, îñçļûðîñĝ ţĥé ţŕåšĥ. Ṽéŕšîöñ ĥîšţöŕý, ţĥûɱƀñåîļš åñð éẋþöŕţš ðöñ\'ţ çöûñţ. Ƒîļéš šĥåŕéð ŵîţĥ ýöû çöûñţ åĝåîñšţ ţĥéîŕ öŵñéŕ\'š šţöŕåĝé. one two three four five six seven eight nine ten one two three fo]'; + String get notifyShares => '[Ƒîļéš šĥåŕéð ŵîţĥ ɱé one tw]'; @override - String get shortcutsGroupShared => '[Šĥåŕéð one]'; + String get offlineBanner => + '[Ýöû\'ŕé öƒƒļîñé. Çĥåñĝéš åŕé šåṽéð öñ ţĥîš ðéṽîçé åñð ŵîļļ šýñç ŵĥéñ ýöû\'ŕé ƀåçķ öñļîñé. one two three four five si]'; @override - String get settingsSaved => '[Šåṽéð on]'; + String get offlineClear => '[Çļéåŕ ļöçåļ ðåţå one t]'; @override - String get settingsSecurity => '[Šîĝñ-îñ & šéçûŕîţý one tw]'; + String get offlineClearHint => + '[Ŕéɱöṽéš çåçĥéð ƒîļéš åñð þéñðîñĝ çĥåñĝéš ƒŕöɱ ţĥîš ðéṽîçé. one two three four]'; @override - String get settingsSheets => '[Ŵöñķý Šĥééţš one]'; + String get offlineCleared => '[Ļöçåļ ðåţå çļéåŕéð one tw]'; @override - String get settingsSignOutHint => - '[Šîĝñš ýöû öûţ öƒ Ŵöñķý Ŵöŕķ öñ ţĥîš ðéṽîçé. one two three]'; + String get offlinePending => '[Çĥåñĝéš ŵåîţîñĝ ţö šýñç one two]'; @override - String get settingsTheme => '[Ţĥéɱé on]'; + String get badgeOfflineRecent => + '[Åṽåîļåƀļé öƒƒļîñé (öþéñéð ŕéçéñţļý) one two thre]'; @override - String get settingsTimeZone => '[Ţîɱé žöñé one]'; + String get badgeOfflinePending => '[Ðöŵñļöåðîñĝ ƒöŕ öƒƒļîñé ûšé… one two t]'; @override - String get settingsTimeZoneHint => - '[ÎÅÑÅ ñåɱé, é.ĝ. Éûŕöþé/Šţöçķĥöļɱ. Éɱþţý ƒöļļöŵš ţĥîš ðéṽîçé. one two three four]'; + String get offlineUnavailable => + '[Ţĥîš ƒîļé îšñ\'ţ åṽåîļåƀļé öƒƒļîñé one two thr]'; @override - String get settingsUiLanguage => '[Ļåñĝûåĝé one]'; + String get offlineDocuments => '[Ƒîļéš öñ ţĥîš ðéṽîçé one tw]'; @override - String get settingsWrite => '[Ŵöñķý Ŵŕîţé one]'; + String offlineDocumentsValue(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ƒîļéš', + one: '1 ƒîļé', + zero: 'Ñöñé', + ); + return '[$_temp0 one t]'; + } @override - String get shareAddPeople => '[Åðð þéöþļé ƀý ñåɱé öŕ éɱåîļ one two]'; + String offlinePinnedCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ɱåðé åṽåîļåƀļé öƒƒļîñé', + one: '1 ɱåðé åṽåîļåƀļé öƒƒļîñé', + zero: 'Ñö ƒîļéš ɱåðé åṽåîļåƀļé öƒƒļîñé', + ); + return '[$_temp0 one two three four five]'; + } @override - String get shareAnyoneWithLink => '[Åñýöñé ŵîţĥ ţĥé ļîñķ one tw]'; + String get offlineUploads => '[Îɱåĝéš ŵåîţîñĝ ţö ûþļöåð one two]'; @override - String get shareApprove => '[Åþþŕöṽé one]'; + String get offlineStorageUsed => '[Šţöŕåĝé ûšéð one]'; @override - String get shareButton => '[Šĥåŕé on]'; + String offlineClearUnsynced(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count çĥåñĝéš ĥåṽéñ\'ţ šýñçéð ýéţ åñð ŵîļļ ƀé ļöšţ.', + one: '1 çĥåñĝé ĥåšñ\'ţ šýñçéð ýéţ åñð ŵîļļ ƀé ļöšţ.', + ); + return '[$_temp0 one two three four five si]'; + } @override - String get shareCannotShare => - '[Öñļý ţĥé öŵñéŕ åñð éðîţöŕš çåñ šĥåŕé ţĥîš ƒîļé. one two three]'; + String get offlineSimulate => '[Šîɱûļåţé öƒƒļîñé one tw]'; @override - String get shareDeny => '[Ðéñý on]'; + String get offlineSimulateHint => + '[Ðîšçöññéçţš ƒŕöɱ ţĥé šéŕṽéŕ ţö ţŕý öƒƒļîñé éðîţîñĝ (ðéṽéļöþéŕ šéţţîñĝ). one two three four fiv]'; @override - String get shareFailed => - '[Ţĥé šĥåŕîñĝ çĥåñĝé çöûļð ñöţ ƀé šåṽéð one two thr]'; + String get ownerAnyone => '[Öŵñéð ƀý åñýöñé one t]'; @override - String get shareGeneralAccess => '[Ĝéñéŕåļ åççéšš one t]'; + String get ownerMe => '[ɱé o]'; @override - String shareInherited(String folder) { - return '[Ƒŕöɱ ƒöļðéŕ “$folder” one t]'; - } + String get ownerMeFilter => '[Öŵñéð ƀý ɱé one]'; @override - String get shareLinkHint => - '[Åñýöñé šîĝñéð îñ ŵĥö ĥåš ţĥé ļîñķ çåñ öþéñ îţ one two three]'; + String get ownerNotMe => '[Ñöţ öŵñéð ƀý ɱé one t]'; @override - String get shareMessage => '[Ṁéššåĝé one]'; + String get paletteAllCommands => '[Åļļ çöɱɱåñðš one]'; @override - String get shareNotify => '[Ñöţîƒý þéöþļé one t]'; + String get paletteCommands => '[Çöɱɱåñðš one]'; @override - String get sharePending => '[Þéñðîñĝ îñṽîţé one t]'; + String get paletteEmpty => '[Ñöţĥîñĝ ƒöûñð one t]'; @override - String get sharePeopleWithAccess => '[Þéöþļé ŵîţĥ åççéšš one tw]'; + String get paletteFiles => '[Ƒîļéš on]'; @override - String get shareRemoveAccess => '[Ŕéɱöṽé åççéšš one t]'; + String get paletteGoToFile => '[Öþéñ ƒîļé one]'; @override - String shareRemoveBody(String name) { - return '[$name ŵîļļ ļöšé åççéšš ţö ţĥîš ƒîļé. one two t]'; - } + String get palettePlaceholder => + '[Ţýþé å çöɱɱåñð öŕ šéåŕçĥ ƒîļéš… one two th]'; @override - String shareRemoveRecipient(String email) { - return '[Ŕéɱöṽé $email one]'; - } + String get paletteRecent => '[Ŕéçéñţ one]'; @override - String get shareRemoveTitle => '[Ŕéɱöṽé åççéšš? one t]'; + String get panelComments => '[Çöɱɱéñţš one]'; @override - String shareRequestTitle(String name, String role) { - return '[$name ŕéǫûéšţš $role åççéšš one t]'; - } + String get panelHistory => '[Ṽéŕšîöñ ĥîšţöŕý one t]'; @override - String get shareRestricted => '[Ŕéšţŕîçţéð one]'; + String presenceJoined(String name) { + return '[$name ĵöîñéð one]'; + } @override - String get shareRestrictedHint => - '[Öñļý þéöþļé ŵîţĥ åççéšš çåñ öþéñ ŵîţĥ ţĥé ļîñķ one two three]'; + String presenceLeft(String name) { + return '[$name ļéƒţ on]'; + } @override - String get shareRotateLink => '[Ŕéšéţ ļîñķ one]'; + String get quickSwitcherEmpty => '[Ñö ƒîļéš ƒöûñð one t]'; @override - String shareSent(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: 'Šĥåŕéð ŵîţĥ $count þéöþļé', - one: 'Šĥåŕéð ŵîţĥ 1 þéŕšöñ', - ); - return '[$_temp0 one two thre]'; - } + String get quickSwitcherPlaceholder => + '[Šéåŕçĥ ðöçûɱéñţš åñð šþŕéåðšĥééţš… one two thr]'; @override - String get shareSettingComments => '[Ṽîéŵéŕš çåñ šéé çöɱɱéñţš one two]'; + String get quickSwitcherRecent => '[Ŕéçéñţ ƒîļéš one]'; @override - String get shareSettingEditors => - '[Éðîţöŕš çåñ çĥåñĝé þéŕɱîššîöñš åñð šĥåŕé one two three]'; + String get quickSwitcherResults => '[Ŕéšûļţš one]'; @override - String get shareSettingExport => - '[Ṽîéŵéŕš åñð çöɱɱéñţéŕš çåñ ðöŵñļöåð, þŕîñţ åñð çöþý one two three fo]'; + String get renameLabel => '[Ñåɱé on]'; @override - String get shareSettingsTitle => '[Šĥåŕîñĝ šéţţîñĝš one tw]'; + String get renameTitle => '[Ŕéñåɱé one]'; @override - String shareTitle(String name) { - return '[Šĥåŕé “$name” one]'; - } + String get replyPlaceholder => '[Ŕéþļý öŕ åðð öţĥéŕš ŵîţĥ @ one two]'; @override - String shareTransferBody(String name) { - return '[$name ƀéçöɱéš ţĥé öŵñéŕ öñçé ţĥéý åççéþţ. Ýöû\'ļļ šţåý åñ éðîţöŕ. one two three four]'; - } + String get reportBugNote => + '[Κšûéš öñ ĜîţĤûƀ åŕé þûƀļîç: ðöñ\'ţ îñçļûðé þŕîṽåţé çöñţéñţ. one two three four]'; @override - String get shareTransferOwnership => '[Ţŕåñšƒéŕ öŵñéŕšĥîþ one tw]'; + String get requestAccessDescription => + '[Ţĥé öŵñéŕ ŵîļļ ƀé ñöţîƒîéð åñð çåñ šĥåŕé ţĥé ƒîļé ŵîţĥ ýöû. one two three fou]'; @override - String shareTransferSent(String name) { - return '[Öŵñéŕšĥîþ ţŕåñšƒéŕ šéñţ ţö $name one two t]'; - } + String get requestAccessFailed => '[Ţĥé ŕéǫûéšţ çöûļð ñöţ ƀé šéñţ one two t]'; @override - String get shareTransferTitle => '[Ţŕåñšƒéŕ öŵñéŕšĥîþ? one two]'; + String get requestAccessMessage => '[Ṁéššåĝé (öþţîöñåļ) one tw]'; @override - String shareYou(String name) { - return '[$name (ýöû) on]'; - } + String get requestAccessRole => '[Åççéšš one]'; @override - String get sheetsAutocomplete => '[Ƒöŕɱûļå šûĝĝéšţîöñš one two]'; + String get requestAccessSend => '[Ŕéǫûéšţ åççéšš one t]'; @override - String get sheetsFormulaHelp => '[Šĥöŵ ƒöŕɱûļå ĥéļþ one tw]'; + String get requestAccessTitle => '[Ŕéǫûéšţ åççéšš one t]'; @override - String get sheetsScripts => '[Åļļöŵ šçŕîþţš one t]'; + String get restoreVersionAction => '[Ŕéšţöŕé one]'; @override - String shortcutConflictBody(String keys, String commands) { - return '[$keys îš åļŕéåðý ûšéð ƀý $commands. Ŕéþļåçé îţ? one two th]'; - } + String get restoreVersionBody => + '[Ţĥé çûŕŕéñţ ṽéŕšîöñ îš ķéþţ îñ ţĥé ĥîšţöŕý, šö ýöû çåñ šŵîţçĥ ƀåçķ åţ åñý ţîɱé. one two three four five]'; @override - String get shortcutConflictTitle => '[Šĥöŕţçûţ îñ ûšé one t]'; + String get restoreVersionTitle => '[Ŕéšţöŕé ţĥîš ṽéŕšîöñ? one two]'; @override - String get shortcutReplace => '[Ŕéþļåçé one]'; + String get roleCommenter => '[Çöɱɱéñţéŕ one]'; @override - String get shortcutReserved => - '[Ţĥé ƀŕöŵšéŕ ŕéšéŕṽéš ţĥîš šĥöŕţçûţ. one two thr]'; + String get roleEditor => '[Éðîţöŕ one]'; @override - String get shortcutReset => '[Ŕéšéţ ţö ðéƒåûļţ one t]'; + String get roleOwner => '[Öŵñéŕ on]'; @override - String get shortcutResetAll => '[Ŕéšéţ åļļ one]'; + String get roleViewer => '[Ṽîéŵéŕ one]'; @override - String get shortcutsSearch => '[Šéåŕçĥ šĥöŕţçûţš one tw]'; + String get routeCreating => '[Çŕéåţîñĝ… one]'; @override - String get shortcutsTitle => '[Ķéýƀöåŕð šĥöŕţçûţš one tw]'; + String get routeImportInvalid => + '[Ţĥîš ļîñķ ðöéšñ\'ţ ñåɱé å ƒîļé ţö îɱþöŕţ. one two thre]'; @override - String get someone => '[Šöɱéöñé one]'; + String get routeImporting => '[Îɱþöŕţîñĝ… one]'; @override - String sortBy(String field) { - return '[Šöŕţ: $field on]'; + String searchAllDrive(String query) { + return '[Šéåŕçĥ åļļ öƒ Ŵöñķý Ðŕîṽé ƒöŕ “$query” one two th]'; } @override - String get sortCreated => '[Çŕéåţéð one]'; + String searchFor(String query) { + return '[Šéåŕçĥ ƒöŕ “$query” one]'; + } @override - String get sortDescending => '[Ðéšçéñðîñĝ one]'; + String get searchHint => '[Šéåŕçĥ ƀý ñåɱé öŕ çöñţéñţ one two]'; @override - String get sortModified => '[Ļåšţ ɱöðîƒîéð one t]'; + String get searchPlaceholder => '[Šéåŕçĥ îñ Ðŕîṽé one t]'; @override - String get sortModifiedByMe => '[Ļåšţ ɱöðîƒîéð ƀý ɱé one tw]'; + String searchResultsFor(String query) { + return '[Ŕéšûļţš ƒöŕ “$query” one t]'; + } @override - String get sortName => '[Ñåɱé on]'; - - @override - String get sortOpenedByMe => '[Ļåšţ öþéñéð ƀý ɱé one t]'; + String selectedCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count šéļéçţéð', + one: '1 šéļéçţéð', + ); + return '[$_temp0 one tw]'; + } @override - String get sortSize => '[Ƒîļé šîžé one]'; + String get sessionExpiredBody => + '[Šîĝñ îñ åĝåîñ ţö çöñţîñûé. Ýöûŕ ŵöŕķ îš ķéþţ. one two three]'; @override - String storageMeterValue(String usage, int percent) { - return '[$usage, $percent þéŕçéñţ one]'; - } + String get sessionExpiredTitle => '[Ýöûŕ šéššîöñ éẋþîŕéð one two]'; @override - String storageUsed(String size) { - return '[$size ûšéð on]'; - } + String get settingsAbout => '[Åƀöûţ on]'; @override - String storageUsedOf(String used, String quota) { - return '[$used öƒ $quota ûšéð one]'; - } + String get settingsAccent => '[Åççéñţ çöļöŕ one]'; @override - String storageUsedOfOver(String used, String quota) { - return '[$used öƒ $quota ûšéð — öṽéŕ ǫûöţå one tw]'; - } + String get settingsAccentNeutral => '[Ñéûţŕåļ one]'; @override - String get storageCalculating => '[Çåļçûļåţîñĝ šţöŕåĝé… one two]'; + String get settingsAccount => '[Åççöûñţ one]'; @override - String get storageMeterTooltip => - '[Šţöŕåĝé îš šĥåŕéð ƀý Ŵöñķý Ðŕîṽé, Ŵŕîţé, Šĥééţš åñð Šļîðéš. one two three four]'; + String get settingsAi => '[ÅÎ o]'; @override - String get storageMeterTooltipOffline => - '[Šţöŕåĝé îš šĥåŕéð ƀý Ŵöñķý Ðŕîṽé, Ŵŕîţé, Šĥééţš åñð Šļîðéš. (öƒƒļîñé) one two three four fi]'; + String get settingsAiProviders => '[ÅÎ þŕöṽîðéŕš one]'; @override - String storageBannerWarning(String used, String quota) { - return '[Ýöû\'ṽé ûšéð $used öƒ ýöûŕ $quota šţöŕåĝé. one two t]'; - } + String get settingsAiHint => + '[Ţĥé åššîšţåñţ ĥéļþš ýöû ŵŕîţé åñð åñåļýžé. Îţ öñļý šééš ƒîļéš ýöû öþéñ ŵîţĥ îţ. one two three four five]'; @override - String get storageBannerOver => - '[Ýöû\'ŕé öûţ öƒ šţöŕåĝé. Ýöû çåñ ķééþ éðîţîñĝ, ƀûţ ýöû çåñ\'ţ ûþļöåð ƒîļéš, åðð îɱåĝéš, îɱþöŕţ, öŕ ɱåķé çöþîéš ûñţîļ ýöû ƒŕéé ûþ šþåçé. one two three four five six seven eight]'; + String get settingsAppearance => '[Åþþéåŕåñçé one]'; @override - String get storageBannerDismiss => '[Ðîšɱîšš one]'; + String get settingsChangePassword => '[Çĥåñĝé þåššŵöŕð one t]'; @override - String get quotaOwnTitle => '[Ýöû\'ŕé öûţ öƒ šţöŕåĝé one two]'; + String get settingsDensity => '[Ðéñšîţý one]'; @override - String quotaOwnBody(String needed, String available, String quota) { - return '[Ţĥîš ñééðš $needed, ƀûţ ýöû ĥåṽé $available ļéƒţ öƒ ýöûŕ $quota. Ƒŕéé ûþ šþåçé îñ Ŵöñķý Ðŕîṽé ƀý ðéļéţîñĝ ƒîļéš ýöû ñö ļöñĝéŕ ñééð åñð éɱþţýîñĝ ţĥé ţŕåšĥ. one two three four five six seven eig]'; - } + String get settingsDeveloper => '[Ðéṽéļöþéŕ & ṀÇÞ one t]'; @override - String quotaOwnBodyUnknown(String available, String quota) { - return '[Ýöû ĥåṽé $available ļéƒţ öƒ ýöûŕ $quota. Ƒŕéé ûþ šþåçé îñ Ŵöñķý Ðŕîṽé ƀý ðéļéţîñĝ ƒîļéš ýöû ñö ļöñĝéŕ ñééð åñð éɱþţýîñĝ ţĥé ţŕåšĥ. one two three four five six seve]'; - } + String get settingsServerTitle => '[Šéŕṽéŕ one]'; @override - String quotaOwnerTitle(String owner) { - return '[$owner îš öûţ öƒ šţöŕåĝé one t]'; - } + String get settingsRedis => '[Ŕéðîš on]'; @override - String quotaOwnerImageBody(String kind, String owner) { - String _temp0 = intl.Intl.selectLogic(kind, { - 'spreadsheet': - 'Îɱåĝéš åððéð ţö ţĥîš šþŕéåðšĥééţ çöûñţ åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé, öŕ åðð ţĥé îɱåĝé ţö å šþŕéåðšĥééţ ýöû öŵñ.', - 'presentation': - 'Îɱåĝéš åððéð ţö ţĥîš þŕéšéñţåţîöñ çöûñţ åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé, öŕ åðð ţĥé îɱåĝé ţö å þŕéšéñţåţîöñ ýöû öŵñ.', - 'other': - 'Îɱåĝéš åððéð ţö ţĥîš ðöçûɱéñţ çöûñţ åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé, öŕ åðð ţĥé îɱåĝé ţö å ðöçûɱéñţ ýöû öŵñ.', - }); - return '[$_temp0 one two three four five six seven eight nine ten one two three four five six seven eight nine ten one two three fo]'; - } + String get settingsRedisHint => + '[Ṁéššåĝîñĝ ƀéţŵééñ šéŕṽéŕ îñšţåñçéš; ñééðéð ŵĥéñ ɱöŕé ţĥåñ öñé ŕûñš. one two three four fi]'; @override - String quotaOwnerBody(String owner) { - return '[Çöñţéñţ åððéð ţö ţĥîš ƒîļé çöûñţš åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé ƒîŕšţ. one two three four five six]'; - } + String get redisConnected => '[Çöññéçţéð one]'; @override - String get quotaBatchTitle => '[Ñöţ éñöûĝĥ šţöŕåĝé ƒöŕ åļļ ƒîļéš one two th]'; + String get redisNotReachable => '[Ñöţ ŕéåçĥåƀļé one t]'; @override - String quotaBatchBody(int count, String needed, String available) { - return '[Ţĥéšé $count ƒîļéš ñééð $needed, ƀûţ ýöû ĥåṽé $available ļéƒţ. Ûþļöåð ţĥé ƒîļéš ţĥåţ ƒîţ, öŕ ƒŕéé ûþ šþåçé ƒîŕšţ. one two three four five s]'; - } + String get redisNotConfigured => '[Ñöţ çöñƒîĝûŕéð one t]'; @override - String get quotaBatchFit => '[Ûþļöåð ţĥé ƒîļéš ţĥåţ ƒîţ one two]'; + String get settingsKeyboard => '[Ķéýƀöåŕð šĥöŕţçûţš one tw]'; @override - String quotaTransferTitle(String name) { - return '[$name ðöéšñ\'ţ ĥåṽé éñöûĝĥ šţöŕåĝé one two t]'; - } + String get settingsLanguage => '[Ļåñĝûåĝé & ŕéĝîöñ one tw]'; @override - String quotaTransferBody(String name, String needed, String item) { - return '[$name ñééðš $needed ƒŕéé ţö ţåķé öŵñéŕšĥîþ öƒ “$item”. Åšķ ţĥéɱ ţö ƒŕéé ûþ šþåçé ƒîŕšţ. one two three four f]'; - } + String get settingsLanguageHint => + '[Ûšéð ƒöŕ ðåţéš, ñûɱƀéŕš åñð ñéŵ šþŕéåðšĥééţš. one two three]'; @override - String get quotaTransferAcceptTitle => - '[Ýöû ðöñ\'ţ ĥåṽé éñöûĝĥ šţöŕåĝé one two t]'; + String get settingsLayout => '[Ļåýöûţ one]'; @override - String quotaTransferAcceptBody(String item, String needed, String available) { - return '[Ţåķîñĝ öŵñéŕšĥîþ öƒ “$item” ñééðš $needed, ƀûţ ýöû ĥåṽé $available ļéƒţ. one two three]'; - } + String get settingsNotifications => '[Ñöţîƒîçåţîöñš one t]'; @override - String get quotaTooLargeTitle => '[Ţĥîš ƒîļé îš ţöö ļåŕĝé one two]'; + String get settingsOffline => '[Öƒƒļîñé & ðéṽîçé ðåţå one two]'; @override - String quotaTooLargeBody(String max) { - return '[Ƒîļéš çåñ ƀé åţ ɱöšţ $max. one tw]'; - } + String get settingsOfflineHint => + '[Ƒîļéš ýöû öþéñ ŕéçéñţļý šţåý åṽåîļåƀļé öñ ţĥîš ðéṽîçé. one two three fou]'; @override - String quotaTooLargeNowBody(String max) { - return '[Ƒîļéš çåñ ƀé åţ ɱöšţ $max ŕîĝĥţ ñöŵ, ƀéçåûšé ţĥåţ\'š ĥöŵ ɱûçĥ šţöŕåĝé ýöû ĥåṽé ļéƒţ. one two three four five]'; - } + String get settingsPasswordHint => + '[Ŵé\'ļļ éɱåîļ ýöû å çöðé ţö šéţ å ñéŵ þåššŵöŕð. one two three]'; @override - String get quotaItemFallback => '[ţĥîš îţéɱ one]'; + String get settingsProfile => '[Þŕöƒîļé one]'; @override - String get strengthEmpty => '[Éñţéŕ å þåššŵöŕð one t]'; + String get settingsReduceMotion => '[Ŕéðûçé ɱöţîöñ one t]'; @override - String get strengthFair => '[Ƒåîŕ on]'; + String get settingsReduceMotionHint => + '[Ţûŕñš öƒƒ ñöñ-éššéñţîåļ åñîɱåţîöñš. one two thre]'; @override - String get strengthGood => '[Ĝööð on]'; + String get settingsAccountProfile => '[Åççöûñţ & þŕöƒîļé one tw]'; @override - String strengthLabel(String label) { - return '[Þåššŵöŕð šţŕéñĝţĥ: $label one tw]'; + String settingsOpeningOtherApp(String settings) { + return '[Öþéñîñĝ $settings… one]'; } @override - String get strengthStrong => '[Šţŕöñĝ one]'; + String get settingsOtherApps => '[Šéţţîñĝš öƒ öţĥéŕ åþþš one two]'; @override - String get strengthWeak => '[Ŵéåķ on]'; + String get settingsSectionPicker => '[Šéţţîñĝš šéçţîöñ one tw]'; @override - String get switchAccount => '[Šŵîţçĥ åççöûñţ one t]'; + String get settingsStorage => '[Šţöŕåĝé one]'; @override - String get templateBlank => '[Ɓļåñķ on]'; + String get settingsStorageDocuments => '[Ðöçûɱéñţš one]'; @override - String get templateEducation => '[Éðûçåţîöñ one]'; + String get settingsStorageFiles => '[Ƒîļéš on]'; @override - String get templateFinance => '[Ƒîñåñçé one]'; + String get settingsStorageLoading => '[Ļöåðîñĝ šţöŕåĝé… one tw]'; @override - String get templateGallery => '[Ţéɱþļåţé ĝåļļéŕý one tw]'; + String get settingsStorageManage => + '[Ṁåñåĝé šţöŕåĝé îñ Ŵöñķý Ðŕîṽé one two t]'; @override - String get templatePersonal => '[Þéŕšöñåļ one]'; + String get settingsStoragePresentations => '[Þŕéšéñţåţîöñš one t]'; @override - String get templateProjectManagement => '[Þŕöĵéçţ ɱåñåĝéɱéñţ one tw]'; + String get settingsStorageQuota => '[Ýöûŕ šţöŕåĝé one]'; @override - String templateStripTitle(String kind) { - return '[Šţåŕţ å ñéŵ $kind one]'; - } + String get settingsStorageQuotaHint => + '[Öñé ǫûöţå ƒöŕ åļļ Ŵöñķý Ŵöŕķ åþþš. one two th]'; @override - String get templateWork => '[Ŵöŕķ on]'; + String get settingsStorageSpreadsheets => '[Šþŕéåðšĥééţš one t]'; @override - String get templatesHide => '[Ĥîðé ţéɱþļåţéš one t]'; + String get settingsStorageTrash => '[Ţŕåšĥ on]'; @override - String get templatesShow => '[Šĥöŵ ţéɱþļåţéš one t]'; + String get settingsStorageUnavailable => + '[Šţöŕåĝé ûšåĝé îšñ\'ţ åṽåîļåƀļé ŕîĝĥţ ñöŵ. one two three]'; @override - String get themeDark => '[Ðåŕķ on]'; + String get settingsStorageWhatCounts => '[Ŵĥåţ çöûñţš one]'; @override - String get themeLight => '[Ļîĝĥţ on]'; + String get settingsStorageWhatCountsBody => + '[Ðöçûɱéñţš, šþŕéåðšĥééţš, þŕéšéñţåţîöñš, ûþļöåðéð ƒîļéš åñð îɱåĝéš îñ ýöûŕ ƒîļéš, îñçļûðîñĝ ţĥé ţŕåšĥ. Ṽéŕšîöñ ĥîšţöŕý, ţĥûɱƀñåîļš åñð éẋþöŕţš ðöñ\'ţ çöûñţ. Ƒîļéš šĥåŕéð ŵîţĥ ýöû çöûñţ åĝåîñšţ ţĥéîŕ öŵñéŕ\'š šţöŕåĝé. one two three four five six seven eight nine ten one two three fo]'; @override - String get themeSystem => '[Šýšţéɱ one]'; + String get shortcutsGroupShared => '[Šĥåŕéð one]'; @override - String themeToggleTooltip(String mode) { - return '[Ţĥéɱé: $mode one]'; - } + String get settingsSaved => '[Šåṽéð on]'; @override - String timeHoursAgo(int hours) { - return '[$hours ĥ åĝö on]'; - } + String get settingsSecurity => '[Šîĝñ-îñ & šéçûŕîţý one tw]'; @override - String get timeJustNow => '[Ĵûšţ ñöŵ one]'; + String get settingsSheets => '[Ŵöñķý Šĥééţš one]'; @override - String timeMinutesAgo(int minutes) { - return '[$minutes ɱîñ åĝö one]'; - } + String get settingsSignOutHint => + '[Šîĝñš ýöû öûţ öƒ Ŵöñķý Ŵöŕķ öñ ţĥîš ðéṽîçé. one two three]'; @override - String get toastAccessRequested => '[Ŕéǫûéšţ šéñţ one]'; + String get settingsTheme => '[Ţĥéɱé on]'; @override - String toastCopyCreated(String name) { - return '[Çŕéåţéð “$name” one]'; - } + String get settingsTimeZone => '[Ţîɱé žöñé one]'; @override - String get toastLinkCopied => '[Ļîñķ çöþîéð one]'; + String get settingsTimeZoneHint => + '[ÎÅÑÅ ñåɱé, é.ĝ. Éûŕöþé/Šţöçķĥöļɱ. Éɱþţý ƒöļļöŵš ţĥîš ðéṽîçé. one two three four]'; @override - String get toastMcpConfigCopied => '[ṀÇÞ šéţţîñĝš çöþîéð one tw]'; + String get settingsUiLanguage => '[Ļåñĝûåĝé one]'; @override - String toastMovedToTrash(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count îţéɱš ɱöṽéð ţö ţŕåšĥ', - one: 'Ṁöṽéð ţö ţŕåšĥ', - ); - return '[$_temp0 one two thr]'; - } + String get settingsWrite => '[Ŵöñķý Ŵŕîţé one]'; @override - String get toastOfflineOpFailed => - '[Å çĥåñĝé ɱåðé öƒƒļîñé çöûļð ñöţ ƀé åþþļîéð one two three]'; + String get shareAddPeople => '[Åðð þéöþļé ƀý ñåɱé öŕ éɱåîļ one two]'; @override - String get toastShortcutAdded => '[Šĥöŕţçûţ åððéð one t]'; + String get shareAnyoneWithLink => '[Åñýöñé ŵîţĥ ţĥé ļîñķ one tw]'; @override - String get toastUndoPartial => - '[Šöɱé çĥåñĝéš çöûļðñ\'ţ ƀé ûñðöñé ƀéçåûšé ţĥéý ŵéŕé éðîţéð ƀý šöɱéöñé éļšé. one two three four fiv]'; + String get shareApprove => '[Åþþŕöṽé one]'; @override - String toastVersionNamed(String name) { - return '[Šåṽéð ṽéŕšîöñ “$name” one t]'; - } + String get shareButton => '[Šĥåŕé on]'; @override - String get toastVersionRestored => '[Ṽéŕšîöñ ŕéšţöŕéð one tw]'; + String get shareCannotShare => + '[Öñļý ţĥé öŵñéŕ åñð éðîţöŕš çåñ šĥåŕé ţĥîš ƒîļé. one two three]'; @override - String get toggleSidebar => '[Ṁåîñ ɱéñû one]'; + String get shareDeny => '[Ðéñý on]'; @override - String get tokenCopyOnce => - '[Çöþý ţĥîš ţöķéñ ñöŵ. Ýöû ŵöñ\'ţ šéé îţ åĝåîñ. one two three]'; + String get shareFailed => + '[Ţĥé šĥåŕîñĝ çĥåñĝé çöûļð ñöţ ƀé šåṽéð one two thr]'; @override - String get tokenCreate => '[Çŕéåţé ţöķéñ one]'; + String get shareGeneralAccess => '[Ĝéñéŕåļ åççéšš one t]'; @override - String get tokenName => '[Ţöķéñ ñåɱé one]'; + String shareInherited(String folder) { + return '[Ƒŕöɱ ƒöļðéŕ “$folder” one t]'; + } @override - String get tokenRevoke => '[Ŕéṽöķé one]'; + String get shareLinkHint => + '[Åñýöñé šîĝñéð îñ ŵĥö ĥåš ţĥé ļîñķ çåñ öþéñ îţ one two three]'; @override - String get tokenRevoked => '[ŕéṽöķéð one]'; + String get shareMessage => '[Ṁéššåĝé one]'; @override - String get tokensEmpty => '[Ñö ţöķéñš ýéţ. one t]'; + String get shareNotify => '[Ñöţîƒý þéöþļé one t]'; @override - String get tokensHint => - '[Þéŕšöñåļ åççéšš ţöķéñš ļéţ ṀÇÞ çļîéñţš åçţ åš ýöû. one two three f]'; + String get sharePending => '[Þéñðîñĝ îñṽîţé one t]'; @override - String get tokensTitle => '[Þéŕšöñåļ åççéšš ţöķéñš one two]'; + String get sharePeopleWithAccess => '[Þéöþļé ŵîţĥ åççéšš one tw]'; @override - String get trashedBanner => '[Ţĥîš ƒîļé îš îñ ţĥé ţŕåšĥ. one two]'; + String get shareRemoveAccess => '[Ŕéɱöṽé åççéšš one t]'; @override - String get typeAll => '[Åļļ ţýþéš one]'; + String shareRemoveBody(String name) { + return '[$name ŵîļļ ļöšé åççéšš ţö ţĥîš ƒîļé. one two t]'; + } @override - String get typeAllFiles => '[Åļļ ƒîļéš one]'; + String shareRemoveRecipient(String email) { + return '[Ŕéɱöṽé $email one]'; + } @override - String get typeDocuments => '[Ðöçûɱéñţš one]'; + String get shareRemoveTitle => '[Ŕéɱöṽé åççéšš? one t]'; @override - String get typeFiles => '[Ƒîļéš on]'; + String shareRequestTitle(String name, String role) { + return '[$name ŕéǫûéšţš $role åççéšš one t]'; + } @override - String get typeFolders => '[Ƒöļðéŕš one]'; + String get shareRestricted => '[Ŕéšţŕîçţéð one]'; @override - String get typePresentations => '[Þŕéšéñţåţîöñš one t]'; + String get shareRestrictedHint => + '[Öñļý þéöþļé ŵîţĥ åççéšš çåñ öþéñ ŵîţĥ ţĥé ļîñķ one two three]'; @override - String get typeSpreadsheets => '[Šþŕéåðšĥééţš one t]'; + String get shareRotateLink => '[Ŕéšéţ ļîñķ one]'; @override - String get undoHistoryEmpty => '[Ñöţĥîñĝ ţö ûñðö one t]'; + String shareSent(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'Šĥåŕéð ŵîţĥ $count þéöþļé', + one: 'Šĥåŕéð ŵîţĥ 1 þéŕšöñ', + ); + return '[$_temp0 one two thre]'; + } @override - String get undoHistoryTitle => '[Ûñðö ĥîšţöŕý one]'; + String get shareSettingComments => '[Ṽîéŵéŕš çåñ šéé çöɱɱéñţš one two]'; @override - String get untitledFolder => '[Ûñţîţļéð ƒöļðéŕ one t]'; + String get shareSettingEditors => + '[Éðîţöŕš çåñ çĥåñĝé þéŕɱîššîöñš åñð šĥåŕé one two three]'; @override - String get versionNewAvailable => '[Å ñéŵ ṽéŕšîöñ îš åṽåîļåƀļé one two]'; + String get shareSettingExport => + '[Ṽîéŵéŕš åñð çöɱɱéñţéŕš çåñ ðöŵñļöåð, þŕîñţ åñð çöþý one two three fo]'; @override - String get versionsEmpty => '[Ñö ṽéŕšîöñš ýéţ one t]'; + String get shareSettingsTitle => '[Šĥåŕîñĝ šéţţîñĝš one tw]'; @override - String get versionsName => '[Ñåɱé ţĥîš ṽéŕšîöñ one tw]'; + String shareTitle(String name) { + return '[Šĥåŕé “$name” one]'; + } @override - String get versionsNamedOnly => '[Öñļý ñåɱéð ṽéŕšîöñš one tw]'; + String shareTransferBody(String name) { + return '[$name ƀéçöɱéš ţĥé öŵñéŕ öñçé ţĥéý åççéþţ. Ýöû\'ļļ šţåý åñ éðîţöŕ. one two three four]'; + } @override - String get versionsOpenFull => '[Öþéñ ƒûļļ ĥîšţöŕý one tw]'; + String get shareTransferOwnership => '[Ţŕåñšƒéŕ öŵñéŕšĥîþ one tw]'; @override - String get versionsRename => '[Ŕéñåɱé ṽéŕšîöñ one t]'; + String shareTransferSent(String name) { + return '[Öŵñéŕšĥîþ ţŕåñšƒéŕ šéñţ ţö $name one two t]'; + } @override - String get versionsRestorePoint => '[Ɓéƒöŕé ŕéšţöŕé one t]'; + String get shareTransferTitle => '[Ţŕåñšƒéŕ öŵñéŕšĥîþ? one two]'; @override - String get whatsNew1 => - '[Öñé åççöûñţ ƒöŕ Ŵöñķý Ŵŕîţé åñð Ŵöñķý Šĥééţš — šîĝñ îñ öñçé, ûšé ƀöţĥ. one two three four f]'; + String shareYou(String name) { + return '[$name (ýöû) on]'; + } @override - String get whatsNew2 => - '[Éṽéŕý åçţîöñ îš å çöɱɱåñð: þŕéšš Çţŕļ+Šĥîƒţ+Þ (⌘⇧Þ) ţö ŕûñ åñýţĥîñĝ. one two three four fi]'; + String get sheetsAutocomplete => '[Ƒöŕɱûļå šûĝĝéšţîöñš one two]'; @override - String get whatsNew3 => - '[Ûñðö çöṽéŕš ðŕîṽé çĥåñĝéš ţöö — ŕéñåɱé, ɱöṽé, šţåŕ åñð ţŕåšĥ. one two three four]'; + String get sheetsFormulaHelp => '[Šĥöŵ ƒöŕɱûļå ĥéļþ one tw]'; @override - String get whatsNew4 => - '[Çöɱɱéñţš, ɱéñţîöñš åñð ṽéŕšîöñ ĥîšţöŕý îñ éṽéŕý ƒîļé. one two three fou]'; + String get sheetsScripts => '[Åļļöŵ šçŕîþţš one t]'; @override - String get whatsNewTitle => '[Ŵĥåţ\'š ñéŵ one]'; + String shortcutConflictBody(String keys, String commands) { + return '[$keys îš åļŕéåðý ûšéð ƀý $commands. Ŕéþļåçé îţ? one two th]'; + } @override - String get wonkyWork => '[Ŵöñķý Ŵöŕķ one]'; + String get shortcutConflictTitle => '[Šĥöŕţçûţ îñ ûšé one t]'; @override - String get writeAutoPair => '[Åûţö-þåîŕ ƀŕåçķéţš åñð ǫûöţéš one two th]'; + String get shortcutReplace => '[Ŕéþļåçé one]'; @override - String get writeExportFormat => '[Ðéƒåûļţ ðöŵñļöåð ƒöŕɱåţ one two]'; + String get shortcutReserved => + '[Ţĥé ƀŕöŵšéŕ ŕéšéŕṽéš ţĥîš šĥöŕţçûţ. one two thr]'; @override - String get writeMarkdownShortcuts => '[Ṁåŕķðöŵñ šĥöŕţçûţš one tw]'; + String get shortcutReset => '[Ŕéšéţ ţö ðéƒåûļţ one t]'; @override - String get writePageless => '[Þåĝéļéšš ƀý ðéƒåûļţ one tw]'; + String get shortcutResetAll => '[Ŕéšéţ åļļ one]'; @override - String get writeSmartQuotes => '[Šɱåŕţ ǫûöţéš one]'; + String get shortcutsSearch => '[Šéåŕçĥ šĥöŕţçûţš one tw]'; @override - String get writeSpellcheck => '[Šþéļļçĥéçķ one]'; + String get shortcutsTitle => '[Ķéýƀöåŕð šĥöŕţçûţš one tw]'; @override - String get youHaveCommentAccess => '[Ýöû ĥåṽé çöɱɱéñţ åççéšš one two]'; + String get someone => '[Šöɱéöñé one]'; @override - String get youHaveViewAccess => '[Ýöû ĥåṽé ṽîéŵ åççéšš one tw]'; + String sortBy(String field) { + return '[Šöŕţ: $field on]'; + } @override - String get assistantNewChat => '[Ñéŵ çĥåţ one]'; + String get sortCreated => '[Çŕéåţéð one]'; @override - String get assistantClearChat => '[Çļéåŕ çĥåţ one]'; + String get sortDescending => '[Ðéšçéñðîñĝ one]'; @override - String get assistantDeleteChat => '[Ðéļéţé ţĥîš çĥåţ one t]'; + String get sortModified => '[Ļåšţ ɱöðîƒîéð one t]'; @override - String get assistantDeleteChatFailed => '[Çöûļðñ\'ţ ðéļéţé ţĥé çĥåţ one two]'; + String get sortModifiedByMe => '[Ļåšţ ɱöðîƒîéð ƀý ɱé one tw]'; @override - String get assistantAiSettings => '[ÅÎ šéţţîñĝš one]'; + String get sortName => '[Ñåɱé on]'; @override - String get assistantOpenAiSettings => '[Öþéñ ÅÎ šéţţîñĝš one t]'; + String get sortOpenedByMe => '[Ļåšţ öþéñéð ƀý ɱé one t]'; @override - String get assistantEmptyTitle => - '[Åšķ åƀöûţ ţĥîš ðöçûɱéñţ öŕ ţéļļ ţĥé åššîšţåñţ ŵĥåţ ţö çĥåñĝé. one two three four]'; + String get sortSize => '[Ƒîļé šîžé one]'; @override - String get assistantEmptyBody => - '[Éṽéŕý çĥåñĝé îţ ɱåķéš çåñ ƀé ûñðöñé îñ öñé šţéþ. one two three]'; + String storageMeterValue(String usage, int percent) { + return '[$usage, $percent þéŕçéñţ one]'; + } @override - String get assistantPlaceholder => '[Åšķ ţĥé åššîšţåñţ… one tw]'; + String storageUsed(String size) { + return '[$size ûšéð on]'; + } @override - String get assistantPrivacyNotice => - '[Ţĥé åššîšţåñţ šéñðš ţĥîš ðöçûɱéñţ åñð ýöûŕ ɱéššåĝéš ţö ţĥé ÅÎ þŕöṽîðéŕ ţö ĝéñéŕåţé åñšŵéŕš. one two three four five six]'; + String storageUsedOf(String used, String quota) { + return '[$used öƒ $quota ûšéð one]'; + } @override - String assistantPrivacyNoticeProvider(String provider) { - return '[Ţĥé åššîšţåñţ šéñðš ţĥîš ðöçûɱéñţ åñð ýöûŕ ɱéššåĝéš ţö $provider ţö ĝéñéŕåţé åñšŵéŕš. one two three four five]'; + String storageUsedOfOver(String used, String quota) { + return '[$used öƒ $quota ûšéð — öṽéŕ ǫûöţå one tw]'; } @override - String get assistantModeEdit => '[Éðîţ on]'; + String get storageCalculating => '[Çåļçûļåţîñĝ šţöŕåĝé… one two]'; @override - String get assistantModeEditHint => - '[Éðîţ ðîŕéçţļý: çĥåñĝéš ĝö šţŕåîĝĥţ îñţö ţĥé ðöçûɱéñţ one two three fo]'; + String get storageMeterTooltip => + '[Šţöŕåĝé îš šĥåŕéð ƀý Ŵöñķý Ðŕîṽé, Ŵŕîţé, Šĥééţš åñð Šļîðéš. one two three four]'; @override - String get assistantModeEditUnavailable => - '[Ýöû çåñ öñļý šûĝĝéšţ çĥåñĝéš îñ ţĥîš ðöçûɱéñţ one two three]'; + String get storageMeterTooltipOffline => + '[Šţöŕåĝé îš šĥåŕéð ƀý Ŵöñķý Ðŕîṽé, Ŵŕîţé, Šĥééţš åñð Šļîðéš. (öƒƒļîñé) one two three four fi]'; @override - String get assistantModeSuggest => '[Šûĝĝéšţ one]'; + String storageBannerWarning(String used, String quota) { + return '[Ýöû\'ṽé ûšéð $used öƒ ýöûŕ $quota šţöŕåĝé. one two t]'; + } @override - String get assistantModeSuggestHint => - '[Šûĝĝéšţ: çĥåñĝéš åŕŕîṽé åš šûĝĝéšţîöñš ţö åççéþţ öŕ ŕéĵéçţ one two three four]'; + String get storageBannerOver => + '[Ýöû\'ŕé öûţ öƒ šţöŕåĝé. Ýöû çåñ ķééþ éðîţîñĝ, ƀûţ ýöû çåñ\'ţ ûþļöåð ƒîļéš, åðð îɱåĝéš, îɱþöŕţ, öŕ ɱåķé çöþîéš ûñţîļ ýöû ƒŕéé ûþ šþåçé. one two three four five six seven eight]'; @override - String assistantRemoveChip(String label) { - return '[Ŕéɱöṽé $label one]'; - } + String get storageBannerDismiss => '[Ðîšɱîšš one]'; @override - String get assistantThinking => '[Ţĥîñķîñĝ… one]'; + String get quotaOwnTitle => '[Ýöû\'ŕé öûţ öƒ šţöŕåĝé one two]'; @override - String get assistantRefused => - '[Ţĥé åššîšţåñţ çåñ\'ţ ĥéļþ ŵîţĥ ţĥåţ ŕéǫûéšţ. one two three]'; + String quotaOwnBody(String needed, String available, String quota) { + return '[Ţĥîš ñééðš $needed, ƀûţ ýöû ĥåṽé $available ļéƒţ öƒ ýöûŕ $quota. Ƒŕéé ûþ šþåçé îñ Ŵöñķý Ðŕîṽé ƀý ðéļéţîñĝ ƒîļéš ýöû ñö ļöñĝéŕ ñééð åñð éɱþţýîñĝ ţĥé ţŕåšĥ. one two three four five six seven eig]'; + } @override - String get assistantFailed => '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ. one two]'; + String quotaOwnBodyUnknown(String available, String quota) { + return '[Ýöû ĥåṽé $available ļéƒţ öƒ ýöûŕ $quota. Ƒŕéé ûþ šþåçé îñ Ŵöñķý Ðŕîṽé ƀý ðéļéţîñĝ ƒîļéš ýöû ñö ļöñĝéŕ ñééð åñð éɱþţýîñĝ ţĥé ţŕåšĥ. one two three four five six seve]'; + } @override - String get assistantStopped => '[Šţöþþéð one]'; + String quotaOwnerTitle(String owner) { + return '[$owner îš öûţ öƒ šţöŕåĝé one t]'; + } @override - String get assistantContinue => '[Çöñţîñûé one]'; + String quotaOwnerImageBody(String kind, String owner) { + String _temp0 = intl.Intl.selectLogic(kind, { + 'spreadsheet': + 'Îɱåĝéš åððéð ţö ţĥîš šþŕéåðšĥééţ çöûñţ åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé, öŕ åðð ţĥé îɱåĝé ţö å šþŕéåðšĥééţ ýöû öŵñ.', + 'presentation': + 'Îɱåĝéš åððéð ţö ţĥîš þŕéšéñţåţîöñ çöûñţ åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé, öŕ åðð ţĥé îɱåĝé ţö å þŕéšéñţåţîöñ ýöû öŵñ.', + 'other': + 'Îɱåĝéš åððéð ţö ţĥîš ðöçûɱéñţ çöûñţ åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé, öŕ åðð ţĥé îɱåĝé ţö å ðöçûɱéñţ ýöû öŵñ.', + }); + return '[$_temp0 one two three four five six seven eight nine ten one two three four five six seven eight nine ten one two three fo]'; + } @override - String get assistantUndone => '[Ûñðöñé one]'; + String quotaOwnerBody(String owner) { + return '[Çöñţéñţ åððéð ţö ţĥîš ƒîļé çöûñţš åĝåîñšţ ţĥé öŵñéŕ\'š šţöŕåĝé. Åšķ $owner ţö ƒŕéé ûþ šþåçé ƒîŕšţ. one two three four five six]'; + } @override - String get assistantUndoChanges => '[Ûñðö çĥåñĝéš one]'; + String get quotaBatchTitle => '[Ñöţ éñöûĝĥ šţöŕåĝé ƒöŕ åļļ ƒîļéš one two th]'; @override - String get assistantInsertAtCursor => '[Îñšéŕţ åţ çûŕšöŕ one t]'; + String quotaBatchBody(int count, String needed, String available) { + return '[Ţĥéšé $count ƒîļéš ñééð $needed, ƀûţ ýöû ĥåṽé $available ļéƒţ. Ûþļöåð ţĥé ƒîļéš ţĥåţ ƒîţ, öŕ ƒŕéé ûþ šþåçé ƒîŕšţ. one two three four five s]'; + } @override - String get assistantAllow => '[Åļļöŵ on]'; + String get quotaBatchFit => '[Ûþļöåð ţĥé ƒîļéš ţĥåţ ƒîţ one two]'; @override - String get assistantDeny => '[Ðéñý on]'; + String quotaTransferTitle(String name) { + return '[$name ðöéšñ\'ţ ĥåṽé éñöûĝĥ šţöŕåĝé one two t]'; + } @override - String get assistantShow => '[Šĥöŵ on]'; + String quotaTransferBody(String name, String needed, String item) { + return '[$name ñééðš $needed ƒŕéé ţö ţåķé öŵñéŕšĥîþ öƒ “$item”. Åšķ ţĥéɱ ţö ƒŕéé ûþ šþåçé ƒîŕšţ. one two three four f]'; + } @override - String get assistantCopyCode => '[Çöþý çöðé one]'; + String get quotaTransferAcceptTitle => + '[Ýöû ðöñ\'ţ ĥåṽé éñöûĝĥ šţöŕåĝé one two t]'; @override - String get aiNotConfigured => - '[ÅÎ îšñ\'ţ çöñƒîĝûŕéð öñ ţĥîš šéŕṽéŕ. one two thr]'; + String quotaTransferAcceptBody(String item, String needed, String available) { + return '[Ţåķîñĝ öŵñéŕšĥîþ öƒ “$item” ñééðš $needed, ƀûţ ýöû ĥåṽé $available ļéƒţ. one two three]'; + } @override - String get aiNotConfiguredHint => - '[Åðð ýöûŕ öŵñ ÖþéñÅÎ, Åñţĥŕöþîç öŕ Ĝéɱîñî ÅÞÎ ķéý ţö ûšé îţ, öŕ åšķ åñ åðɱîñîšţŕåţöŕ ţö åðð öñé ţö ţĥé šéŕṽéŕ. one two three four five six sev]'; + String get quotaTooLargeTitle => '[Ţĥîš ƒîļé îš ţöö ļåŕĝé one two]'; @override - String get aiNotConfiguredAdminHint => - '[Åñ åðɱîñîšţŕåţöŕ çåñ éñåƀļé îţ ƀý åððîñĝ åñ ÖþéñÅÎ, Åñţĥŕöþîç öŕ Ĝéɱîñî ÅÞÎ ķéý ţö ţĥé šéŕṽéŕ çöñƒîĝûŕåţîöñ. one two three four five six seve]'; + String quotaTooLargeBody(String max) { + return '[Ƒîļéš çåñ ƀé åţ ɱöšţ $max. one tw]'; + } @override - String get aiAddApiKey => '[Åðð åñ ÅÞÎ ķéý one]'; + String quotaTooLargeNowBody(String max) { + return '[Ƒîļéš çåñ ƀé åţ ɱöšţ $max ŕîĝĥţ ñöŵ, ƀéçåûšé ţĥåţ\'š ĥöŵ ɱûçĥ šţöŕåĝé ýöû ĥåṽé ļéƒţ. one two three four five]'; + } @override - String get aiDisabled => '[ÅÎ îš ţûŕñéð öƒƒ öñ ţĥîš šéŕṽéŕ. one two th]'; + String get quotaItemFallback => '[ţĥîš îţéɱ one]'; @override - String get aiOptedOut => - '[Ţĥé åššîšţåñţ îš ţûŕñéð öƒƒ îñ ýöûŕ šéţţîñĝš (Šéţţîñĝš › ÅÎ). one two three four]'; + String get strengthEmpty => '[Éñţéŕ å þåššŵöŕð one t]'; @override - String get aiAssistantTitle => '[Åššîšţåñţ one]'; + String get strengthFair => '[Ƒåîŕ on]'; @override - String get aiAssistantHint => - '[Ţĥé åššîšţåñţ ĥéļþš ýöû ŵŕîţé, éðîţ åñð ûñðéŕšţåñð ðöçûɱéñţš. Îţ öñļý šééš ţĥé ðöçûɱéñţ ýöû ûšé îţ îñ. one two three four five six se]'; + String get strengthGood => '[Ĝööð on]'; @override - String get aiEnableHint => - '[Ţûŕñ öƒƒ ţö ĥîðé ÅÎ ƒéåţûŕéš åñð šţöþ šéñðîñĝ çöñţéñţ ţö ţĥé ÅÎ šéŕṽîçé. one two three four fi]'; + String strengthLabel(String label) { + return '[Þåššŵöŕð šţŕéñĝţĥ: $label one tw]'; + } @override - String get aiQuality => '[ÅÎ ǫûåļîţý one]'; + String get strengthStrong => '[Šţŕöñĝ one]'; @override - String get aiQualityBest => '[Ɓéšţ on]'; + String get strengthWeak => '[Ŵéåķ on]'; @override - String get aiQualityBestHint => '[Ṁöšţ çåþåƀļé åñšŵéŕš åñð éðîţš one two th]'; + String get switchAccount => '[Šŵîţçĥ åççöûñţ one t]'; @override - String get aiQualityBalanced => '[Ɓåļåñçéð one]'; + String get templateBlank => '[Ɓļåñķ on]'; @override - String get aiQualityBalancedHint => - '[Ĝööð åñšŵéŕš, å ļîţţļé ƒåšţéŕ one two t]'; + String get templateEducation => '[Éðûçåţîöñ one]'; @override - String get aiQualityFast => '[Ƒåšţ on]'; + String get templateFinance => '[Ƒîñåñçé one]'; @override - String get aiQualityFastHint => - '[Ǫûîçķéšţ åñšŵéŕš ƒöŕ šîɱþļé ţåšķš one two thr]'; + String get templateGallery => '[Ţéɱþļåţé ĝåļļéŕý one tw]'; @override - String get aiQualitySaveFailed => '[Çöûļðñ\'ţ šåṽé ţĥé ÅÎ ǫûåļîţý one two t]'; + String get templatePersonal => '[Þéŕšöñåļ one]'; @override - String get aiUsageToday => '[Ûšåĝé ţöðåý one]'; + String get templateProjectManagement => '[Þŕöĵéçţ ɱåñåĝéɱéñţ one tw]'; @override - String get aiUsageTodayHint => '[Ŕéšéţš ðåîļý åţ ɱîðñîĝĥţ ÛŢÇ. one two t]'; + String templateStripTitle(String kind) { + return '[Šţåŕţ å ñéŵ $kind one]'; + } @override - String aiUsagePercent(int percent) { - return '[$percent % o]'; - } + String get templateWork => '[Ŵöŕķ on]'; @override - String get aiProviderOpenai => '[ÖþéñÅÎ one]'; + String get templatesHide => '[Ĥîðé ţéɱþļåţéš one t]'; @override - String get aiProviderAnthropic => '[Åñţĥŕöþîç one]'; + String get templatesShow => '[Šĥöŵ ţéɱþļåţéš one t]'; @override - String get aiProviderGemini => '[Ĝööĝļé Ĝéɱîñî one t]'; + String get themeDark => '[Ðåŕķ on]'; @override - String get aiProvidersServerTitle => '[Þŕöṽîðéð ƀý ţĥîš šéŕṽéŕ one two]'; + String get themeLight => '[Ļîĝĥţ on]'; @override - String aiProvidersServerBody(String provider) { - return '[ÅÎ ŕéǫûéšţš ĝö ţö $provider ŵîţĥ ţĥîš šéŕṽéŕ\'š ÅÞÎ ķéý. Ýöû ðöñ\'ţ ñééð å ķéý öƒ ýöûŕ öŵñ. one two three four five]'; + String get themeSystem => '[Šýšţéɱ one]'; + + @override + String themeToggleTooltip(String mode) { + return '[Ţĥéɱé: $mode one]'; } @override - String get aiProvidersKeyTitle => '[Ýöûŕ ÅÞÎ ķéý one]'; + String timeHoursAgo(int hours) { + return '[$hours ĥ åĝö on]'; + } @override - String get aiProvidersKeyHint => - '[Ţĥîš šéŕṽéŕ ĥåš ñö ÅÎ þŕöṽîðéŕ šéţ ûþ. Åðð ýöûŕ öŵñ ķéý ţö ûšé ţĥé åššîšţåñţ åñð ţĥé öţĥéŕ ÅÎ ƒéåţûŕéš. Ţĥé ķéý îš šţöŕéð öñ ţĥé šéŕṽéŕ, ûšéð öñļý ƒöŕ ýöûŕ ŕéǫûéšţš åñð ñéṽéŕ šĥöŵñ åĝåîñ. one two three four five six seven eight nine ten one]'; + String get timeJustNow => '[Ĵûšţ ñöŵ one]'; @override - String get aiProvidersProvider => '[Þŕöṽîðéŕ one]'; + String timeMinutesAgo(int minutes) { + return '[$minutes ɱîñ åĝö one]'; + } @override - String get aiProvidersKey => '[ÅÞÎ ķéý one]'; + String get toastAccessRequested => '[Ŕéǫûéšţ šéñţ one]'; @override - String get aiProvidersKeyPlaceholder => '[Þåšţé ýöûŕ ÅÞÎ ķéý one tw]'; + String toastCopyCreated(String name) { + return '[Çŕéåţéð “$name” one]'; + } @override - String get aiProvidersSave => '[Šåṽé ķéý one]'; + String get toastLinkCopied => '[Ļîñķ çöþîéð one]'; @override - String get aiProvidersSaved => '[ÅÞÎ ķéý šåṽéð one]'; + String get toastMcpConfigCopied => '[ṀÇÞ šéţţîñĝš çöþîéð one tw]'; @override - String get aiProvidersSaveFailed => '[Çöûļðñ\'ţ šåṽé ţĥé ÅÞÎ ķéý one two]'; + String toastMovedToTrash(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count îţéɱš ɱöṽéð ţö ţŕåšĥ', + one: 'Ṁöṽéð ţö ţŕåšĥ', + ); + return '[$_temp0 one two thr]'; + } @override - String get aiProvidersCurrent => '[Ýöûŕ ķéý one]'; + String get toastOfflineOpFailed => + '[Å çĥåñĝé ɱåðé öƒƒļîñé çöûļð ñöţ ƀé åþþļîéð one two three]'; @override - String aiProvidersCurrentValue(String provider, String last4) { - return '[$provider ķéý éñðîñĝ îñ $last4 one]'; + String get toastShortcutAdded => '[Šĥöŕţçûţ åððéð one t]'; + + @override + String get toastUndoPartial => + '[Šöɱé çĥåñĝéš çöûļðñ\'ţ ƀé ûñðöñé ƀéçåûšé ţĥéý ŵéŕé éðîţéð ƀý šöɱéöñé éļšé. one two three four fiv]'; + + @override + String toastVersionNamed(String name) { + return '[Šåṽéð ṽéŕšîöñ “$name” one t]'; } @override - String get aiProvidersRemove => '[Ŕéɱöṽé ķéý one]'; + String get toastVersionRestored => '[Ṽéŕšîöñ ŕéšţöŕéð one tw]'; @override - String get aiProvidersRemoveTitle => '[Ŕéɱöṽé ýöûŕ ÅÞÎ ķéý? one tw]'; + String get toggleSidebar => '[Ṁåîñ ɱéñû one]'; @override - String get aiProvidersRemoveBody => - '[ÅÎ ƒéåţûŕéš šţöþ ŵöŕķîñĝ ƒöŕ ýöû ûñţîļ ýöû åðð å ķéý åĝåîñ. one two three fou]'; + String get tokenCopyOnce => + '[Çöþý ţĥîš ţöķéñ ñöŵ. Ýöû ŵöñ\'ţ šéé îţ åĝåîñ. one two three]'; @override - String get aiProvidersRemoved => '[ÅÞÎ ķéý ŕéɱöṽéð one t]'; + String get tokenCreate => '[Çŕéåţé ţöķéñ one]'; @override - String get aiProvidersRemoveFailed => - '[Çöûļðñ\'ţ ŕéɱöṽé ţĥé ÅÞÎ ķéý one two t]'; + String get tokenName => '[Ţöķéñ ñåɱé one]'; @override - String get aiProvidersNotAllowed => - '[Ţĥîš šéŕṽéŕ ðöéšñ\'ţ åļļöŵ þéŕšöñåļ ÅÞÎ ķéýš. Åšķ åñ åðɱîñîšţŕåţöŕ ţö šéţ ûþ ÅÎ. one two three four five]'; + String get tokenRevoke => '[Ŕéṽöķé one]'; @override - String get aiProvidersManage => '[Ṁåñåĝé ÅÎ þŕöṽîðéŕš one tw]'; + String get tokenRevoked => '[ŕéṽöķéð one]'; @override - String get aiChatHistory => '[Çĥåţ ĥîšţöŕý one]'; + String get tokensEmpty => '[Ñö ţöķéñš ýéţ. one t]'; @override - String get aiChatHistoryHint => - '[Ðéļéţé åļļ ýöûŕ åššîšţåñţ çĥåţš. one two th]'; + String get tokensHint => + '[Þéŕšöñåļ åççéšš ţöķéñš ļéţ ṀÇÞ çļîéñţš åçţ åš ýöû. one two three f]'; @override - String get aiClearHistory => '[Çļéåŕ ĥîšţöŕý one t]'; + String get tokensTitle => '[Þéŕšöñåļ åççéšš ţöķéñš one two]'; @override - String get aiClearHistoryTitle => '[Çļéåŕ åššîšţåñţ ĥîšţöŕý? one two]'; + String get trashedBanner => '[Ţĥîš ƒîļé îš îñ ţĥé ţŕåšĥ. one two]'; @override - String get aiClearHistoryBody => - '[Åļļ ýöûŕ åššîšţåñţ çĥåţš îñ éṽéŕý ðöçûɱéñţ åŕé ðéļéţéð. Ţĥîš çåñ\'ţ ƀé ûñðöñé. Éðîţš ţĥé åššîšţåñţ ɱåðé šţåý îñ ţĥé ðöçûɱéñţš. one two three four five six seven eig]'; + String get typeAll => '[Åļļ ţýþéš one]'; @override - String get aiClearHistoryFailed => '[Çöûļðñ\'ţ çļéåŕ ţĥé ĥîšţöŕý one two t]'; + String get typeAllFiles => '[Åļļ ƒîļéš one]'; @override - String aiHistoryCleared(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: 'Ðéļéţéð $count çĥåţš', - one: 'Ðéļéţéð 1 çĥåţ', - ); - return '[$_temp0 one two t]'; - } + String get typeDocuments => '[Ðöçûɱéñţš one]'; @override - String get mcpScopeDriveRead => - '[Ðŕîṽé: ŕéåð (ļîšţ, šéåŕçĥ, éẋþöŕţ, ðöŵñļöåð ƒîļéš, šţöŕåĝé) one two three four]'; + String get typeFiles => '[Ƒîļéš on]'; @override - String get mcpScopeDriveWrite => - '[Ðŕîṽé: ŵŕîţé (çŕéåţé, ŕéñåɱé, ɱöṽé, ţŕåšĥ, šĥåŕé, ûþļöåð åñð çöñṽéŕţ ƒîļéš) one two three four five]'; + String get typeFolders => '[Ƒöļðéŕš one]'; @override - String get mcpScopeWriteRead => '[Ðöçûɱéñţš: ŕéåð one t]'; + String get typePresentations => '[Þŕéšéñţåţîöñš one t]'; @override - String get mcpScopeWriteEdit => - '[Ðöçûɱéñţš: éðîţ (çöñţéñţ, çöɱɱéñţš, šûĝĝéšţîöñš) one two three fo]'; + String get typeSpreadsheets => '[Šþŕéåðšĥééţš one t]'; @override - String get mcpScopeSheetsRead => '[Šþŕéåðšĥééţš: ŕéåð one tw]'; + String get undoHistoryEmpty => '[Ñöţĥîñĝ ţö ûñðö one t]'; @override - String get mcpScopeSheetsEdit => '[Šþŕéåðšĥééţš: éðîţ one tw]'; + String get undoHistoryTitle => '[Ûñðö ĥîšţöŕý one]'; @override - String get mcpScopeSlidesRead => '[Þŕéšéñţåţîöñš: ŕéåð one two]'; + String get untitledFolder => '[Ûñţîţļéð ƒöļðéŕ one t]'; @override - String get mcpScopeSlidesEdit => '[Þŕéšéñţåţîöñš: éðîţ one two]'; + String get versionNewAvailable => '[Å ñéŵ ṽéŕšîöñ îš åṽåîļåƀļé one two]'; @override - String get mcpScopeScriptsRun => '[Šçŕîþţš: ŕûñ one]'; + String get versionsEmpty => '[Ñö ṽéŕšîöñš ýéţ one t]'; @override - String get mcpScopeUiControl => - '[Çöñţŕöļ åþþ ŵîñðöŵš (ûî.* ţööļš) one two th]'; + String get versionsName => '[Ñåɱé ţĥîš ṽéŕšîöñ one tw]'; @override - String get mcpScopeBoard => - '[Ɓûĝš & îɱþŕöṽéɱéñţš: ŕéåð, ŕéþöŕţ îššûéš, ṽöţé, çļåîɱ ţåšķš one two three four]'; + String get versionsNamedOnly => '[Öñļý ñåɱéð ṽéŕšîöñš one tw]'; @override - String get tokenCreateHint => - '[Ţĥé ţöķéñ åçţš åš ýöû ŵîţĥ ţĥé þéŕɱîššîöñš ýöû çĥööšé. Ýöû çåñ ŕéṽöķé îţ åţ åñý ţîɱé. one two three four five s]'; + String get versionsOpenFull => '[Öþéñ ƒûļļ ĥîšţöŕý one tw]'; @override - String get tokenNameRequired => '[Ĝîṽé ţĥé ţöķéñ å ñåɱé. one two]'; + String get versionsRename => '[Ŕéñåɱé ṽéŕšîöñ one t]'; @override - String get tokenScopesRequired => - '[Çĥööšé åţ ļéåšţ öñé þéŕɱîššîöñ. one two th]'; + String get versionsRestorePoint => '[Ɓéƒöŕé ŕéšţöŕé one t]'; @override - String get tokenExpires => '[Éẋþîŕéš one]'; + String get whatsNew1 => + '[Öñé åççöûñţ ƒöŕ Ŵöñķý Ŵŕîţé åñð Ŵöñķý Šĥééţš — šîĝñ îñ öñçé, ûšé ƀöţĥ. one two three four f]'; @override - String tokenExpiresInDays(int days) { - String _temp0 = intl.Intl.pluralLogic( - days, - locale: localeName, - other: 'Îñ $days ðåýš', - one: 'Îñ 1 ðåý', - ); - return '[$_temp0 one t]'; - } + String get whatsNew2 => + '[Éṽéŕý åçţîöñ îš å çöɱɱåñð: þŕéšš Çţŕļ+Šĥîƒţ+Þ (⌘⇧Þ) ţö ŕûñ åñýţĥîñĝ. one two three four fi]'; @override - String get tokenExpiresInYear => '[Îñ 1 ýéåŕ one]'; + String get whatsNew3 => + '[Ûñðö çöṽéŕš ðŕîṽé çĥåñĝéš ţöö — ŕéñåɱé, ɱöṽé, šţåŕ åñð ţŕåšĥ. one two three four]'; @override - String get tokenNever => '[Ñéṽéŕ on]'; + String get whatsNew4 => + '[Çöɱɱéñţš, ɱéñţîöñš åñð ṽéŕšîöñ ĥîšţöŕý îñ éṽéŕý ƒîļé. one two three fou]'; @override - String get tokenNeverLower => '[ñéṽéŕ on]'; + String get whatsNewTitle => '[Ŵĥåţ\'š ñéŵ one]'; @override - String get tokenExpired => '[éẋþîŕéð one]'; + String get wonkyWork => '[Ŵöñķý Ŵöŕķ one]'; @override - String tokenNameWithStatus(String name, String status) { - return '[$name · $status o]'; - } + String get writeAutoPair => '[Åûţö-þåîŕ ƀŕåçķéţš åñð ǫûöţéš one two th]'; @override - String tokenDates(String created, String expires, String lastUsed) { - return '[Çŕéåţéð $created · éẋþîŕéš $expires · ļåšţ ûšéð $lastUsed one two t]'; - } + String get writeExportFormat => '[Ðéƒåûļţ ðöŵñļöåð ƒöŕɱåţ one two]'; @override - String tokenRevokeTitle(String name) { - return '[Ŕéṽöķé \"$name\"? one]'; - } + String get writeMarkdownShortcuts => '[Ṁåŕķðöŵñ šĥöŕţçûţš one tw]'; @override - String get tokenRevokeBody => - '[ṀÇÞ çļîéñţš ûšîñĝ ţĥîš ţöķéñ šţöþ ŵöŕķîñĝ îɱɱéðîåţéļý. Ţĥîš çåñ\'ţ ƀé ûñðöñé. one two three four five]'; + String get writePageless => '[Þåĝéļéšš ƀý ðéƒåûļţ one tw]'; @override - String get toastTokenCopied => '[Ţöķéñ çöþîéð one]'; + String get writeSmartQuotes => '[Šɱåŕţ ǫûöţéš one]'; @override - String mcpEndpoint(String url) { - return '[Éñðþöîñţ: $url one]'; - } + String get writeSpellcheck => '[Šþéļļçĥéçķ one]'; @override - String mcpReplaceToken(String variable) { - return '[Ŕéþļåçé $variable ŵîţĥ å ţöķéñ. one two]'; - } + String get youHaveCommentAccess => '[Ýöû ĥåṽé çöɱɱéñţ åççéšš one two]'; @override - String get mcpWindowControl => '[Ŵîñðöŵ çöñţŕöļ one t]'; + String get youHaveViewAccess => '[Ýöû ĥåṽé ṽîéŵ åççéšš one tw]'; @override - String get mcpWindowControlHint => - '[Ļéţš ṀÇÞ çļîéñţš ŵîţĥ ţĥé ûî:çöñţŕöļ þéŕɱîššîöñ ðŕîṽé ţĥîš ŵîñðöŵ: ñåṽîĝåţé, ŕûñ çöɱɱåñðš, ƒîļļ ðîåļöĝš, ţåķé šçŕééñšĥöţš. Å þîļļ ŵîţĥ Šţöþ šĥöŵš ŵĥîļé åñ åĝéñţ ŵöŕķš. one two three four five six seven eight nine ten o]'; + String get assistantNewChat => '[Ñéŵ çĥåţ one]'; @override - String get mcpBridgeStatus => '[Šţåţûš one]'; + String get assistantClearChat => '[Çļéåŕ çĥåţ one]'; @override - String get mcpBridgeOff => '[Öƒƒ on]'; + String get assistantDeleteChat => '[Ðéļéţé ţĥîš çĥåţ one t]'; @override - String get mcpBridgeConnecting => '[Çöññéçţîñĝ… one]'; + String get assistantDeleteChatFailed => '[Çöûļðñ\'ţ ðéļéţé ţĥé çĥåţ one two]'; @override - String mcpBridgeConnected(String id) { - return '[Öñ · ŵîñðöŵ $id one]'; - } + String get assistantAiSettings => '[ÅÎ šéţţîñĝš one]'; @override - String driveItemLabel(String kind, String name) { - return '[$kind $name]'; - } + String get assistantOpenAiSettings => '[Öþéñ ÅÎ šéţţîñĝš one t]'; @override - String get activityShowMore => '[Šĥöŵ ɱöŕé one]'; + String get assistantEmptyTitle => + '[Åšķ åƀöûţ ţĥîš ðöçûɱéñţ öŕ ţéļļ ţĥé åššîšţåñţ ŵĥåţ ţö çĥåñĝé. one two three four]'; @override - String get notificationsFilterAll => '[Åļļ on]'; + String get assistantEmptyBody => + '[Éṽéŕý çĥåñĝé îţ ɱåķéš çåñ ƀé ûñðöñé îñ öñé šţéþ. one two three]'; @override - String get notificationsFilterUnread => '[Ûñŕéåð one]'; + String get assistantPlaceholder => '[Åšķ ţĥé åššîšţåñţ… one tw]'; @override - String notificationsFilterUnreadCount(int count) { - return '[Ûñŕéåð ($count) one]'; + String get assistantPrivacyNotice => + '[Ţĥé åššîšţåñţ šéñðš ţĥîš ðöçûɱéñţ åñð ýöûŕ ɱéššåĝéš ţö ţĥé ÅÎ þŕöṽîðéŕ ţö ĝéñéŕåţé åñšŵéŕš. one two three four five six]'; + + @override + String assistantPrivacyNoticeProvider(String provider) { + return '[Ţĥé åššîšţåñţ šéñðš ţĥîš ðöçûɱéñţ åñð ýöûŕ ɱéššåĝéš ţö $provider ţö ĝéñéŕåţé åñšŵéŕš. one two three four five]'; } @override - String get notificationsSettings => '[Ñöţîƒîçåţîöñ šéţţîñĝš one two]'; + String get assistantModeEdit => '[Éðîţ on]'; @override - String get notificationsLoadFailed => - '[Çöûļðñ\'ţ ļöåð ýöûŕ ñöţîƒîçåţîöñš one two thr]'; + String get assistantModeEditHint => + '[Éðîţ ðîŕéçţļý: çĥåñĝéš ĝö šţŕåîĝĥţ îñţö ţĥé ðöçûɱéñţ one two three fo]'; @override - String get notificationsEmptyUnread => '[Ñö ûñŕéåð ñöţîƒîçåţîöñš one two]'; + String get assistantModeEditUnavailable => + '[Ýöû çåñ öñļý šûĝĝéšţ çĥåñĝéš îñ ţĥîš ðöçûɱéñţ one two three]'; @override - String get notificationsLoadMore => '[Ļöåð ɱöŕé one]'; + String get assistantModeSuggest => '[Šûĝĝéšţ one]'; @override - String get notificationsUnreadMarker => '[ûñŕéåð one]'; + String get assistantModeSuggestHint => + '[Šûĝĝéšţ: çĥåñĝéš åŕŕîṽé åš šûĝĝéšţîöñš ţö åççéþţ öŕ ŕéĵéçţ one two three four]'; @override - String notifSuggestionAccepted(String who, String item) { - return '[$who åççéþţéð ýöûŕ šûĝĝéšţîöñ îñ $item one two t]'; + String assistantRemoveChip(String label) { + return '[Ŕéɱöṽé $label one]'; } @override - String notifSuggestionRejected(String who, String item) { - return '[$who ŕéĵéçţéð ýöûŕ šûĝĝéšţîöñ îñ $item one two t]'; - } + String get assistantThinking => '[Ţĥîñķîñĝ… one]'; @override - String get notifyAccessRequests => '[Åççéšš ŕéǫûéšţš one t]'; + String get assistantRefused => + '[Ţĥé åššîšţåñţ çåñ\'ţ ĥéļþ ŵîţĥ ţĥåţ ŕéǫûéšţ. one two three]'; @override - String get notifySuggestions => '[Šûĝĝéšţîöñš öñ ɱý ƒîļéš one two]'; + String get assistantFailed => '[Šöɱéţĥîñĝ ŵéñţ ŵŕöñĝ. one two]'; @override - String get notifyDigest => '[Ɓûñðļé éɱåîļš one t]'; + String get assistantStopped => '[Šţöþþéð one]'; @override - String get notifyDigestHint => - '[Šéñð öñé éɱåîļ éṽéŕý 15 ɱîñûţéš îñšţéåð öƒ öñé þéŕ ñöţîƒîçåţîöñ. Ṁéñţîöñš åñð åššîĝñɱéñţš åŕé åļŵåýš éɱåîļéð ŕîĝĥţ åŵåý. one two three four five six seven ei]'; + String get assistantContinue => '[Çöñţîñûé one]'; @override - String get exportFormatMarkdown => '[Ṁåŕķðöŵñ (.ɱð) one t]'; + String get assistantUndone => '[Ûñðöñé one]'; @override - String get exportFormatHtml => '[ĤŢṀĻ (.ĥţɱļ) one]'; + String get assistantUndoChanges => '[Ûñðö çĥåñĝéš one]'; @override - String get exportFormatPdf => '[ÞÐƑ (.þðƒ) one]'; + String get assistantInsertAtCursor => '[Îñšéŕţ åţ çûŕšöŕ one t]'; @override - String get exportFormatText => '[Þļåîñ ţéẋţ (.ţẋţ) one tw]'; + String get assistantAllow => '[Åļļöŵ on]'; @override - String get badgePendingCreate => - '[Çŕéåţéð öƒƒļîñé. Îţ îš åððéð ţö ýöûŕ Ðŕîṽé ŵĥéñ ýöû\'ŕé ƀåçķ öñļîñé. one two three four f]'; + String get assistantDeny => '[Ðéñý on]'; @override - String dropToUploadInto(String folder) { - return '[Ðŕöþ ƒîļéš ţö ûþļöåð ţö $folder one two]'; - } + String get assistantShow => '[Šĥöŵ on]'; @override - String dropUploadToFolder(String folder) { - return '[Ûþļöåð ţö $folder one]'; - } + String get assistantCopyCode => '[Çöþý çöðé one]'; @override - String get driveItemUploading => '[Ûþļöåðîñĝ… one]'; + String get aiNotConfigured => + '[ÅÎ îšñ\'ţ çöñƒîĝûŕéð öñ ţĥîš šéŕṽéŕ. one two thr]'; @override - String get spellingTitle => '[Šþéļļîñĝ one]'; + String get aiNotConfiguredHint => + '[Åðð ýöûŕ öŵñ ÖþéñÅÎ, Åñţĥŕöþîç öŕ Ĝéɱîñî ÅÞÎ ķéý ţö ûšé îţ, öŕ åšķ åñ åðɱîñîšţŕåţöŕ ţö åðð öñé ţö ţĥé šéŕṽéŕ. one two three four five six sev]'; @override - String get spellingDone => '[Ðöñé on]'; + String get aiNotConfiguredAdminHint => + '[Åñ åðɱîñîšţŕåţöŕ çåñ éñåƀļé îţ ƀý åððîñĝ åñ ÖþéñÅÎ, Åñţĥŕöþîç öŕ Ĝéɱîñî ÅÞÎ ķéý ţö ţĥé šéŕṽéŕ çöñƒîĝûŕåţîöñ. one two three four five six seve]'; @override - String get spellingNoErrors => '[Ñö šþéļļîñĝ éŕŕöŕš ƒöûñð. one two]'; + String get aiAddApiKey => '[Åðð åñ ÅÞÎ ķéý one]'; @override - String get spellingUnavailable => - '[Šþéļļçĥéçķ îšñ’ţ åṽåîļåƀļé ƒöŕ ţĥîš ðöçûɱéñţ’š ļåñĝûåĝé. one two three four]'; + String get aiDisabled => '[ÅÎ îš ţûŕñéð öƒƒ öñ ţĥîš šéŕṽéŕ. one two th]'; @override - String get spellingNotInDictionary => '[Ñöţ îñ ðîçţîöñåŕý one tw]'; + String get aiOptedOut => + '[Ţĥé åššîšţåñţ îš ţûŕñéð öƒƒ îñ ýöûŕ šéţţîñĝš (Šéţţîñĝš › ÅÎ). one two three four]'; @override - String get spellingSuggestions => '[Šûĝĝéšţîöñš one]'; + String get aiAssistantTitle => '[Åššîšţåñţ one]'; @override - String get spellingNoSuggestions => '[Ñö šûĝĝéšţîöñš one t]'; + String get aiAssistantHint => + '[Ţĥé åššîšţåñţ ĥéļþš ýöû ŵŕîţé, éðîţ åñð ûñðéŕšţåñð ðöçûɱéñţš. Îţ öñļý šééš ţĥé ðöçûɱéñţ ýöû ûšé îţ îñ. one two three four five six se]'; @override - String get spellingChange => '[Çĥåñĝé one]'; + String get aiEnableHint => + '[Ţûŕñ öƒƒ ţö ĥîðé ÅÎ ƒéåţûŕéš åñð šţöþ šéñðîñĝ çöñţéñţ ţö ţĥé ÅÎ šéŕṽîçé. one two three four fi]'; @override - String get spellingChangeAll => '[Çĥåñĝé åļļ one]'; + String get aiQuality => '[ÅÎ ǫûåļîţý one]'; @override - String get spellingIgnore => '[Îĝñöŕé one]'; + String get aiQualityBest => '[Ɓéšţ on]'; @override - String get spellingIgnoreAll => '[Îĝñöŕé åļļ one]'; + String get aiQualityBestHint => '[Ṁöšţ çåþåƀļé åñšŵéŕš åñð éðîţš one two th]'; @override - String get spellingAddToDictionary => '[Åðð ţö ðîçţîöñåŕý one tw]'; + String get aiQualityBalanced => '[Ɓåļåñçéð one]'; @override - String get spellingPersonalDictionary => '[Þéŕšöñåļ ðîçţîöñåŕý one two]'; + String get aiQualityBalancedHint => + '[Ĝööð åñšŵéŕš, å ļîţţļé ƒåšţéŕ one two t]'; @override - String get spellingPersonalDictionaryHint => - '[Ŵöŕðš ýöû åððéð åŕé ñéṽéŕ ɱåŕķéð åš ɱîššþéļļéð, îñ åñý ðöçûɱéñţ. one two three four]'; + String get aiQualityFast => '[Ƒåšţ on]'; @override - String get spellingAddWord => '[Åðð å ŵöŕð one]'; + String get aiQualityFastHint => + '[Ǫûîçķéšţ åñšŵéŕš ƒöŕ šîɱþļé ţåšķš one two thr]'; @override - String get spellingAdd => '[Åðð on]'; + String get aiQualitySaveFailed => '[Çöûļðñ\'ţ šåṽé ţĥé ÅÎ ǫûåļîţý one two t]'; @override - String get spellingNoWords => '[Ñö ŵöŕðš ýéţ. one]'; + String get aiUsageToday => '[Ûšåĝé ţöðåý one]'; @override - String spellingRemoveWord(String word) { - return '[Ŕéɱöṽé $word one]'; + String get aiUsageTodayHint => '[Ŕéšéţš ðåîļý åţ ɱîðñîĝĥţ ÛŢÇ. one two t]'; + + @override + String aiUsagePercent(int percent) { + return '[$percent % o]'; } @override - String get emojiPickerClose => '[Çļöšé éɱöĵî þîçķéŕ one tw]'; + String get aiProviderOpenai => '[ÖþéñÅÎ one]'; @override - String get emojiDialogLabel => '[Éɱöĵî on]'; + String get aiProviderAnthropic => '[Åñţĥŕöþîç one]'; @override - String get emojiPickerLabel => '[Éɱöĵî þîçķéŕ one]'; + String get aiProviderGemini => '[Ĝööĝļé Ĝéɱîñî one t]'; @override - String get emojiSearch => '[Šéåŕçĥ éɱöĵî one]'; + String get aiProvidersServerTitle => '[Þŕöṽîðéð ƀý ţĥîš šéŕṽéŕ one two]'; @override - String get emojiRecentlyUsed => '[Ŕéçéñţļý ûšéð one t]'; + String aiProvidersServerBody(String provider) { + return '[ÅÎ ŕéǫûéšţš ĝö ţö $provider ŵîţĥ ţĥîš šéŕṽéŕ\'š ÅÞÎ ķéý. Ýöû ðöñ\'ţ ñééð å ķéý öƒ ýöûŕ öŵñ. one two three four five]'; + } @override - String get emojiLoadFailed => '[Éɱöĵî çöûļð ñöţ ƀé ļöåðéð one two]'; + String get aiProvidersKeyTitle => '[Ýöûŕ ÅÞÎ ķéý one]'; @override - String get emojiNoneFound => '[Ñö éɱöĵî ƒöûñð one t]'; + String get aiProvidersKeyHint => + '[Ţĥîš šéŕṽéŕ ĥåš ñö ÅÎ þŕöṽîðéŕ šéţ ûþ. Åðð ýöûŕ öŵñ ķéý ţö ûšé ţĥé åššîšţåñţ åñð ţĥé öţĥéŕ ÅÎ ƒéåţûŕéš. Ţĥé ķéý îš šţöŕéð öñ ţĥé šéŕṽéŕ, ûšéð öñļý ƒöŕ ýöûŕ ŕéǫûéšţš åñð ñéṽéŕ šĥöŵñ åĝåîñ. one two three four five six seven eight nine ten one]'; @override - String get emojiNone => '[Ñö éɱöĵî one]'; + String get aiProvidersProvider => '[Þŕöṽîðéŕ one]'; @override - String get emojiSearchResults => '[Šéåŕçĥ ŕéšûļţš one t]'; + String get aiProvidersKey => '[ÅÞÎ ķéý one]'; @override - String get emojiPickAnEmoji => '[Þîçķ åñ éɱöĵî one]'; + String get aiProvidersKeyPlaceholder => '[Þåšţé ýöûŕ ÅÞÎ ķéý one tw]'; @override - String emojiSkinToneOption(String tone) { - return '[$tone šķîñ ţöñé one]'; - } + String get aiProvidersSave => '[Šåṽé ķéý one]'; @override - String emojiSkinToneCurrent(String tone) { - return '[Šķîñ ţöñé: $tone one]'; - } + String get aiProvidersSaved => '[ÅÞÎ ķéý šåṽéð one]'; @override - String get emojiSkinToneDefault => '[Ðéƒåûļţ one]'; + String get aiProvidersSaveFailed => '[Çöûļðñ\'ţ šåṽé ţĥé ÅÞÎ ķéý one two]'; @override - String get emojiSkinToneLight => '[Ļîĝĥţ on]'; + String get aiProvidersCurrent => '[Ýöûŕ ķéý one]'; @override - String get emojiSkinToneMediumLight => '[Ṁéðîûɱ-ļîĝĥţ one t]'; + String aiProvidersCurrentValue(String provider, String last4) { + return '[$provider ķéý éñðîñĝ îñ $last4 one]'; + } @override - String get emojiSkinToneMedium => '[Ṁéðîûɱ one]'; + String get aiProvidersRemove => '[Ŕéɱöṽé ķéý one]'; @override - String get emojiSkinToneMediumDark => '[Ṁéðîûɱ-ðåŕķ one]'; + String get aiProvidersRemoveTitle => '[Ŕéɱöṽé ýöûŕ ÅÞÎ ķéý? one tw]'; @override - String get emojiSkinToneDark => '[Ðåŕķ on]'; + String get aiProvidersRemoveBody => + '[ÅÎ ƒéåţûŕéš šţöþ ŵöŕķîñĝ ƒöŕ ýöû ûñţîļ ýöû åðð å ķéý åĝåîñ. one two three fou]'; @override - String get specialCharsTitle => '[Šþéçîåļ çĥåŕåçţéŕš one tw]'; + String get aiProvidersRemoved => '[ÅÞÎ ķéý ŕéɱöṽéð one t]'; @override - String get specialCharsClose => '[Çļöšé on]'; + String get aiProvidersRemoveFailed => + '[Çöûļðñ\'ţ ŕéɱöṽé ţĥé ÅÞÎ ķéý one two t]'; @override - String get specialCharsSearch => - '[Šéåŕçĥ ƀý ñåɱé öŕ çöðé (Û+2192) one two th]'; + String get aiProvidersNotAllowed => + '[Ţĥîš šéŕṽéŕ ðöéšñ\'ţ åļļöŵ þéŕšöñåļ ÅÞÎ ķéýš. Åšķ åñ åðɱîñîšţŕåţöŕ ţö šéţ ûþ ÅÎ. one two three four five]'; @override - String get specialCharsRecent => '[Ŕéçéñţ one]'; + String get aiProvidersManage => '[Ṁåñåĝé ÅÎ þŕöṽîðéŕš one tw]'; @override - String get specialCharsLoadFailed => - '[Çĥåŕåçţéŕš çöûļð ñöţ ƀé ļöåðéð one two th]'; + String get aiChatHistory => '[Çĥåţ ĥîšţöŕý one]'; @override - String get specialCharsNoneFound => '[Ñö çĥåŕåçţéŕš ƒöûñð one tw]'; + String get aiChatHistoryHint => + '[Ðéļéţé åļļ ýöûŕ åššîšţåñţ çĥåţš. one two th]'; @override - String get specialCharsSearchResults => '[Šéåŕçĥ ŕéšûļţš one t]'; + String get aiClearHistory => '[Çļéåŕ ĥîšţöŕý one t]'; @override - String activityDetailSlides(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count šļîðéš', - one: '1 šļîðé', - ); - return '[$_temp0 one t]'; - } + String get aiClearHistoryTitle => '[Çļéåŕ åššîšţåñţ ĥîšţöŕý? one two]'; @override - String activityDetailSlidesDeleted(int count) { + String get aiClearHistoryBody => + '[Åļļ ýöûŕ åššîšţåñţ çĥåţš îñ éṽéŕý ðöçûɱéñţ åŕé ðéļéţéð. Ţĥîš çåñ\'ţ ƀé ûñðöñé. Éðîţš ţĥé åššîšţåñţ ɱåðé šţåý îñ ţĥé ðöçûɱéñţš. one two three four five six seven eig]'; + + @override + String get aiClearHistoryFailed => '[Çöûļðñ\'ţ çļéåŕ ţĥé ĥîšţöŕý one two t]'; + + @override + String aiHistoryCleared(int count) { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count šļîðéš ðéļéţéð', - one: '1 šļîðé ðéļéţéð', + other: 'Ðéļéţéð $count çĥåţš', + one: 'Ðéļéţéð 1 çĥåţ', ); - return '[$_temp0 one two th]'; + return '[$_temp0 one two t]'; } @override - String get activityDetailTheme => '[ţĥéɱé çĥåñĝéð one t]'; + String get mcpScopeDriveRead => + '[Ðŕîṽé: ŕéåð (ļîšţ, šéåŕçĥ, éẋþöŕţ, ðöŵñļöåð ƒîļéš, šţöŕåĝé) one two three four]'; @override - String get activityDetailAgent => '[ŵîţĥ Çļåûðé one]'; + String get mcpScopeDriveWrite => + '[Ðŕîṽé: ŵŕîţé (çŕéåţé, ŕéñåɱé, ɱöṽé, ţŕåšĥ, šĥåŕé, ûþļöåð åñð çöñṽéŕţ ƒîļéš) one two three four five]'; @override - String get markdownBold => '[Ɓöļð on]'; + String get mcpScopeWriteRead => '[Ðöçûɱéñţš: ŕéåð one t]'; @override - String get markdownItalic => '[Îţåļîç one]'; + String get mcpScopeWriteEdit => + '[Ðöçûɱéñţš: éðîţ (çöñţéñţ, çöɱɱéñţš, šûĝĝéšţîöñš) one two three fo]'; @override - String get markdownCode => '[Çöðé on]'; + String get mcpScopeSheetsRead => '[Šþŕéåðšĥééţš: ŕéåð one tw]'; @override - String get markdownLink => '[Ļîñķ on]'; + String get mcpScopeSheetsEdit => '[Šþŕéåðšĥééţš: éðîţ one tw]'; @override - String get markdownBulletedList => '[Ɓûļļéţéð ļîšţ one t]'; + String get mcpScopeSlidesRead => '[Þŕéšéñţåţîöñš: ŕéåð one two]'; @override - String get markdownStrikethrough => '[Šţŕîķéţĥŕöûĝĥ one t]'; + String get mcpScopeSlidesEdit => '[Þŕéšéñţåţîöñš: éðîţ one two]'; @override - String get markdownNumberedList => '[Ñûɱƀéŕéð ļîšţ one t]'; + String get mcpScopeScriptsRun => '[Šçŕîþţš: ŕûñ one]'; @override - String get markdownTaskList => '[Çĥéçķļîšţ one]'; + String get mcpScopeUiControl => + '[Çöñţŕöļ åþþ ŵîñðöŵš (ûî.* ţööļš) one two th]'; @override - String get markdownQuote => '[Ǫûöţé on]'; + String get mcpScopeBoard => + '[Ɓûĝš & îɱþŕöṽéɱéñţš: ŕéåð, ŕéþöŕţ îššûéš, ṽöţé, çļåîɱ ţåšķš one two three four]'; @override - String get markdownToolbar => '[Ƒöŕɱåţţîñĝ one]'; + String get tokenCreateHint => + '[Ţĥé ţöķéñ åçţš åš ýöû ŵîţĥ ţĥé þéŕɱîššîöñš ýöû çĥööšé. Ýöû çåñ ŕéṽöķé îţ åţ åñý ţîɱé. one two three four five s]'; @override - String get markdownLinkTitle => '[Îñšéŕţ ļîñķ one]'; + String get tokenNameRequired => '[Ĝîṽé ţĥé ţöķéñ å ñåɱé. one two]'; @override - String get markdownLinkEditTitle => '[Éðîţ ļîñķ one]'; + String get tokenScopesRequired => + '[Çĥööšé åţ ļéåšţ öñé þéŕɱîššîöñ. one two th]'; @override - String get markdownLinkRemove => '[Ŕéɱöṽé ļîñķ one]'; + String get tokenExpires => '[Éẋþîŕéš one]'; @override - String get markdownLinkUrl => '[ÛŔĻ on]'; + String tokenExpiresInDays(int days) { + String _temp0 = intl.Intl.pluralLogic( + days, + locale: localeName, + other: 'Îñ $days ðåýš', + one: 'Îñ 1 ðåý', + ); + return '[$_temp0 one t]'; + } @override - String get markdownLinkInsert => '[Îñšéŕţ one]'; + String get tokenExpiresInYear => '[Îñ 1 ýéåŕ one]'; @override - String get markdownLinkInvalid => - '[Éñţéŕ å ŵéƀ (ĥţţþ öŕ ĥţţþš) öŕ éɱåîļ (ɱåîļţö) ļîñķ one two three f]'; + String get tokenNever => '[Ñéṽéŕ on]'; @override - String markdownLength(int count, int max) { - return '[$count / $max o]'; - } + String get tokenNeverLower => '[ñéṽéŕ on]'; @override - String get commentAddReaction => '[Åðð ŕéåçţîöñ one]'; + String get tokenExpired => '[éẋþîŕéð one]'; @override - String commentReaction(String emoji, int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count ŕéåçţîöñš', - one: '1 ŕéåçţîöñ', - ); - return '[$emoji $_temp0 one two]'; + String tokenNameWithStatus(String name, String status) { + return '[$name · $status o]'; } @override - String get lightboxImage => '[Îɱåĝé on]'; + String tokenDates(String created, String expires, String lastUsed) { + return '[Çŕéåţéð $created · éẋþîŕéš $expires · ļåšţ ûšéð $lastUsed one two t]'; + } @override - String get lightboxClose => '[Çļöšé (Éšç) one]'; + String tokenRevokeTitle(String name) { + return '[Ŕéṽöķé \"$name\"? one]'; + } @override - String get lightboxCloseImage => '[Çļöšé îɱåĝé one]'; + String get tokenRevokeBody => + '[ṀÇÞ çļîéñţš ûšîñĝ ţĥîš ţöķéñ šţöþ ŵöŕķîñĝ îɱɱéðîåţéļý. Ţĥîš çåñ\'ţ ƀé ûñðöñé. one two three four five]'; @override - String get lightboxLoadFailed => '[Ţĥé îɱåĝé çöûļðñ’ţ ƀé ļöåðéð one two t]'; + String get toastTokenCopied => '[Ţöķéñ çöþîéð one]'; @override - String get lightboxZoomIn => '[Žööɱ îñ one]'; + String mcpEndpoint(String url) { + return '[Éñðþöîñţ: $url one]'; + } @override - String get lightboxZoomOut => '[Žööɱ öûţ one]'; + String mcpReplaceToken(String variable) { + return '[Ŕéþļåçé $variable ŵîţĥ å ţöķéñ. one two]'; + } @override - String get lightboxFit => '[Ƒîţ ţö šçŕééñ one]'; + String get mcpWindowControl => '[Ŵîñðöŵ çöñţŕöļ one t]'; @override - String get cmdBoardReport => '[Ɓûĝš & îɱþŕöṽéɱéñţš… one two]'; + String get mcpWindowControlHint => + '[Ļéţš ṀÇÞ çļîéñţš ŵîţĥ ţĥé ûî:çöñţŕöļ þéŕɱîššîöñ ðŕîṽé ţĥîš ŵîñðöŵ: ñåṽîĝåţé, ŕûñ çöɱɱåñðš, ƒîļļ ðîåļöĝš, ţåķé šçŕééñšĥöţš. Å þîļļ ŵîţĥ Šţöþ šĥöŵš ŵĥîļé åñ åĝéñţ ŵöŕķš. one two three four five six seven eight nine ten o]'; @override - String get cmdBoardOpen => '[Ɓŕöŵšé Ɓûĝš & îɱþŕöṽéɱéñţš one two t]'; + String get mcpBridgeStatus => '[Šţåţûš one]'; @override - String get boardReportName => '[Ɓûĝš & îɱþŕöṽéɱéñţš one tw]'; + String get mcpBridgeOff => '[Öƒƒ on]'; @override - String get boardContributeNav => '[Çöñţŕîƀûţé & ƀûîļð one tw]'; + String get mcpBridgeConnecting => '[Çöññéçţîñĝ… one]'; @override - String get boardReportKindLabel => '[Ķîñð on]'; - - @override - String get boardReportKindBug => '[Ŕéþöŕţ å ƀûĝ one]'; + String mcpBridgeConnected(String id) { + return '[Öñ · ŵîñðöŵ $id one]'; + } @override - String get boardReportKindIdea => '[Šûĝĝéšţ åñ îɱþŕöṽéɱéñţ one two]'; + String driveItemLabel(String kind, String name) { + return '[$kind $name]'; + } @override - String get boardReportFieldTitle => '[Ţîţļé on]'; + String get activityShowMore => '[Šĥöŵ ɱöŕé one]'; @override - String get boardReportTitleHintBug => - '[Ðéšçŕîƀé ţĥé þŕöƀļéɱ îñ å ƒéŵ ŵöŕðš one two thr]'; + String get notificationsFilterAll => '[Åļļ on]'; @override - String get boardReportTitleHintIdea => - '[Ðéšçŕîƀé ýöûŕ îðéå îñ å ƒéŵ ŵöŕðš one two th]'; + String get notificationsFilterUnread => '[Ûñŕéåð one]'; @override - String get boardReportFieldHappened => '[Ŵĥåţ ĥåþþéñéð? one t]'; + String notificationsFilterUnreadCount(int count) { + return '[Ûñŕéåð ($count) one]'; + } @override - String get boardReportFieldExpected => '[Ŵĥåţ ðîð ýöû éẋþéçţ? one tw]'; + String get notificationsSettings => '[Ñöţîƒîçåţîöñ šéţţîñĝš one two]'; @override - String get boardReportFieldSteps => '[Šţéþš ţö ŕéþŕöðûçé one tw]'; + String get notificationsLoadFailed => + '[Çöûļðñ\'ţ ļöåð ýöûŕ ñöţîƒîçåţîöñš one two thr]'; @override - String get boardReportFieldIdea => '[Ŵĥåţ ŵöûļð ýöû ļîķé? one tw]'; + String get notificationsEmptyUnread => '[Ñö ûñŕéåð ñöţîƒîçåţîöñš one two]'; @override - String get boardReportFieldWhy => '[Ŵĥý ŵöûļð îţ ĥéļþ? one tw]'; + String get notificationsLoadMore => '[Ļöåð ɱöŕé one]'; @override - String get boardReportOptional => '[(öþţîöñåļ) one]'; + String get notificationsUnreadMarker => '[ûñŕéåð one]'; @override - String boardReportTitleLength(int min, int max) { - return '[Ûšé $min ţö $max çĥåŕåçţéŕš. one tw]'; + String notifSuggestionAccepted(String who, String item) { + return '[$who åççéþţéð ýöûŕ šûĝĝéšţîöñ îñ $item one two t]'; } @override - String boardReportBodyTooLong(int max) { - return '[Ţĥé ðéšçŕîþţîöñ îš ţöö ļöñĝ: åţ ɱöšţ $max çĥåŕåçţéŕš. one two three f]'; + String notifSuggestionRejected(String who, String item) { + return '[$who ŕéĵéçţéð ýöûŕ šûĝĝéšţîöñ îñ $item one two t]'; } @override - String get boardReportSimilarTitle => '[Šîɱîļåŕ îššûéš one t]'; - - @override - String boardReportSimilarVotes(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count ṽöţéš', - one: '1 ṽöţé', - ); - return '[$_temp0 one]'; - } + String get notifyAccessRequests => '[Åççéšš ŕéǫûéšţš one t]'; @override - String boardSimilarShow(int number, String title) { - return '[Šĥöŵ #$number $title on]'; - } + String get notifySuggestions => '[Šûĝĝéšţîöñš öñ ɱý ƒîļéš one two]'; @override - String get boardSimilarLoadFailed => - '[Çöûļðñ\'ţ ļöåð ţĥîš îššûé. Ţŕý åĝåîñ ļåţéŕ. one two three]'; + String get notifyDigest => '[Ɓûñðļé éɱåîļš one t]'; @override - String get boardTaskCommentsLabel => '[Çöɱɱéñţš ƒöŕ ţĥé þŕöɱþţ one two]'; + String get notifyDigestHint => + '[Šéñð öñé éɱåîļ éṽéŕý 15 ɱîñûţéš îñšţéåð öƒ öñé þéŕ ñöţîƒîçåţîöñ. Ṁéñţîöñš åñð åššîĝñɱéñţš åŕé åļŵåýš éɱåîļéð ŕîĝĥţ åŵåý. one two three four five six seven ei]'; @override - String get boardTaskCommentsHint => - '[Ţĥé ÅÎ ŕéåðš ţĥé çĥéçķéð çöɱɱéñţš ŵĥéñ îţ ŵŕîţéš ţĥé þŕöɱþţ. one two three four]'; + String get exportFormatMarkdown => '[Ṁåŕķðöŵñ (.ɱð) one t]'; @override - String get boardCommentsPromptHint => - '[Çĥéçķéð çöɱɱéñţš ĝö îñţö ţĥé ţåšķ þŕöɱþţ ŵĥéñ ýöû šéļéçţ ţĥîš îššûé ƒöŕ ƀûîļðîñĝ. one two three four five]'; + String get exportFormatHtml => '[ĤŢṀĻ (.ĥţɱļ) one]'; @override - String boardCommentInPrompt(String name) { - return '[Îñçļûðé ţĥé çöɱɱéñţ ƀý $name îñ ţĥé ţåšķ þŕöɱþţ one two thre]'; - } + String get exportFormatPdf => '[ÞÐƑ (.þðƒ) one]'; @override - String get boardReportVoteInstead => '[Ṽöţé îñšţéåð one]'; + String get exportFormatText => '[Þļåîñ ţéẋţ (.ţẋţ) one tw]'; @override - String get boardReportVoted => '[Ṽöţéð on]'; + String get badgePendingCreate => + '[Çŕéåţéð öƒƒļîñé. Îţ îš åððéð ţö ýöûŕ Ðŕîṽé ŵĥéñ ýöû\'ŕé ƀåçķ öñļîñé. one two three four f]'; @override - String boardReportVotedFor(int number) { - return '[Ṽöţéð ƒöŕ #$number one]'; + String dropToUploadInto(String folder) { + return '[Ðŕöþ ƒîļéš ţö ûþļöåð ţö $folder one two]'; } @override - String boardReportHitThisToo(int number) { - return '[Åððéð “Î ĥîţ ţĥîš ţöö” ţö #$number one two]'; + String dropUploadToFolder(String folder) { + return '[Ûþļöåð ţö $folder one]'; } @override - String boardReportVoteFailed(String message) { - return '[Çöûļðñ’ţ ṽöţé: $message one t]'; - } + String get driveItemUploading => '[Ûþļöåðîñĝ… one]'; @override - String get boardReportScreenshot => '[Šçŕééñšĥöţ one]'; + String get spellingTitle => '[Šþéļļîñĝ one]'; @override - String get boardReportAddScreenshot => '[Åðð šçŕééñšĥöţ one t]'; + String get spellingDone => '[Ðöñé on]'; @override - String get boardReportEditScreenshot => '[Éðîţ on]'; + String get spellingNoErrors => '[Ñö šþéļļîñĝ éŕŕöŕš ƒöûñð. one two]'; @override - String get boardReportRemoveScreenshot => '[Ŕéɱöṽé one]'; + String get spellingUnavailable => + '[Šþéļļçĥéçķ îšñ’ţ åṽåîļåƀļé ƒöŕ ţĥîš ðöçûɱéñţ’š ļåñĝûåĝé. one two three four]'; @override - String get boardReportScreenshotPreview => '[Šçŕééñšĥöţ þŕéṽîéŵ one tw]'; + String get spellingNotInDictionary => '[Ñöţ îñ ðîçţîöñåŕý one tw]'; @override - String get boardReportScreenshotWarning => - '[Šçŕééñšĥöţš åŕé þûƀļîç. Çöṽéŕ ñåɱéš, éɱåîļš åñð ðöçûɱéñţ çöñţéñţ. one two three four f]'; + String get spellingSuggestions => '[Šûĝĝéšţîöñš one]'; @override - String get boardReportCaptureFailed => - '[Çöûļðñ’ţ çåþţûŕé ţĥé šçŕééñ one two t]'; + String get spellingNoSuggestions => '[Ñö šûĝĝéšţîöñš one t]'; @override - String boardReportDetails(String summary) { - return '[Ðéţåîļš ţĥåţ ŵîļļ ƀé îñçļûðéð: $summary one two th]'; - } + String get spellingChange => '[Çĥåñĝé one]'; @override - String get boardReportDetailApp => '[Åþþ on]'; + String get spellingChangeAll => '[Çĥåñĝé åļļ one]'; @override - String get boardReportDetailPlatform => '[Þļåţƒöŕɱ one]'; + String get spellingIgnore => '[Îĝñöŕé one]'; @override - String get boardReportDetailTheme => '[Ţĥéɱé on]'; + String get spellingIgnoreAll => '[Îĝñöŕé åļļ one]'; @override - String get boardReportDetailLocale => '[Ļåñĝûåĝé one]'; + String get spellingAddToDictionary => '[Åðð ţö ðîçţîöñåŕý one tw]'; @override - String get boardReportDetailWindow => '[Ŵîñðöŵ šîžé one]'; + String get spellingPersonalDictionary => '[Þéŕšöñåļ ðîçţîöñåŕý one two]'; @override - String get boardReportDetailRoute => '[Þåĝé on]'; + String get spellingPersonalDictionaryHint => + '[Ŵöŕðš ýöû åððéð åŕé ñéṽéŕ ɱåŕķéð åš ɱîššþéļļéð, îñ åñý ðöçûɱéñţ. one two three four]'; @override - String get boardReportDetailError => '[Éŕŕöŕ on]'; + String get spellingAddWord => '[Åðð å ŵöŕð one]'; @override - String get boardReportThemeLight => '[ļîĝĥţ ţĥéɱé one]'; + String get spellingAdd => '[Åðð on]'; @override - String get boardReportThemeDark => '[ðåŕķ ţĥéɱé one]'; + String get spellingNoWords => '[Ñö ŵöŕðš ýéţ. one]'; @override - String boardReportIncludeError(String age) { - return '[Îñçļûðé ţĥé ļåšţ éŕŕöŕ ($age) one two]'; + String spellingRemoveWord(String word) { + return '[Ŕéɱöṽé $word one]'; } @override - String boardReportErrorAge(int minutes) { - String _temp0 = intl.Intl.pluralLogic( - minutes, - locale: localeName, - other: '$minutes ɱîñ åĝö', - one: '1 ɱîñ åĝö', - zero: 'ĵûšţ ñöŵ', - ); - return '[$_temp0 one two]'; - } + String get emojiPickerClose => '[Çļöšé éɱöĵî þîçķéŕ one tw]'; @override - String boardReportErrorAgeHours(int hours) { - String _temp0 = intl.Intl.pluralLogic( - hours, - locale: localeName, - other: '$hours ĥ åĝö', - one: '1 ĥ åĝö', - ); - return '[$_temp0 one]'; - } + String get emojiDialogLabel => '[Éɱöĵî on]'; @override - String get boardReportAiNotice => - '[Κšûéš åŕé þûƀļîç åñð çĥéçķéð åûţöɱåţîçåļļý ƀý ÅÎ (Ĵéṽ, Ĝéɱîñî). one two three four f]'; + String get emojiPickerLabel => '[Éɱöĵî þîçķéŕ one]'; @override - String get boardReportPublicNotice => '[Κšûéš åŕé þûƀļîç. one tw]'; + String get emojiSearch => '[Šéåŕçĥ éɱöĵî one]'; @override - String boardReportSecurityNotice(String contact) { - return '[Šéçûŕîţý îššûé? Ðöñ’ţ þöšţ îţ ĥéŕé: éɱåîļ $contact one two three]'; - } + String get emojiRecentlyUsed => '[Ŕéçéñţļý ûšéð one t]'; @override - String get boardReportPostBug => '[Þöšţ ƀûĝ one]'; + String get emojiLoadFailed => '[Éɱöĵî çöûļð ñöţ ƀé ļöåðéð one two]'; @override - String get boardReportPostIdea => '[Þöšţ îɱþŕöṽéɱéñţ one tw]'; + String get emojiNoneFound => '[Ñö éɱöĵî ƒöûñð one t]'; @override - String get boardReportPosted => '[Þöšţéð one]'; + String get emojiNone => '[Ñö éɱöĵî one]'; @override - String get boardReportPostedChecking => '[Þöšţéð. Çĥéçķîñĝ îţ ñöŵ… one two]'; + String get emojiSearchResults => '[Šéåŕçĥ ŕéšûļţš one t]'; @override - String get boardReportPostedHeld => - '[Þöšţéð. Ŵåîţîñĝ ƒöŕ ŕéṽîéŵ: å ɱöðéŕåţöŕ ŵîļļ ļööķ åţ îţ. one two three fou]'; + String get emojiPickAnEmoji => '[Þîçķ åñ éɱöĵî one]'; @override - String get boardReportView => '[Ṽîéŵ on]'; + String emojiSkinToneOption(String tone) { + return '[$tone šķîñ ţöñé one]'; + } @override - String get boardReportRateLimited => - '[Ýöû’ṽé þöšţéð å ļöţ ŕéçéñţļý. Þļéåšé ţŕý åĝåîñ ļåţéŕ. one two three fo]'; + String emojiSkinToneCurrent(String tone) { + return '[Šķîñ ţöñé: $tone one]'; + } @override - String get boardReportBlocked => - '[Ýöû çåñ’ţ þöšţ öñ Ɓûĝš & îɱþŕöṽéɱéñţš. one two thre]'; + String get emojiSkinToneDefault => '[Ðéƒåûļţ one]'; @override - String boardReportBlockedReason(String reason) { - return '[Ýöû çåñ’ţ þöšţ öñ Ɓûĝš & îɱþŕöṽéɱéñţš: $reason one two thre]'; - } + String get emojiSkinToneLight => '[Ļîĝĥţ on]'; @override - String boardReportPostFailed(String message) { - return '[Çöûļðñ’ţ þöšţ: $message one t]'; - } + String get emojiSkinToneMediumLight => '[Ṁéðîûɱ-ļîĝĥţ one t]'; @override - String boardReportUploadFailed(String message) { - return '[Çöûļðñ’ţ ûþļöåð ţĥé šçŕééñšĥöţ: $message one two th]'; - } + String get emojiSkinToneMedium => '[Ṁéðîûɱ one]'; @override - String get boardReportDiscardTitle => '[Ðîšçåŕð ðŕåƒţ? one t]'; + String get emojiSkinToneMediumDark => '[Ṁéðîûɱ-ðåŕķ one]'; @override - String get boardReportDiscardBody => - '[Ýöûŕ îššûé ĥåšñ’ţ ƀééñ þöšţéð ýéţ. one two thr]'; + String get emojiSkinToneDark => '[Ðåŕķ on]'; @override - String get boardReportDiscard => '[Ðîšçåŕð one]'; + String get specialCharsTitle => '[Šþéçîåļ çĥåŕåçţéŕš one tw]'; @override - String get boardReportKeepDraft => '[Ķééþ ðŕåƒţ one]'; + String get specialCharsClose => '[Çļöšé on]'; @override - String get errorReportBug => '[Ŕéþöŕţ ţĥîš ƀûĝ one t]'; + String get specialCharsSearch => + '[Šéåŕçĥ ƀý ñåɱé öŕ çöðé (Û+2192) one two th]'; @override - String get screenshotEditorTitle => '[Éðîţ šçŕééñšĥöţ one t]'; + String get specialCharsRecent => '[Ŕéçéñţ one]'; @override - String get screenshotEditorWarning => - '[Ţĥîš šçŕééñšĥöţ ŵîļļ ƀé þûƀļîç. Çöṽéŕ åñýţĥîñĝ þŕîṽåţé: ñåɱéš, éɱåîļš, ðöçûɱéñţ åñð šþŕéåðšĥééţ çöñţéñţ ýöû ðöñ’ţ ŵåñţ ţö šĥåŕé. one two three four five six seven eight]'; + String get specialCharsLoadFailed => + '[Çĥåŕåçţéŕš çöûļð ñöţ ƀé ļöåðéð one two th]'; @override - String get screenshotToolsLabel => '[Ţööļ on]'; + String get specialCharsNoneFound => '[Ñö çĥåŕåçţéŕš ƒöûñð one tw]'; @override - String get screenshotColorsLabel => '[Çöļöŕ on]'; + String get specialCharsSearchResults => '[Šéåŕçĥ ŕéšûļţš one t]'; @override - String get screenshotToolCover => '[Çöṽéŕ on]'; + String activityDetailSlides(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count šļîðéš', + one: '1 šļîðé', + ); + return '[$_temp0 one t]'; + } @override - String get screenshotToolHighlight => '[Ĥîĝĥļîĝĥţ one]'; + String activityDetailSlidesDeleted(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count šļîðéš ðéļéţéð', + one: '1 šļîðé ðéļéţéð', + ); + return '[$_temp0 one two th]'; + } @override - String get screenshotToolArrow => '[Åŕŕöŵ on]'; + String get activityDetailTheme => '[ţĥéɱé çĥåñĝéð one t]'; @override - String get screenshotToolPen => '[Þéñ on]'; + String get activityDetailAgent => '[ŵîţĥ Çļåûðé one]'; @override - String get screenshotColorRed => '[Ŕéð on]'; + String get markdownBold => '[Ɓöļð on]'; @override - String get screenshotColorYellow => '[Ýéļļöŵ one]'; + String get markdownItalic => '[Îţåļîç one]'; @override - String get screenshotColorBlue => '[Ɓļûé on]'; + String get markdownCode => '[Çöðé on]'; @override - String get screenshotUndo => '[Ûñðö on]'; + String get markdownLink => '[Ļîñķ on]'; @override - String get screenshotRedo => '[Ŕéðö on]'; + String get markdownBulletedList => '[Ɓûļļéţéð ļîšţ one t]'; @override - String get screenshotDelete => '[Ðéļéţé šéļéçţéð one t]'; + String get markdownStrikethrough => '[Šţŕîķéţĥŕöûĝĥ one t]'; @override - String get screenshotClear => '[Çļéåŕ on]'; + String get markdownNumberedList => '[Ñûɱƀéŕéð ļîšţ one t]'; @override - String get screenshotDone => '[Ðöñé on]'; + String get markdownTaskList => '[Çĥéçķļîšţ one]'; @override - String screenshotShortcut(String label, String shortcut) { - return '[$label ($shortcut) o]'; - } + String get markdownQuote => '[Ǫûöţé on]'; @override - String get screenshotCanvasLabel => - '[Šçŕééñšĥöţ. Ðŕåĝ ţö ðŕåŵ ŵîţĥ ţĥé šéļéçţéð ţööļ; çļîçķ åñ åññöţåţîöñ ţö šéļéçţ îţ. one two three four five s]'; + String get markdownToolbar => '[Ƒöŕɱåţţîñĝ one]'; @override - String screenshotEncodeFailed(String message) { - return '[Çöûļðñ’ţ þŕéþåŕé ţĥé šçŕééñšĥöţ: $message one two thr]'; - } + String get markdownLinkTitle => '[Îñšéŕţ ļîñķ one]'; @override - String get boardTitle => '[Çöñţŕîƀûţé & ƀûîļð one tw]'; + String get markdownLinkEditTitle => '[Éðîţ ļîñķ one]'; @override - String get boardBreadcrumb => '[Ɓŕéåðçŕûɱƀ one]'; + String get markdownLinkRemove => '[Ŕéɱöṽé ļîñķ one]'; @override - String get boardClose => '[Çļöšé Çöñţŕîƀûţé & ƀûîļð one two]'; + String get markdownLinkUrl => '[ÛŔĻ on]'; @override - String get boardShowPath => '[Šĥöŵ ţĥé ƒûļļ þåţĥ one tw]'; + String get markdownLinkInsert => '[Îñšéŕţ one]'; @override - String boardTabWithCount(String name, int count) { - return '[$name, $count o]'; + String get markdownLinkInvalid => + '[Éñţéŕ å ŵéƀ (ĥţţþ öŕ ĥţţþš) öŕ éɱåîļ (ɱåîļţö) ļîñķ one two three f]'; + + @override + String markdownLength(int count, int max) { + return '[$count / $max o]'; } @override - String get boardReportBug => '[Ŕéþöŕţ å ƀûĝ one]'; + String get commentAddReaction => '[Åðð ŕéåçţîöñ one]'; @override - String get boardSuggestImprovement => '[Šûĝĝéšţ åñ îɱþŕöṽéɱéñţ one two]'; + String commentReaction(String emoji, int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ŕéåçţîöñš', + one: '1 ŕéåçţîöñ', + ); + return '[$emoji $_temp0 one two]'; + } @override - String get boardSearch => '[Šéåŕçĥ îššûéš one t]'; + String get lightboxImage => '[Îɱåĝé on]'; @override - String get boardSignIn => '[Šîĝñ îñ one]'; + String get lightboxClose => '[Çļöšé (Éšç) one]'; @override - String get boardSignInToVote => - '[Šîĝñ îñ ţö ṽöţé åñð ŕéþöŕţ îššûéš. one two th]'; + String get lightboxCloseImage => '[Çļöšé îɱåĝé one]'; @override - String get boardSignInToComment => '[Šîĝñ îñ ţö çöɱɱéñţ one tw]'; + String get lightboxLoadFailed => '[Ţĥé îɱåĝé çöûļðñ’ţ ƀé ļöåðéð one two t]'; @override - String get boardSignInToClaim => '[Šîĝñ îñ ţö çļåîɱ ţĥîš ţåšķ one two]'; + String get lightboxZoomIn => '[Žööɱ îñ one]'; @override - String get boardBlocked => - '[Ýöû çåñ\'ţ þöšţ öñ Ɓûĝš & îɱþŕöṽéɱéñţš. one two thre]'; + String get lightboxZoomOut => '[Žööɱ öûţ one]'; @override - String get boardContributeLink => '[Ĥöŵ ţö çöñţŕîƀûţé one tw]'; + String get lightboxFit => '[Ƒîţ ţö šçŕééñ one]'; @override - String get boardTabImprovements => '[Îɱþŕöṽéɱéñţš one t]'; + String get cmdBoardReport => '[Ɓûĝš & îɱþŕöṽéɱéñţš… one two]'; @override - String get boardTabBugs => '[Ɓûĝš on]'; + String get cmdBoardOpen => '[Ɓŕöŵšé Ɓûĝš & îɱþŕöṽéɱéñţš one two t]'; @override - String get boardTabTasks => '[Ûþ ƒöŕ ĝŕåƀš one]'; + String get boardReportName => '[Ɓûĝš & îɱþŕöṽéɱéñţš one tw]'; @override - String get boardTabClaimed => '[Çļåîɱéð one]'; + String get boardContributeNav => '[Çöñţŕîƀûţé & ƀûîļð one tw]'; @override - String get boardSearchButton => '[Šéåŕçĥ one]'; + String get boardReportKindLabel => '[Ķîñð on]'; @override - String boardSearchActive(String query) { - return '[Šéåŕçĥ: “$query” one]'; - } + String get boardReportKindBug => '[Ŕéþöŕţ å ƀûĝ one]'; @override - String get boardSearchRemove => '[Çļéåŕ ţĥé šéåŕçĥ one t]'; + String get boardReportKindIdea => '[Šûĝĝéšţ åñ îɱþŕöṽéɱéñţ one two]'; @override - String get boardSearchIncludeClosed => '[Îñçļûðé çļöšéð one t]'; + String get boardReportFieldTitle => '[Ţîţļé on]'; @override - String get boardSearchIncludeClosedHint => - '[Ðöñé, šĥîþþéð, ðéçļîñéð åñð ðûþļîçåţéš one two thre]'; + String get boardReportTitleHintBug => + '[Ðéšçŕîƀé ţĥé þŕöƀļéɱ îñ å ƒéŵ ŵöŕðš one two thr]'; @override - String get boardSearchKind => '[Ķîñð on]'; + String get boardReportTitleHintIdea => + '[Ðéšçŕîƀé ýöûŕ îðéå îñ å ƒéŵ ŵöŕðš one two th]'; @override - String get boardSearchKindAll => '[Åļļ on]'; + String get boardReportFieldHappened => '[Ŵĥåţ ĥåþþéñéð? one t]'; @override - String get boardSearchResults => '[Šéåŕçĥ one]'; + String get boardReportFieldExpected => '[Ŵĥåţ ðîð ýöû éẋþéçţ? one tw]'; @override - String boardSearchResultsFor(String query) { - return '[Ŕéšûļţš ƒöŕ “$query” one t]'; - } + String get boardReportFieldSteps => '[Šţéþš ţö ŕéþŕöðûçé one tw]'; @override - String get boardSearchStartTitle => '[Šéåŕçĥ ţĥé ƀöåŕð one t]'; + String get boardReportFieldIdea => '[Ŵĥåţ ŵöûļð ýöû ļîķé? one tw]'; @override - String get boardSearchStartHint => - '[Ƒîñð îššûéš ƀý ţĥéîŕ ŵöŕðš, þåŕţ öƒ å ţîţļé öŕ ţĥéîŕ ñûɱƀéŕ. one two three four]'; + String get boardReportFieldWhy => '[Ŵĥý ŵöûļð îţ ĥéļþ? one tw]'; @override - String get boardEmptySearchHint => - '[Ţŕý ƒéŵéŕ ŵöŕðš öŕ þåŕţ öƒ å ŵöŕð, öŕ îñçļûðé çļöšéð îššûéš. one two three four]'; + String get boardReportOptional => '[(öþţîöñåļ) one]'; @override - String get boardEmptyClaimed => '[Ñö çļåîɱéð ţåšķš one t]'; + String boardReportTitleLength(int min, int max) { + return '[Ûšé $min ţö $max çĥåŕåçţéŕš. one tw]'; + } @override - String get boardEmptyClaimedHint => - '[Ţåšķš šĥöŵ ĥéŕé ŵĥîļé šöɱéöñé ŵöŕķš öñ ţĥéɱ, åñð ŵĥîļé ţĥéîŕ þûļļ ŕéǫûéšţ îš îñ ŕéṽîéŵ. one two three four five si]'; + String boardReportBodyTooLong(int max) { + return '[Ţĥé ðéšçŕîþţîöñ îš ţöö ļöñĝ: åţ ɱöšţ $max çĥåŕåçţéŕš. one two three f]'; + } @override - String get boardTabDone => '[Ðöñé on]'; + String get boardReportSimilarTitle => '[Šîɱîļåŕ îššûéš one t]'; @override - String get boardTabReview => '[Ŕéṽîéŵ one]'; + String boardReportSimilarVotes(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ṽöţéš', + one: '1 ṽöţé', + ); + return '[$_temp0 one]'; + } @override - String get boardKindBug => '[Ɓûĝ on]'; + String boardSimilarShow(int number, String title) { + return '[Šĥöŵ #$number $title on]'; + } @override - String get boardKindIdea => '[Îɱþŕöṽéɱéñţ one]'; + String get boardSimilarLoadFailed => + '[Çöûļðñ\'ţ ļöåð ţĥîš îššûé. Ţŕý åĝåîñ ļåţéŕ. one two three]'; @override - String get boardAreaDrive => '[Ðŕîṽé on]'; + String get boardTaskCommentsLabel => '[Çöɱɱéñţš ƒöŕ ţĥé þŕöɱþţ one two]'; @override - String get boardAreaWrite => '[Ŵŕîţé on]'; + String get boardTaskCommentsHint => + '[Ţĥé ÅÎ ŕéåðš ţĥé çĥéçķéð çöɱɱéñţš ŵĥéñ îţ ŵŕîţéš ţĥé þŕöɱþţ. one two three four]'; @override - String get boardAreaSheets => '[Šĥééţš one]'; + String get boardCommentsPromptHint => + '[Çĥéçķéð çöɱɱéñţš ĝö îñţö ţĥé ţåšķ þŕöɱþţ ŵĥéñ ýöû šéļéçţ ţĥîš îššûé ƒöŕ ƀûîļðîñĝ. one two three four five]'; @override - String get boardAreaSlides => '[Šļîðéš one]'; + String boardCommentInPrompt(String name) { + return '[Îñçļûðé ţĥé çöɱɱéñţ ƀý $name îñ ţĥé ţåšķ þŕöɱþţ one two thre]'; + } @override - String get boardAreaSuite => '[Šûîţé on]'; + String get boardReportVoteInstead => '[Ṽöţé îñšţéåð one]'; @override - String get boardAreaServer => '[Šéŕṽéŕ one]'; + String get boardReportVoted => '[Ṽöţéð on]'; @override - String get boardSizeSmall => '[Šɱåļļ on]'; + String boardReportVotedFor(int number) { + return '[Ṽöţéð ƒöŕ #$number one]'; + } @override - String get boardSizeMedium => '[Ṁéðîûɱ one]'; + String boardReportHitThisToo(int number) { + return '[Åððéð “Î ĥîţ ţĥîš ţöö” ţö #$number one two]'; + } @override - String get boardSizeLarge => '[Ļåŕĝé on]'; + String boardReportVoteFailed(String message) { + return '[Çöûļðñ’ţ ṽöţé: $message one t]'; + } @override - String get boardStatusOpen => '[Öþéñ on]'; + String get boardReportScreenshot => '[Šçŕééñšĥöţ one]'; @override - String get boardStatusPlanned => '[Þļåññéð one]'; + String get boardReportAddScreenshot => '[Åðð šçŕééñšĥöţ one t]'; @override - String get boardStatusDone => '[Ðöñé on]'; + String get boardReportEditScreenshot => '[Éðîţ on]'; @override - String get boardStatusShipped => '[Šĥîþþéð one]'; + String get boardReportRemoveScreenshot => '[Ŕéɱöṽé one]'; @override - String get boardStatusDeclined => '[Ðéçļîñéð one]'; + String get boardReportScreenshotPreview => '[Šçŕééñšĥöţ þŕéṽîéŵ one tw]'; @override - String get boardStatusDuplicate => '[Ðûþļîçåţé one]'; + String get boardReportScreenshotWarning => + '[Šçŕééñšĥöţš åŕé þûƀļîç. Çöṽéŕ ñåɱéš, éɱåîļš åñð ðöçûɱéñţ çöñţéñţ. one two three four f]'; @override - String get boardTaskDraft => '[Ðŕåƒţ on]'; + String get boardReportCaptureFailed => + '[Çöûļðñ’ţ çåþţûŕé ţĥé šçŕééñ one two t]'; @override - String get boardTaskPublished => '[Þûƀļîšĥéð one]'; + String boardReportDetails(String summary) { + return '[Ðéţåîļš ţĥåţ ŵîļļ ƀé îñçļûðéð: $summary one two th]'; + } @override - String get boardTaskClaimed => '[Çļåîɱéð one]'; + String get boardReportDetailApp => '[Åþþ on]'; @override - String get boardTaskInReview => '[Îñ ŕéṽîéŵ one]'; + String get boardReportDetailPlatform => '[Þļåţƒöŕɱ one]'; @override - String get boardTaskCancelled => '[Çåñçéļļéð one]'; + String get boardReportDetailTheme => '[Ţĥéɱé on]'; @override - String get boardModerationChecking => '[Çĥéçķîñĝ one]'; + String get boardReportDetailLocale => '[Ļåñĝûåĝé one]'; @override - String get boardModerationVisible => '[Ṽîšîƀļé one]'; + String get boardReportDetailWindow => '[Ŵîñðöŵ šîžé one]'; @override - String get boardModerationHeld => '[Ĥéļð on]'; + String get boardReportDetailRoute => '[Þåĝé on]'; @override - String get boardModerationRemoved => '[Ŕéɱöṽéð one]'; + String get boardReportDetailError => '[Éŕŕöŕ on]'; @override - String get boardReasonOffensive => '[Öƒƒéñšîṽé one]'; + String get boardReportThemeLight => '[ļîĝĥţ ţĥéɱé one]'; @override - String get boardReasonSpam => '[Šþåɱ on]'; + String get boardReportThemeDark => '[ðåŕķ ţĥéɱé one]'; @override - String get boardReasonPersonalData => '[Þéŕšöñåļ ðåţå one t]'; + String boardReportIncludeError(String age) { + return '[Îñçļûðé ţĥé ļåšţ éŕŕöŕ ($age) one two]'; + } @override - String get boardReasonSecurity => '[Šéçûŕîţý îššûé one t]'; + String boardReportErrorAge(int minutes) { + String _temp0 = intl.Intl.pluralLogic( + minutes, + locale: localeName, + other: '$minutes ɱîñ åĝö', + one: '1 ɱîñ åĝö', + zero: 'ĵûšţ ñöŵ', + ); + return '[$_temp0 one two]'; + } @override - String get boardReasonOther => '[Öţĥéŕ on]'; + String boardReportErrorAgeHours(int hours) { + String _temp0 = intl.Intl.pluralLogic( + hours, + locale: localeName, + other: '$hours ĥ åĝö', + one: '1 ĥ åĝö', + ); + return '[$_temp0 one]'; + } @override - String get boardSortTrending => '[Ţŕéñðîñĝ one]'; + String get boardReportAiNotice => + '[Κšûéš åŕé þûƀļîç åñð çĥéçķéð åûţöɱåţîçåļļý ƀý ÅÎ (Ĵéṽ, Ĝéɱîñî). one two three four f]'; @override - String get boardSortTop => '[Ţöþ on]'; + String get boardReportPublicNotice => '[Κšûéš åŕé þûƀļîç. one tw]'; @override - String get boardSortNew => '[Ñéŵ on]'; + String boardReportSecurityNotice(String contact) { + return '[Šéçûŕîţý îššûé? Ðöñ’ţ þöšţ îţ ĥéŕé: éɱåîļ $contact one two three]'; + } @override - String get boardSortDiscussed => '[Ṁöšţ ðîšçûššéð one t]'; + String get boardReportPostBug => '[Þöšţ ƀûĝ one]'; @override - String get boardSort => '[Šöŕţ on]'; + String get boardReportPostIdea => '[Þöšţ îɱþŕöṽéɱéñţ one tw]'; @override - String get boardFilterArea => '[Åŕéå on]'; + String get boardReportPosted => '[Þöšţéð one]'; @override - String get boardFilterSize => '[Šîžé on]'; + String get boardReportPostedChecking => '[Þöšţéð. Çĥéçķîñĝ îţ ñöŵ… one two]'; @override - String get boardFilterStatus => '[Šţåţûš one]'; + String get boardReportPostedHeld => + '[Þöšţéð. Ŵåîţîñĝ ƒöŕ ŕéṽîéŵ: å ɱöðéŕåţöŕ ŵîļļ ļööķ åţ îţ. one two three fou]'; @override - String get boardFilterMine => '[Ṁîñé on]'; + String get boardReportView => '[Ṽîéŵ on]'; @override - String get boardFilterAny => '[Åñý on]'; + String get boardReportRateLimited => + '[Ýöû’ṽé þöšţéð å ļöţ ŕéçéñţļý. Þļéåšé ţŕý åĝåîñ ļåţéŕ. one two three fo]'; @override - String get boardSelect => '[Šéļéçţ one]'; + String get boardReportBlocked => + '[Ýöû çåñ’ţ þöšţ öñ Ɓûĝš & îɱþŕöṽéɱéñţš. one two thre]'; @override - String get boardSelectDone => '[Ðöñé šéļéçţîñĝ one t]'; + String boardReportBlockedReason(String reason) { + return '[Ýöû çåñ’ţ þöšţ öñ Ɓûĝš & îɱþŕöṽéɱéñţš: $reason one two thre]'; + } @override - String boardSelected(int count) { - return '[$count šéļéçţéð one]'; + String boardReportPostFailed(String message) { + return '[Çöûļðñ’ţ þöšţ: $message one t]'; } @override - String boardCreateTaskFrom(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: 'Çŕéåţé ţåšķ ƒŕöɱ $count îššûéš…', - one: 'Çŕéåţé ţåšķ ƒŕöɱ 1 îššûé…', - ); - return '[$_temp0 one two three f]'; + String boardReportUploadFailed(String message) { + return '[Çöûļðñ’ţ ûþļöåð ţĥé šçŕééñšĥöţ: $message one two th]'; } @override - String get boardCreateTaskHint => - '[Ţĥé ðŕåƒţ ţåšķ ĝéţš åñ ÅÎ-ŵŕîţţéñ þŕöɱþţ. Îţ îš þûƀļîšĥéð öñçé ţĥé þŕöɱþţ îš ŵŕîţţéñ. one two three four five s]'; + String get boardReportDiscardTitle => '[Ðîšçåŕð ðŕåƒţ? one t]'; @override - String get boardAddToTask => '[Åðð ţö ţåšķ one]'; + String get boardReportDiscardBody => + '[Ýöûŕ îššûé ĥåšñ’ţ ƀééñ þöšţéð ýéţ. one two thr]'; @override - String get boardAddToTaskEllipsis => '[Åðð ţö ţåšķ… one]'; + String get boardReportDiscard => '[Ðîšçåŕð one]'; @override - String get boardNoOpenTasks => - '[Ţĥéŕé åŕé ñö ðŕåƒţ öŕ þûƀļîšĥéð ţåšķš. one two thre]'; + String get boardReportKeepDraft => '[Ķééþ ðŕåƒţ one]'; @override - String get boardLoadMore => '[Ļöåð ɱöŕé one]'; + String get errorReportBug => '[Ŕéþöŕţ ţĥîš ƀûĝ one t]'; @override - String boardShowing(int shown, int total) { - return '[$shown öƒ $total o]'; - } + String get screenshotEditorTitle => '[Éðîţ šçŕééñšĥöţ one t]'; @override - String get boardLoadFailed => '[Çöûļðñ’ţ ļöåð Çöñţŕîƀûţé & ƀûîļð one two th]'; + String get screenshotEditorWarning => + '[Ţĥîš šçŕééñšĥöţ ŵîļļ ƀé þûƀļîç. Çöṽéŕ åñýţĥîñĝ þŕîṽåţé: ñåɱéš, éɱåîļš, ðöçûɱéñţ åñð šþŕéåðšĥééţ çöñţéñţ ýöû ðöñ’ţ ŵåñţ ţö šĥåŕé. one two three four five six seven eight]'; @override - String get boardEmptyIdeas => '[Ñö îɱþŕöṽéɱéñţš ĥéŕé ýéţ one two]'; + String get screenshotToolsLabel => '[Ţööļ on]'; @override - String get boardEmptyBugs => '[Ñö ƀûĝš ĥéŕé one]'; + String get screenshotColorsLabel => '[Çöļöŕ on]'; @override - String get boardEmptyDone => '[Ñöţĥîñĝ ƒîñîšĥéð ýéţ one two]'; + String get screenshotToolCover => '[Çöṽéŕ on]'; @override - String get boardEmptySearch => '[Ñö îššûéš ɱåţçĥ ýöûŕ šéåŕçĥ one two t]'; + String get screenshotToolHighlight => '[Ĥîĝĥļîĝĥţ one]'; @override - String get boardEmptyHint => - '[Çĥåñĝé ţĥé ƒîļţéŕš, öŕ ƀé ţĥé ƒîŕšţ ţö ŕéþöŕţ öñé. one two three f]'; + String get screenshotToolArrow => '[Åŕŕöŵ on]'; @override - String get boardEmptyTasks => '[Ñö ţåšķš ûþ ƒöŕ ĝŕåƀš one tw]'; + String get screenshotToolPen => '[Þéñ on]'; @override - String get boardEmptyTasksHint => - '[Åðɱîñš þûƀļîšĥ ţåšķš ƒŕöɱ ţĥé ɱöšţ ŵåñţéð îššûéš. Çĥéçķ ƀåçķ šööñ. one two three four f]'; + String get screenshotColorRed => '[Ŕéð on]'; @override - String boardUpvoteLabel(int score) { - return '[Ûþṽöţé, $score ṽöţéš one t]'; - } + String get screenshotColorYellow => '[Ýéļļöŵ one]'; @override - String boardDownvoteLabel(int score) { - return '[Ðöŵñṽöţé, $score ṽöţéš one t]'; - } + String get screenshotColorBlue => '[Ɓļûé on]'; @override - String get boardRemoveUpvote => '[Ŕéɱöṽé ûþṽöţé one t]'; + String get screenshotUndo => '[Ûñðö on]'; @override - String get boardRemoveDownvote => '[Ŕéɱöṽé ðöŵñṽöţé one t]'; + String get screenshotRedo => '[Ŕéðö on]'; @override - String get boardBugsUpvoteOnly => '[Ɓûĝš çåñ öñļý ƀé ûþṽöţéð one two]'; + String get screenshotDelete => '[Ðéļéţé šéļéçţéð one t]'; @override - String get boardDownvoteUnavailable => - '[Ðöŵñṽöţé, ûñåṽåîļåƀļé: ƀûĝš çåñ öñļý ƀé ûþṽöţéð one two three f]'; + String get screenshotClear => '[Çļéåŕ on]'; @override - String get boardAiMarker => '[ÅÎ o]'; + String get screenshotDone => '[Ðöñé on]'; @override - String boardAiLabel(String label) { - return '[$label, šéţ ƀý ÅÎ one]'; + String screenshotShortcut(String label, String shortcut) { + return '[$label ($shortcut) o]'; } @override - String boardPlannedIn(int number) { - return '[Þļåññéð · Ţ-$number one]'; - } + String get screenshotCanvasLabel => + '[Šçŕééñšĥöţ. Ðŕåĝ ţö ðŕåŵ ŵîţĥ ţĥé šéļéçţéð ţööļ; çļîçķ åñ åññöţåţîöñ ţö šéļéçţ îţ. one two three four five s]'; @override - String boardCommentCount(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count çöɱɱéñţš', - one: '1 çöɱɱéñţ', - ); - return '[$_temp0 one tw]'; + String screenshotEncodeFailed(String message) { + return '[Çöûļðñ’ţ þŕéþåŕé ţĥé šçŕééñšĥöţ: $message one two thr]'; } @override - String get boardHasScreenshot => '[Ĥåš å šçŕééñšĥöţ one t]'; + String get boardTitle => '[Çöñţŕîƀûţé & ƀûîļð one tw]'; @override - String get boardDeletedUser => '[Ðéļéţéð ûšéŕ one]'; + String get boardBreadcrumb => '[Ɓŕéåðçŕûɱƀ one]'; @override - String get boardAdmin => '[Åðɱîñ on]'; + String get boardClose => '[Çļöšé Çöñţŕîƀûţé & ƀûîļð one two]'; @override - String boardEdited(String time) { - return '[éðîţéð $time one]'; + String get boardShowPath => '[Šĥöŵ ţĥé ƒûļļ þåţĥ one tw]'; + + @override + String boardTabWithCount(String name, int count) { + return '[$name, $count o]'; } @override - String get boardCopy => '[Çöþý on]'; + String get boardReportBug => '[Ŕéþöŕţ å ƀûĝ one]'; @override - String get boardCopied => '[Çöþîéð one]'; + String get boardSuggestImprovement => '[Šûĝĝéšţ åñ îɱþŕöṽéɱéñţ one two]'; @override - String get boardPromptCopied => '[Þŕöɱþţ çöþîéð one t]'; + String get boardSearch => '[Šéåŕçĥ îššûéš one t]'; @override - String get boardFlagged => - '[Ţĥåñķš. Å ɱöðéŕåţöŕ ŵîļļ ţåķé å ļööķ. one two thr]'; + String get boardSignIn => '[Šîĝñ îñ one]'; @override - String boardPostNotFound(int number) { - return '[Κšûé #$number ðöéšñ\'ţ éẋîšţ öŕ îšñ\'ţ þûƀļîç one two thr]'; - } + String get boardSignInToVote => + '[Šîĝñ îñ ţö ṽöţé åñð ŕéþöŕţ îššûéš. one two th]'; @override - String boardTaskNotFound(int number) { - return '[Ţåšķ Ţ-$number ðöéšñ\'ţ éẋîšţ one two]'; - } + String get boardSignInToComment => '[Šîĝñ îñ ţö çöɱɱéñţ one tw]'; @override - String get boardBackToBoard => '[Ɓåçķ ţö Çöñţŕîƀûţé & ƀûîļð one two]'; + String get boardSignInToClaim => '[Šîĝñ îñ ţö çļåîɱ ţĥîš ţåšķ one two]'; @override - String get boardAdminActions => '[Åðɱîñ on]'; + String get boardBlocked => + '[Ýöû çåñ\'ţ þöšţ öñ Ɓûĝš & îɱþŕöṽéɱéñţš. one two thre]'; @override - String get boardEditAndApprove => '[Éðîţ åñð åþþŕöṽé… one tw]'; + String get boardContributeLink => '[Ĥöŵ ţö çöñţŕîƀûţé one tw]'; @override - String get boardActionApprove => '[Åþþŕöṽé one]'; + String get boardTabImprovements => '[Îɱþŕöṽéɱéñţš one t]'; @override - String get boardActionHold => '[Ĥöļð on]'; + String get boardTabBugs => '[Ɓûĝš on]'; @override - String get boardActionLooksFine => '[Ļööķš ƒîñé one]'; + String get boardTabTasks => '[Ûþ ƒöŕ ĝŕåƀš one]'; @override - String get boardActionRestore => '[Ŕéšţöŕé one]'; + String get boardTabClaimed => '[Çļåîɱéð one]'; @override - String get boardActionRemove => '[Ŕéɱöṽé one]'; + String get boardSearchButton => '[Šéåŕçĥ one]'; @override - String get boardActionRemoveEllipsis => '[Ŕéɱöṽé… one]'; + String boardSearchActive(String query) { + return '[Šéåŕçĥ: “$query” one]'; + } @override - String get boardActionDecline => '[Ðéçļîñé one]'; + String get boardSearchRemove => '[Çļéåŕ ţĥé šéåŕçĥ one t]'; @override - String get boardActionMerge => '[Ṁéŕĝé on]'; + String get boardSearchIncludeClosed => '[Îñçļûðé çļöšéð one t]'; @override - String get boardActionBlock => '[Ɓļöçķ on]'; + String get boardSearchIncludeClosedHint => + '[Ðöñé, šĥîþþéð, ðéçļîñéð åñð ðûþļîçåţéš one two thre]'; @override - String get boardActionCreateTask => '[Çŕéåţé ţåšķ one]'; + String get boardSearchKind => '[Ķîñð on]'; @override - String get boardActionAdd => '[Åðð on]'; + String get boardSearchKindAll => '[Åļļ on]'; @override - String get boardActionLink => '[Ļîñķ on]'; + String get boardSearchResults => '[Šéåŕçĥ one]'; @override - String get boardSelectForBuilding => '[Šéļéçţ ƒöŕ ƀûîļðîñĝ one tw]'; + String boardSearchResultsFor(String query) { + return '[Ŕéšûļţš ƒöŕ “$query” one t]'; + } @override - String get boardDeclineEllipsis => '[Ðéçļîñé… one]'; + String get boardSearchStartTitle => '[Šéåŕçĥ ţĥé ƀöåŕð one t]'; @override - String get boardMergeEllipsis => '[Ṁéŕĝé îñţö… one]'; + String get boardSearchStartHint => + '[Ƒîñð îššûéš ƀý ţĥéîŕ ŵöŕðš, þåŕţ öƒ å ţîţļé öŕ ţĥéîŕ ñûɱƀéŕ. one two three four]'; @override - String get boardLabelsEllipsis => '[Ļåƀéļš… one]'; + String get boardEmptySearchHint => + '[Ţŕý ƒéŵéŕ ŵöŕðš öŕ þåŕţ öƒ å ŵöŕð, öŕ îñçļûðé çļöšéð îššûéš. one two three four]'; @override - String get boardBlockEllipsis => '[Ɓļöçķ ûšéŕ ƒŕöɱ ţĥé ƀöåŕð… one two]'; + String get boardEmptyClaimed => '[Ñö çļåîɱéð ţåšķš one t]'; @override - String get boardEditEllipsis => '[Éðîţ… on]'; + String get boardEmptyClaimedHint => + '[Ţåšķš šĥöŵ ĥéŕé ŵĥîļé šöɱéöñé ŵöŕķš öñ ţĥéɱ, åñð ŵĥîļé ţĥéîŕ þûļļ ŕéǫûéšţ îš îñ ŕéṽîéŵ. one two three four five si]'; @override - String get boardDismiss => '[Ðîšɱîšš one]'; + String get boardTabDone => '[Ðöñé on]'; @override - String get boardApply => '[Åþþļý on]'; + String get boardTabReview => '[Ŕéṽîéŵ one]'; @override - String boardMergedFromNote(int number) { - return '[#$number ŵåš ɱéŕĝéð îñţö ţĥîš îššûé. one two t]'; - } + String get boardKindBug => '[Ɓûĝ on]'; @override - String get boardPostDeleted => '[Ţĥîš îššûé ŵåš ðéļéţéð. one two]'; + String get boardKindIdea => '[Îɱþŕöṽéɱéñţ one]'; @override - String get boardChecking => '[Çĥéçķîñĝ ýöûŕ îššûé… one two]'; + String get boardAreaDrive => '[Ðŕîṽé on]'; @override - String get boardWaitingForReview => - '[Ŵåîţîñĝ ƒöŕ ŕéṽîéŵ: å ɱöðéŕåţöŕ ŵîļļ ļööķ åţ îţ. one two three]'; + String get boardAreaWrite => '[Ŵŕîţé on]'; @override - String boardHeldAdmin(String reason) { - return '[Ĥéļð ƒöŕ ŕéṽîéŵ. $reason one t]'; - } + String get boardAreaSheets => '[Šĥééţš one]'; @override - String boardRemovedByModerator(String reason) { - return '[Ŕéɱöṽéð ƀý å ɱöðéŕåţöŕ. $reason one two]'; - } + String get boardAreaSlides => '[Šļîðéš one]'; @override - String boardDeclinedNote(String reason) { - return '[Ðéçļîñéð: $reason one]'; - } + String get boardAreaSuite => '[Šûîţé on]'; @override - String boardMergedInto(int number) { - return '[Ṁéŕĝéð îñţö #$number. one t]'; - } + String get boardAreaServer => '[Šéŕṽéŕ one]'; @override - String boardOpenPost(int number) { - return '[Öþéñ #$number on]'; - } + String get boardSizeSmall => '[Šɱåļļ on]'; @override - String get boardMovedToIdeas => '[Ṁöṽéð ţö Îɱþŕöṽéɱéñţš one two]'; + String get boardSizeMedium => '[Ṁéðîûɱ one]'; @override - String get boardMovedToBugs => '[Ṁöṽéð ţö Ɓûĝš one]'; + String get boardSizeLarge => '[Ļåŕĝé on]'; @override - String get boardEditedByModerator => '[Éðîţéð ƀý å ɱöðéŕåţöŕ one two]'; + String get boardStatusOpen => '[Öþéñ on]'; @override - String get boardDetails => '[Ðéţåîļš one]'; + String get boardStatusPlanned => '[Þļåññéð one]'; @override - String get boardAdminPanel => '[Ṁöðéŕåţîöñ one]'; + String get boardStatusDone => '[Ðöñé on]'; @override - String boardTriage(String state) { - return '[Ţŕîåĝé: $state one]'; - } + String get boardStatusShipped => '[Šĥîþþéð one]'; @override - String get boardNeedsCheck => '[Çĥéçķ on]'; + String get boardStatusDeclined => '[Ðéçļîñéð one]'; @override - String get boardNeedsLabels => '[Ñééðš ļåƀéļš one]'; + String get boardStatusDuplicate => '[Ðûþļîçåţé one]'; @override - String boardSuggestedTitle(String title) { - return '[Šûĝĝéšţéð ţîţļé: $title one tw]'; - } + String get boardTaskDraft => '[Ðŕåƒţ on]'; @override - String boardPossibleDuplicate(int number) { - return '[Þöššîƀļé ðûþļîçåţé öƒ #$number one two]'; - } + String get boardTaskPublished => '[Þûƀļîšĥéð one]'; @override - String get boardAiScores => '[ÅÎ šçöŕéš one]'; + String get boardTaskClaimed => '[Çļåîɱéð one]'; @override - String boardFlags(int count, String reasons) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: '$count ƒļåĝš', - one: '1 ƒļåĝ', - ); - return '[$_temp0: $reasons one]'; - } + String get boardTaskInReview => '[Îñ ŕéṽîéŵ one]'; @override - String get boardOpenScreenshot => '[Öþéñ šçŕééñšĥöţ one t]'; + String get boardTaskCancelled => '[Çåñçéļļéð one]'; @override - String boardScreenshotAlt(int number) { - return '[Šçŕééñšĥöţ öƒ îššûé #$number one two]'; - } + String get boardModerationChecking => '[Çĥéçķîñĝ one]'; @override - String get boardRelations => '[Ŕéļåţéð one]'; + String get boardModerationVisible => '[Ṽîšîƀļé one]'; @override - String boardPartOfTask(int number, String title) { - return '[Þåŕţ öƒ ţåšķ Ţ-$number: $title one t]'; - } + String get boardModerationHeld => '[Ĥéļð on]'; @override - String get boardMergedFrom => - '[Ðûþļîçåţéš ɱéŕĝéð îñţö ţĥîš îššûé: one two thr]'; + String get boardModerationRemoved => '[Ŕéɱöṽéð one]'; @override - String get boardSimilarPosts => '[Šîɱîļåŕ îššûéš one t]'; + String get boardReasonOffensive => '[Öƒƒéñšîṽé one]'; @override - String boardScore(int score) { - String _temp0 = intl.Intl.pluralLogic( - score, - locale: localeName, - other: '$score ṽöţéš', - one: '1 ṽöţé', - ); - return '[$_temp0 one]'; - } + String get boardReasonSpam => '[Šþåɱ on]'; @override - String boardCommentsTitle(int count) { - return '[Çöɱɱéñţš ($count) one]'; - } + String get boardReasonPersonalData => '[Þéŕšöñåļ ðåţå one t]'; @override - String get boardCommentHint => '[Åðð å çöɱɱéñţ one]'; + String get boardReasonSecurity => '[Šéçûŕîţý îššûé one t]'; @override - String get boardCommentHeld => '[Ĥîððéñ þéñðîñĝ ŕéṽîéŵ one two]'; + String get boardReasonOther => '[Öţĥéŕ on]'; @override - String get boardCommentRemoved => '[Ŕéɱöṽéð ƀý å ɱöðéŕåţöŕ one two]'; + String get boardSortTrending => '[Ţŕéñðîñĝ one]'; @override - String boardCommentOnPost(int number) { - return '[Çöɱɱéñţ öñ #$number one]'; - } + String get boardSortTop => '[Ţöþ on]'; @override - String boardCommentOnTask(int number) { - return '[Çöɱɱéñţ öñ Ţ-$number one]'; - } + String get boardSortNew => '[Ñéŵ on]'; @override - String get boardEventClaimed => '[çļåîɱéð ţĥé ţåšķ one t]'; + String get boardSortDiscussed => '[Ṁöšţ ðîšçûššéð one t]'; @override - String get boardEventReleased => '[ŕéļéåšéð ţĥé çļåîɱ one tw]'; + String get boardSort => '[Šöŕţ on]'; @override - String get boardEventExpired => '[Ţĥé çļåîɱ éẋþîŕéð one tw]'; + String get boardFilterArea => '[Åŕéå on]'; @override - String boardEventPrLinked(String url) { - return '[ļîñķéð å þûļļ ŕéǫûéšţ: $url one two]'; - } + String get boardFilterSize => '[Šîžé on]'; @override - String get boardEventPrUnlinked => '[ûñļîñķéð ţĥé þûļļ ŕéǫûéšţ one two]'; + String get boardFilterStatus => '[Šţåţûš one]'; @override - String get boardEventPublished => '[þûƀļîšĥéð ţĥé ţåšķ one tw]'; + String get boardFilterMine => '[Ṁîñé on]'; @override - String get boardEventDone => '[ɱåŕķéð ţĥé ţåšķ ðöñé one tw]'; + String get boardFilterAny => '[Åñý on]'; @override - String get boardEventShipped => '[ɱåŕķéð ţĥé ţåšķ šĥîþþéð one two]'; + String get boardSelect => '[Šéļéçţ one]'; @override - String get boardEventCancelled => '[çåñçéļļéð ţĥé ţåšķ one tw]'; + String get boardSelectDone => '[Ðöñé šéļéçţîñĝ one t]'; @override - String get boardEventMerged => '[ɱéŕĝéð å ðûþļîçåţé one tw]'; + String boardSelected(int count) { + return '[$count šéļéçţéð one]'; + } @override - String boardEventMergedInto(String task) { - return '[ɱéŕĝéð ţĥîš ţåšķ îñţö $task one two]'; + String boardCreateTaskFrom(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'Çŕéåţé ţåšķ ƒŕöɱ $count îššûéš…', + one: 'Çŕéåţé ţåšķ ƒŕöɱ 1 îššûé…', + ); + return '[$_temp0 one two three f]'; } @override - String boardEventMergedTasks(String tasks) { - return '[ɱéŕĝéð $tasks îñţö ţĥîš ţåšķ one two]'; - } + String get boardCreateTaskHint => + '[Ţĥé ðŕåƒţ ţåšķ ĝéţš åñ ÅÎ-ŵŕîţţéñ þŕöɱþţ. Îţ îš þûƀļîšĥéð öñçé ţĥé þŕöɱþţ îš ŵŕîţţéñ. one two three four five s]'; @override - String get boardEventUnmerged => '[ûñðîð å ɱéŕĝé öƒ ţåšķš one two]'; + String get boardAddToTask => '[Åðð ţö ţåšķ one]'; @override - String get boardEventRewriting => - '[çĥåñĝéð ţĥé îššûéš; ţĥé ţåšķ îš å ðŕåƒţ ûñţîļ ţĥé ÅÎ ĥåš ŕéŵŕîţţéñ ţĥé þŕöɱþţ one two three four five]'; + String get boardAddToTaskEllipsis => '[Åðð ţö ţåšķ… one]'; @override - String boardMergeTasksTitle(int count) { - String _temp0 = intl.Intl.pluralLogic( - count, - locale: localeName, - other: 'Ṁéŕĝé $count ţåšķš…', - one: 'Ṁéŕĝé 1 ţåšķ…', - ); - return '[$_temp0 one two]'; + String get boardNoOpenTasks => + '[Ţĥéŕé åŕé ñö ðŕåƒţ öŕ þûƀļîšĥéð ţåšķš. one two thre]'; + + @override + String get boardLoadMore => '[Ļöåð ɱöŕé one]'; + + @override + String boardShowing(int shown, int total) { + return '[$shown öƒ $total o]'; } @override - String get boardMergeTasksHint => - '[Ţĥé öļðéšţ ţåšķ ķééþš åļļ ţĥé îššûéš åñð ĝéţš å ñéŵ ÅÎ-ŵŕîţţéñ þŕöɱþţ. Ţĥé öţĥéŕ ţåšķš åŕé çåñçéļļéð. Ûñţîļ ţĥé þŕöɱþţ îš ŵŕîţţéñ, ţĥé ţåšķ îš å ðŕåƒţ. one two three four five six seven eight nine]'; + String get boardLoadFailed => '[Çöûļðñ’ţ ļöåð Çöñţŕîƀûţé & ƀûîļð one two th]'; @override - String get boardMergeTasksNeedsTwo => - '[Šéļéçţ ţŵö ţåšķš öŕ ɱöŕé ţö ɱéŕĝé ţĥéɱ one two thr]'; + String get boardEmptyIdeas => '[Ñö îɱþŕöṽéɱéñţš ĥéŕé ýéţ one two]'; @override - String boardTaskMergedNotice(int number) { - return '[Ţĥîš ţåšķ ŵåš ɱéŕĝéð îñţö Ţ-$number. one two t]'; + String get boardEmptyBugs => '[Ñö ƀûĝš ĥéŕé one]'; + + @override + String get boardEmptyDone => '[Ñöţĥîñĝ ƒîñîšĥéð ýéţ one two]'; + + @override + String get boardEmptySearch => '[Ñö îššûéš ɱåţçĥ ýöûŕ šéåŕçĥ one two t]'; + + @override + String get boardEmptyHint => + '[Çĥåñĝé ţĥé ƒîļţéŕš, öŕ ƀé ţĥé ƒîŕšţ ţö ŕéþöŕţ öñé. one two three f]'; + + @override + String get boardEmptyTasks => '[Ñö ţåšķš ûþ ƒöŕ ĝŕåƀš one tw]'; + + @override + String get boardEmptyTasksHint => + '[Åðɱîñš þûƀļîšĥ ţåšķš ƒŕöɱ ţĥé ɱöšţ ŵåñţéð îššûéš. Çĥéçķ ƀåçķ šööñ. one two three four f]'; + + @override + String boardUpvoteLabel(int score) { + return '[Ûþṽöţé, $score ṽöţéš one t]'; } @override - String boardOpenTask(int number) { - return '[Öþéñ Ţ-$number one]'; + String boardDownvoteLabel(int score) { + return '[Ðöŵñṽöţé, $score ṽöţéš one t]'; } @override - String get cmdBoardMergeTasks => '[Ṁéŕĝé ţåšķš one]'; + String get boardRemoveUpvote => '[Ŕéɱöṽé ûþṽöţé one t]'; @override - String get boardUpForGrabs => '[Ûþ ƒöŕ ĝŕåƀš one]'; + String get boardRemoveDownvote => '[Ŕéɱöṽé ðöŵñṽöţé one t]'; @override - String boardClaimedBy(String name, int hours) { - return '[Çļåîɱéð ƀý $name · $hours ĥ ļéƒţ one tw]'; + String get boardBugsUpvoteOnly => '[Ɓûĝš çåñ öñļý ƀé ûþṽöţéð one two]'; + + @override + String get boardDownvoteUnavailable => + '[Ðöŵñṽöţé, ûñåṽåîļåƀļé: ƀûĝš çåñ öñļý ƀé ûþṽöţéð one two three f]'; + + @override + String get boardAiMarker => '[ÅÎ o]'; + + @override + String boardAiLabel(String label) { + return '[$label, šéţ ƀý ÅÎ one]'; } @override - String boardInReviewBy(String name) { - return '[Îñ ŕéṽîéŵ · $name one]'; + String boardPlannedIn(int number) { + return '[Þļåññéð · Ţ-$number one]'; } @override - String boardPostCount(int count) { + String boardCommentCount(int count) { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count îššûéš', - one: '1 îššûé', + other: '$count çöɱɱéñţš', + one: '1 çöɱɱéñţ', ); - return '[$_temp0 one t]'; + return '[$_temp0 one tw]'; } @override - String get boardClaimTask => '[Çļåîɱ ţĥîš ţåšķ one t]'; + String get boardHasScreenshot => '[Ĥåš å šçŕééñšĥöţ one t]'; @override - String get boardReleaseClaim => '[Ŕéļéåšé çļåîɱ one t]'; + String get boardDeletedUser => '[Ðéļéţéð ûšéŕ one]'; @override - String get boardYourClaimCode => '[Ýöûŕ çļåîɱ çöðé one t]'; + String get boardAdmin => '[Åðɱîñ on]'; @override - String boardTimeLeft(int hours) { - return '[$hours ĥ ļéƒţ öñ ýöûŕ çļåîɱ one tw]'; + String boardEdited(String time) { + return '[éðîţéð $time one]'; } @override - String get boardClaimCodeHint => - '[Þûţ îţ îñ ţĥé þûļļ ŕéǫûéšţ ðéšçŕîþţîöñ. Öñļý ýöû çåñ šéé îţ. one two three four]'; + String get boardCopy => '[Çöþý on]'; @override - String get boardClaimCodePlaceholder => '[<ýöûŕ çļåîɱ çöðé> one tw]'; + String get boardCopied => '[Çöþîéð one]'; @override - String get boardDraftNotice => - '[Ðŕåƒţ: öñļý åðɱîñš šéé ţĥîš ţåšķ. Îţ îš þûƀļîšĥéð öñçé ţĥé ÅÎ ĥåš ŵŕîţţéñ îţš þŕöɱþţ, öŕ ŵĥéñ ýöû šåṽé ţĥé þŕöɱþţ. one two three four five six seven]'; + String get boardPromptCopied => '[Þŕöɱþţ çöþîéð one t]'; @override - String get boardPromptWriting => - '[Ŵŕîţîñĝ ţĥé þŕöɱþţ ŵîţĥ ÅÎ… ţĥîš ţåķéš åƀöûţ å ɱîñûţé one two three fo]'; + String get boardFlagged => + '[Ţĥåñķš. Å ɱöðéŕåţöŕ ŵîļļ ţåķé å ļööķ. one two thr]'; @override - String boardPromptNote(String note) { - return '[Ţĥé ÅÎ ðîð ñöţ ŵŕîţé ţĥé þŕöɱþţ: $note one two th]'; + String boardPostNotFound(int number) { + return '[Κšûé #$number ðöéšñ\'ţ éẋîšţ öŕ îšñ\'ţ þûƀļîç one two thr]'; } @override - String get boardTaskCancelledNotice => - '[Ţĥîš ţåšķ ŵåš çåñçéļļéð. Îţš îššûéš åŕé öþéñ åĝåîñ. one two three fo]'; + String boardTaskNotFound(int number) { + return '[Ţåšķ Ţ-$number ðöéšñ\'ţ éẋîšţ one two]'; + } @override - String get boardLinkedPosts => '[Ļîñķéð îššûéš one t]'; + String get boardBackToBoard => '[Ɓåçķ ţö Çöñţŕîƀûţé & ƀûîļð one two]'; @override - String get boardNoLinkedPosts => - '[Ñö îššûéš åŕé ļîñķéð ţö ţĥîš ţåšķ. one two th]'; + String get boardAdminActions => '[Åðɱîñ on]'; @override - String get boardRemoveFromTask => '[Ŕéɱöṽé ƒŕöɱ ţåšķ one t]'; + String get boardEditAndApprove => '[Éðîţ åñð åþþŕöṽé… one tw]'; @override - String get boardAddPosts => '[Åðð îššûéš… one]'; + String get boardActionApprove => '[Åþþŕöṽé one]'; @override - String get boardFieldPostNumbers => '[Κšûé ñûɱƀéŕš one t]'; + String get boardActionHold => '[Ĥöļð on]'; @override - String get boardHowToBuild => '[Ĥöŵ ţö ƀûîļð îţ one t]'; + String get boardActionLooksFine => '[Ļööķš ƒîñé one]'; @override - String get boardStepSetupNumber => '[1. o]'; + String get boardActionRestore => '[Ŕéšţöŕé one]'; @override - String get boardStepSetupLink => - '[Šéţ ûþ ýöûŕ ðéṽéļöþɱéñţ éñṽîŕöñɱéñţ one two thr]'; + String get boardActionRemove => '[Ŕéɱöṽé one]'; @override - String get boardInstallTools => - '[Îñšţåļļ Ƒļûţţéŕ, Ðåŕţ åñð ţĥé Šéŕṽéŕþöð ÇĻÎ: one two three]'; + String get boardActionRemoveEllipsis => '[Ŕéɱöṽé… one]'; + + @override + String get boardActionDecline => '[Ðéçļîñé one]'; + + @override + String get boardActionMerge => '[Ṁéŕĝé on]'; + + @override + String get boardActionBlock => '[Ɓļöçķ on]'; + + @override + String get boardActionCreateTask => '[Çŕéåţé ţåšķ one]'; + + @override + String get boardActionAdd => '[Åðð on]'; + + @override + String get boardActionLink => '[Ļîñķ on]'; + + @override + String get boardSelectForBuilding => '[Šéļéçţ ƒöŕ ƀûîļðîñĝ one tw]'; + + @override + String get boardDeclineEllipsis => '[Ðéçļîñé… one]'; + + @override + String get boardMergeEllipsis => '[Ṁéŕĝé îñţö… one]'; + + @override + String get boardLabelsEllipsis => '[Ļåƀéļš… one]'; + + @override + String get boardBlockEllipsis => '[Ɓļöçķ ûšéŕ ƒŕöɱ ţĥé ƀöåŕð… one two]'; + + @override + String get boardEditEllipsis => '[Éðîţ… on]'; + + @override + String get boardDismiss => '[Ðîšɱîšš one]'; + + @override + String get boardApply => '[Åþþļý on]'; + + @override + String boardMergedFromNote(int number) { + return '[#$number ŵåš ɱéŕĝéð îñţö ţĥîš îššûé. one two t]'; + } + + @override + String get boardPostDeleted => '[Ţĥîš îššûé ŵåš ðéļéţéð. one two]'; + + @override + String get boardChecking => '[Çĥéçķîñĝ ýöûŕ îššûé… one two]'; + + @override + String get boardWaitingForReview => + '[Ŵåîţîñĝ ƒöŕ ŕéṽîéŵ: å ɱöðéŕåţöŕ ŵîļļ ļööķ åţ îţ. one two three]'; + + @override + String boardHeldAdmin(String reason) { + return '[Ĥéļð ƒöŕ ŕéṽîéŵ. $reason one t]'; + } + + @override + String boardRemovedByModerator(String reason) { + return '[Ŕéɱöṽéð ƀý å ɱöðéŕåţöŕ. $reason one two]'; + } + + @override + String boardDeclinedNote(String reason) { + return '[Ðéçļîñéð: $reason one]'; + } + + @override + String boardMergedInto(int number) { + return '[Ṁéŕĝéð îñţö #$number. one t]'; + } + + @override + String boardOpenPost(int number) { + return '[Öþéñ #$number on]'; + } + + @override + String get boardMovedToIdeas => '[Ṁöṽéð ţö Îɱþŕöṽéɱéñţš one two]'; + + @override + String get boardMovedToBugs => '[Ṁöṽéð ţö Ɓûĝš one]'; + + @override + String get boardEditedByModerator => '[Éðîţéð ƀý å ɱöðéŕåţöŕ one two]'; + + @override + String get boardDetails => '[Ðéţåîļš one]'; + + @override + String get boardAdminPanel => '[Ṁöðéŕåţîöñ one]'; + + @override + String boardTriage(String state) { + return '[Ţŕîåĝé: $state one]'; + } + + @override + String get boardNeedsCheck => '[Çĥéçķ on]'; + + @override + String get boardNeedsLabels => '[Ñééðš ļåƀéļš one]'; + + @override + String boardSuggestedTitle(String title) { + return '[Šûĝĝéšţéð ţîţļé: $title one tw]'; + } + + @override + String boardPossibleDuplicate(int number) { + return '[Þöššîƀļé ðûþļîçåţé öƒ #$number one two]'; + } + + @override + String get boardAiScores => '[ÅÎ šçöŕéš one]'; + + @override + String boardFlags(int count, String reasons) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ƒļåĝš', + one: '1 ƒļåĝ', + ); + return '[$_temp0: $reasons one]'; + } + + @override + String get boardOpenScreenshot => '[Öþéñ šçŕééñšĥöţ one t]'; + + @override + String boardScreenshotAlt(int number) { + return '[Šçŕééñšĥöţ öƒ îššûé #$number one two]'; + } + + @override + String get boardRelations => '[Ŕéļåţéð one]'; + + @override + String boardPartOfTask(int number, String title) { + return '[Þåŕţ öƒ ţåšķ Ţ-$number: $title one t]'; + } + + @override + String get boardMergedFrom => + '[Ðûþļîçåţéš ɱéŕĝéð îñţö ţĥîš îššûé: one two thr]'; + + @override + String get boardSimilarPosts => '[Šîɱîļåŕ îššûéš one t]'; + + @override + String boardScore(int score) { + String _temp0 = intl.Intl.pluralLogic( + score, + locale: localeName, + other: '$score ṽöţéš', + one: '1 ṽöţé', + ); + return '[$_temp0 one]'; + } + + @override + String boardCommentsTitle(int count) { + return '[Çöɱɱéñţš ($count) one]'; + } + + @override + String get boardCommentHint => '[Åðð å çöɱɱéñţ one]'; + + @override + String get boardCommentHeld => '[Ĥîððéñ þéñðîñĝ ŕéṽîéŵ one two]'; + + @override + String get boardCommentRemoved => '[Ŕéɱöṽéð ƀý å ɱöðéŕåţöŕ one two]'; + + @override + String boardCommentOnPost(int number) { + return '[Çöɱɱéñţ öñ #$number one]'; + } + + @override + String boardCommentOnTask(int number) { + return '[Çöɱɱéñţ öñ Ţ-$number one]'; + } + + @override + String get boardEventClaimed => '[çļåîɱéð ţĥé ţåšķ one t]'; + + @override + String get boardEventReleased => '[ŕéļéåšéð ţĥé çļåîɱ one tw]'; + + @override + String get boardEventExpired => '[Ţĥé çļåîɱ éẋþîŕéð one tw]'; + + @override + String boardEventPrLinked(String url) { + return '[ļîñķéð å þûļļ ŕéǫûéšţ: $url one two]'; + } + + @override + String get boardEventPrUnlinked => '[ûñļîñķéð ţĥé þûļļ ŕéǫûéšţ one two]'; + + @override + String get boardEventPublished => '[þûƀļîšĥéð ţĥé ţåšķ one tw]'; + + @override + String get boardEventDone => '[ɱåŕķéð ţĥé ţåšķ ðöñé one tw]'; + + @override + String get boardEventShipped => '[ɱåŕķéð ţĥé ţåšķ šĥîþþéð one two]'; + + @override + String get boardEventCancelled => '[çåñçéļļéð ţĥé ţåšķ one tw]'; + + @override + String get boardEventMerged => '[ɱéŕĝéð å ðûþļîçåţé one tw]'; + + @override + String boardEventMergedInto(String task) { + return '[ɱéŕĝéð ţĥîš ţåšķ îñţö $task one two]'; + } + + @override + String boardEventMergedTasks(String tasks) { + return '[ɱéŕĝéð $tasks îñţö ţĥîš ţåšķ one two]'; + } + + @override + String get boardEventUnmerged => '[ûñðîð å ɱéŕĝé öƒ ţåšķš one two]'; + + @override + String get boardEventRewriting => + '[çĥåñĝéð ţĥé îššûéš; ţĥé ţåšķ îš å ðŕåƒţ ûñţîļ ţĥé ÅÎ ĥåš ŕéŵŕîţţéñ ţĥé þŕöɱþţ one two three four five]'; + + @override + String boardMergeTasksTitle(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: 'Ṁéŕĝé $count ţåšķš…', + one: 'Ṁéŕĝé 1 ţåšķ…', + ); + return '[$_temp0 one two]'; + } + + @override + String get boardMergeTasksHint => + '[Ţĥé öļðéšţ ţåšķ ķééþš åļļ ţĥé îššûéš åñð ĝéţš å ñéŵ ÅÎ-ŵŕîţţéñ þŕöɱþţ. Ţĥé öţĥéŕ ţåšķš åŕé çåñçéļļéð. Ûñţîļ ţĥé þŕöɱþţ îš ŵŕîţţéñ, ţĥé ţåšķ îš å ðŕåƒţ. one two three four five six seven eight nine]'; + + @override + String get boardMergeTasksNeedsTwo => + '[Šéļéçţ ţŵö ţåšķš öŕ ɱöŕé ţö ɱéŕĝé ţĥéɱ one two thr]'; + + @override + String boardTaskMergedNotice(int number) { + return '[Ţĥîš ţåšķ ŵåš ɱéŕĝéð îñţö Ţ-$number. one two t]'; + } + + @override + String boardOpenTask(int number) { + return '[Öþéñ Ţ-$number one]'; + } + + @override + String get cmdBoardMergeTasks => '[Ṁéŕĝé ţåšķš one]'; + + @override + String get boardUpForGrabs => '[Ûþ ƒöŕ ĝŕåƀš one]'; + + @override + String boardClaimedBy(String name, int hours) { + return '[Çļåîɱéð ƀý $name · $hours ĥ ļéƒţ one tw]'; + } + + @override + String boardInReviewBy(String name) { + return '[Îñ ŕéṽîéŵ · $name one]'; + } + + @override + String boardPostCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count îššûéš', + one: '1 îššûé', + ); + return '[$_temp0 one t]'; + } + + @override + String get boardClaimTask => '[Çļåîɱ ţĥîš ţåšķ one t]'; + + @override + String get boardReleaseClaim => '[Ŕéļéåšé çļåîɱ one t]'; + + @override + String get boardYourClaimCode => '[Ýöûŕ çļåîɱ çöðé one t]'; + + @override + String boardTimeLeft(int hours) { + return '[$hours ĥ ļéƒţ öñ ýöûŕ çļåîɱ one tw]'; + } + + @override + String get boardClaimCodeHint => + '[Þûţ îţ îñ ţĥé þûļļ ŕéǫûéšţ ðéšçŕîþţîöñ. Öñļý ýöû çåñ šéé îţ. one two three four]'; + + @override + String get boardClaimCodePlaceholder => '[<ýöûŕ çļåîɱ çöðé> one tw]'; + + @override + String get boardDraftNotice => + '[Ðŕåƒţ: öñļý åðɱîñš šéé ţĥîš ţåšķ. Îţ îš þûƀļîšĥéð öñçé ţĥé ÅÎ ĥåš ŵŕîţţéñ îţš þŕöɱþţ, öŕ ŵĥéñ ýöû šåṽé ţĥé þŕöɱþţ. one two three four five six seven]'; + + @override + String get boardPromptWriting => + '[Ŵŕîţîñĝ ţĥé þŕöɱþţ ŵîţĥ ÅÎ… ţĥîš ţåķéš åƀöûţ å ɱîñûţé one two three fo]'; + + @override + String boardPromptNote(String note) { + return '[Ţĥé ÅÎ ðîð ñöţ ŵŕîţé ţĥé þŕöɱþţ: $note one two th]'; + } + + @override + String get boardTaskCancelledNotice => + '[Ţĥîš ţåšķ ŵåš çåñçéļļéð. Îţš îššûéš åŕé öþéñ åĝåîñ. one two three fo]'; + + @override + String get boardLinkedPosts => '[Ļîñķéð îššûéš one t]'; + + @override + String get boardNoLinkedPosts => + '[Ñö îššûéš åŕé ļîñķéð ţö ţĥîš ţåšķ. one two th]'; + + @override + String get boardRemoveFromTask => '[Ŕéɱöṽé ƒŕöɱ ţåšķ one t]'; + + @override + String get boardAddPosts => '[Åðð îššûéš… one]'; + + @override + String get boardFieldPostNumbers => '[Κšûé ñûɱƀéŕš one t]'; + + @override + String get boardHowToBuild => '[Ĥöŵ ţö ƀûîļð îţ one t]'; + + @override + String get boardStepSetupNumber => '[1. o]'; + + @override + String get boardStepSetupLink => + '[Šéţ ûþ ýöûŕ ðéṽéļöþɱéñţ éñṽîŕöñɱéñţ one two thr]'; + + @override + String get boardInstallTools => + '[Îñšţåļļ Ƒļûţţéŕ, Ðåŕţ åñð ţĥé Šéŕṽéŕþöð ÇĻÎ: one two three]'; + + @override + String get boardInstallGuide => '[Šéŕṽéŕþöð îñšţåļļåţîöñ ĝûîðé one two th]'; + + @override + String get boardStepPrompt => + '[2. Ĝîṽé ýöûŕ çöðîñĝ åĝéñţ ţĥé þŕöɱþţ one two thr]'; + + @override + String get boardStepPr => '[3. Öþéñ å þûļļ ŕéǫûéšţ one two]'; + + @override + String get boardStepPromptLocked => + '[2. Ĝîṽé ýöûŕ çöðîñĝ åĝéñţ ţĥé þŕöɱþţ (çļåîɱ ţĥé ţåšķ ţö ĝéţ ţĥé þŕöɱþţ). one two three four fi]'; + + @override + String get boardPrRules => + '[Öñé ţåšķ þéŕ þûļļ ŕéǫûéšţ, åĝåîñšţ ɱåîñ. Þûţ ţĥéšé ţŵö ļîñéš îñ îţš ðéšçŕîþţîöñ: one two three four five]'; + + @override + String get boardPullRequest => '[Þûļļ ŕéǫûéšţ one]'; + + @override + String boardPrNumber(int number) { + return '[Þûļļ ŕéǫûéšţ #$number one t]'; + } + + @override + String boardPrBy(String login) { + return '[ƀý $login o]'; + } + + @override + String get boardLatestReview => '[Ļåţéšţ ŕéṽîéŵ one t]'; + + @override + String get boardActivity => '[Åçţîṽîţý one]'; + + @override + String get boardNoActivity => '[Ñö åçţîṽîţý ýéţ one t]'; + + @override + String get boardClaimForPrompt => + '[Çļåîɱ ţĥîš ţåšķ ţö ĝéţ ţĥé þŕöɱþţ. one two th]'; + + @override + String get boardContributeTitle => '[Ĥöŵ ţö çöñţŕîƀûţé one tw]'; + + @override + String get boardContributeIntro => + '[Åñýöñé çåñ ƀûîļð å ţåšķ ţĥåţ îš ûþ ƒöŕ ĝŕåƀš. Çļåîɱ îţ, ļéţ å çöðîñĝ åĝéñţ ðö ţĥé ŵöŕķ ŵîţĥ ţĥé ţåšķ\'š þŕöɱþţ, åñð öþéñ å þûļļ ŕéǫûéšţ. one two three four five six seven eigh]'; + + @override + String get boardContribStep1Title => '[Ĝéţ ţĥé ţööļš one]'; + + @override + String get boardContribStep1 => + '[Îñšţåļļ Ƒļûţţéŕ, Ðåŕţ åñð ţĥé Šéŕṽéŕþöð ÇĻÎ, åñð åñ ÅÎ çöðîñĝ åĝéñţ ţĥåţ ŕéåðš ÅĜÉÑŢŠ.ɱð, šûçĥ åš Çļåûðé Çöðé. one two three four five six seven]'; + + @override + String get boardContribStep2Title => + '[Îñšţåļļ öŕ ûþðåţé ţĥé Šéŕṽéŕþöð ÇĻÎ one two thr]'; + + @override + String get boardContribStep2 => + '[Îţ ŕûñš ţĥé šéŕṽéŕ åñð ţĥé åþþš. Ţĥé šåɱé çöɱɱåñð ûþðåţéš åñ îñšţåļļéð ÇĻÎ ţö ţĥîš ṽéŕšîöñ. Åðð Ðåŕţ\'š îñšţåļļ ðîŕéçţöŕý ţö ýöûŕ ÞÅŢĤ îƒ šéŕṽéŕþöð îš ñöţ ƒöûñð. one two three four five six seven eight nine te]'; + + @override + String get boardContribStep3Title => '[Ƒöŕķ ţĥé ŕéþöšîţöŕý one tw]'; + + @override + String get boardContribStep3 => + '[Çŕéåţé ýöûŕ öŵñ çöþý öƒ ţĥé ŕéþöšîţöŕý öñ ĜîţĤûƀ. Ýöû þûšĥ ýöûŕ çĥåñĝéš ţö ýöûŕ ƒöŕķ åñð öþéñ ţĥé þûļļ ŕéǫûéšţ ƒŕöɱ ţĥéŕé. one two three four five six seven e]'; + + @override + String get boardContribForkLink => '[Ƒöŕķ öñ ĜîţĤûƀ one t]'; + + @override + String get boardContribStep4Title => '[Çļöñé ţĥé ŕéþöšîţöŕý one two]'; + + @override + String get boardContribStep4 => + '[Çļöñé ýöûŕ ƒöŕķ ţö ýöûŕ ɱåçĥîñé (ŕéþļåçé <ýöû> ŵîţĥ ýöûŕ ĜîţĤûƀ ûšéŕñåɱé) åñð ĝéţ ţĥé þåçķåĝéš. one two three four five six]'; + + @override + String get boardContribStep5Title => '[Çöñƒîĝûŕé ţĥé šéŕṽéŕ one two]'; + + @override + String get boardContribStep5 => + '[Çŕéåţé ýöûŕ þåššŵöŕðš ƒîļé îñ ŵöñķý_šéŕṽéŕ åñð ŕéþļåçé ţĥé ÇĤÅÑĜÉ_ṀÉ ṽåļûéš. ÅÎ ķéýš åŕé öþţîöñåļ. one two three four five six se]'; + + @override + String get boardContribStep6Title => '[Šţåŕţ ţĥé šéŕṽéŕ one t]'; + + @override + String get boardContribStep6 => + '[Ŕûñ îţ îñ ŵöñķý_šéŕṽéŕ: îţ šţåŕţš ţĥé ðéṽéļöþɱéñţ ðåţåƀåšé, åþþļîéš ţĥé ɱîĝŕåţîöñš åñð ĥöţ ŕéļöåðš. Šţåŕţ åñ åþþ ƒŕöɱ îţš ÛÎ öŕ ļéţ ýöûŕ åĝéñţ ðö îţ ţĥŕöûĝĥ ţĥé šéŕṽéŕþöð ṀÇÞ šéŕṽéŕ (.ɱçþ.ĵšöñ îš îñ ţĥé ŕéþöšîţöŕý). Šîĝñ ûþ ŵîţĥ åñý éɱåîļ; îñ ðéṽéļöþɱéñţ ţĥé çöðé îš îñ ţĥé šéŕṽéŕ ļöĝ. one two three four five six seven eight nine ten one two three four five six seven]'; + + @override + String get boardContribStep7Title => '[Þîçķ å ţåšķ one]'; + + @override + String get boardContribStep7 => + '[Çļåîɱ å ţåšķ ûñðéŕ Ûþ ƒöŕ ĝŕåƀš, þåšţé îţš þŕöɱþţ îñţö ýöûŕ åĝéñţ åñð ŕéṽîéŵ ţĥé ŕéšûļţ. one two three four five si]'; + + @override + String get boardContribStep8Title => '[Öþéñ å þûļļ ŕéǫûéšţ one tw]'; + + @override + String get boardContribStep8 => + '[Öñé ţåšķ þéŕ þûļļ ŕéǫûéšţ. Ţĥé ðéšçŕîþţîöñ çöñţåîñš ţĥé Ŵöñķý-Ţåšķ åñð Ŵöñķý-Çļåîɱ ļîñéš ƒŕöɱ ţĥé ţåšķ þåĝé. Þûļļ ŕéǫûéšţš ŵîţĥöûţ å ṽåļîð ţåšķ åŕé çļöšéð åƒţéŕ 7 ðåýš. one two three four five six seven eight nine ten o]'; + + @override + String get boardContribStep9Title => '[Šîĝñ ţĥé ÇĻÅ åñð ƒöļļöŵ ûþ one two]'; + + @override + String get boardContribStep9 => + '[΃ ýöû ĥåṽéñ\'ţ šîĝñéð ţĥé Šéŕṽéŕþöð çöñţŕîƀûţöŕ ļîçéñšé åĝŕééɱéñţ (ÇĻÅ) ýéţ, šîĝñ îţ öñ ĜîţĤûƀ: ţĥé ÇĻÅ Åššîšţåñţ ƀöţ åšķš ƒöŕ îţ öñ ýöûŕ þûļļ ŕéǫûéšţ, åñð ýöû ŕéþļý ŵîţĥ ţĥé ļîñé ƀéļöŵ. Ýöû šîĝñ îţ öñçé. Ţĥéñ çĥéçķ ƀåçķ öñçé ýöûŕ þûļļ ŕéǫûéšţ ĥåš ƀééñ ŕéṽîéŵéð, åñð ƒîẋ åñý îššûéš ţĥé ŕéṽîéŵ þöîñţš öûţ. one two three four five six seven eight nine ten one two three four five six seven eight]'; + + @override + String get boardContribLicense => + '[Çöñţŕîƀûţîöñš åŕé åççéþţéð ûñðéŕ ţĥé ŕéþöšîţöŕý\'š ƁŠÐ-3-Çļåûšé ļîçéñšé. one two three four five]'; + + @override + String boardContribSecurity(String email) { + return '[Ƒöûñð å šéçûŕîţý îššûé? Éɱåîļ $email. Ñéṽéŕ þöšţ îţ öñ ţĥé ƀöåŕð öŕ îñ å þûļļ ŕéǫûéšţ. one two three four five]'; + } + + @override + String get boardContributeGuide => '[Ƒûļļ ĝûîðé öñ ĜîţĤûƀ one tw]'; + + @override + String get boardFieldTitle => '[Ţîţļé on]'; + + @override + String get boardTitleLength => '[Ûšé 8 ţö 120 çĥåŕåçţéŕš. one two]'; + + @override + String get boardModeratorEditHint => + '[Ţĥé îššûé šĥöŵš Éðîţéð ƀý å ɱöðéŕåţöŕ. one two thre]'; + + @override + String get boardFieldReason => '[Ŕéåšöñ one]'; + + @override + String get boardFieldNote => '[Ñöţé (öþţîöñåļ) one t]'; + + @override + String get boardFieldNoteForAuthor => + '[Ṁéššåĝé ţö ţĥé åûţĥöŕ (öþţîöñåļ) one two th]'; + + @override + String get boardFlagHint => + '[Ƒļåĝĝéð îššûéš åŕé ĥîððéñ ƒöŕ ŕéṽîéŵ åƒţéŕ 3 þéöþļé ƒļåĝ ţĥéɱ. one two three four]'; + + @override + String get boardFlagAction => '[Ƒļåĝ on]'; + + @override + String get boardRemoveTitle => '[Ŕéɱöṽé one]'; + + @override + String get boardDeclineOutOfScope => '[Öûţ öƒ šçöþé one]'; + + @override + String get boardDeclineAsIntended => '[Ŵöŕķš åš îñţéñðéð one tw]'; + + @override + String get boardDeclineWontFix => '[Ŵöñ\'ţ ƒîẋ one]'; + + @override + String boardBlockHint(String name) { + return '[$name çåñ šţîļļ ŕéåð ţĥé ƀöåŕð ƀûţ çåñ\'ţ þöšţ, ṽöţé öŕ çöɱɱéñţ. one two three fou]'; + } + + @override + String boardMergeHint(int number) { + return '[Ṽöţéš öñ #$number ɱöṽé ţö ţĥé îššûé ţĥåţ ŕéɱåîñš. one two thre]'; + } + + @override + String get boardFieldTargetPost => '[Κšûé ţĥåţ ŕéɱåîñš one tw]'; + + @override + String get boardInvalidPostNumber => '[Éñţéŕ åñ îššûé ñûɱƀéŕ one two]'; + + @override + String get boardMergeSelf => + '[Åñ îššûé çåñ\'ţ ƀé ɱéŕĝéð îñţö îţšéļƒ one two thr]'; + + @override + String get boardFieldKind => '[Ķîñð on]'; + + @override + String get boardFieldArea => '[Åŕéå on]'; + + @override + String get boardFieldSize => '[Šîžé on]'; + + @override + String get boardNoLabel => '[Ñöţ šéţ one]'; + + @override + String get boardFieldTask => '[Ţåšķ on]'; + + @override + String get boardLinkPrHint => + '[Å þûļļ ŕéǫûéšţ öƒ ţĥé ŕéþöšîţöŕý. Ļéåṽé îţ éɱþţý ţö ûñļîñķ. one two three four]'; + + @override + String get boardFieldPrUrl => '[Þûļļ ŕéǫûéšţ ÛŔĻ one t]'; + + @override + String get boardInvalidPrUrl => + '[Ûšé å ĝîţĥûƀ.çöɱ þûļļ ŕéǫûéšţ ÛŔĻ one two th]'; + + @override + String get boardRemoveScreenshotHint => + '[Ţĥé šçŕééñšĥöţ îš ðéļéţéð ƒöŕ ĝööð. one two thr]'; + + @override + String boardPromptEditorTitle(int number) { + return '[Þŕöɱþţ öƒ Ţ-$number one]'; + } + + @override + String get boardPromptEditorHint => + '[Çöñţŕîƀûţöŕš ŕûñ ţĥîš þŕöɱþţ îñ çöðîñĝ åĝéñţš. Ŕéåð îţ åļļ ƀéƒöŕé šåṽîñĝ. one two three four fiv]'; + + @override + String get boardPromptSavePublishes => + '[Šåṽîñĝ þûƀļîšĥéš ţĥé ţåšķ. one two t]'; + + @override + String get boardPromptDiffTitle => '[Çĥåñĝéš ƒŕöɱ Ŕéĝéñéŕåţé one two]'; + + @override + String boardLintTitle(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count ûñûšûåļ îñšţŕûçţîöñš', + one: '1 ûñûšûåļ îñšţŕûçţîöñ', + ); + return '[$_temp0: çĥéçķ ƀéƒöŕé šåṽîñĝ one two three four f]'; + } + + @override + String boardLintCommand(int line, String text) { + return '[Ļîñé $line: çöɱɱåñð $text one t]'; + } + + @override + String boardLintUrl(int line, String text) { + return '[Ļîñé $line: ļîñķ öûţšîðé ţĥé ŕéþöšîţöŕý $text one two thr]'; + } + + @override + String boardLintWording(int line, String text) { + return '[Ļîñé $line: “$text” one]'; + } + + @override + String get boardReviewHeld => '[Ĥéļð on]'; + + @override + String get boardReviewCheck => '[Çĥéçķ on]'; + + @override + String get boardReviewUnchecked => '[Ûñçĥéçķéð one]'; + + @override + String get boardReviewDuplicates => '[Þöššîƀļé ðûþļîçåţéš one two]'; + + @override + String get boardReviewBundles => '[Šûĝĝéšţéð ƀûñðļéš one tw]'; + + @override + String get boardReviewDrafts => '[Ðŕåƒţ ţåšķš one]'; + + @override + String get boardReviewEmpty => '[Ñöţĥîñĝ ţö ŕéṽîéŵ. one tw]'; + + @override + String get cmdBoardVote => '[Ṽöţé on]'; + + @override + String get cmdBoardCreatePost => '[Ŕéþöŕţ îššûé one]'; + + @override + String get cmdBoardEditPost => '[Éðîţ îššûé one]'; + + @override + String get cmdBoardDeletePost => '[Ðéļéţé îššûé one]'; + + @override + String get cmdBoardRemoveScreenshot => '[Ŕéɱöṽé šçŕééñšĥöţ one tw]'; + + @override + String get cmdBoardComment => '[Çöɱɱéñţ one]'; + + @override + String get cmdBoardEditComment => '[Éðîţ çöɱɱéñţ one]'; + + @override + String get cmdBoardDeleteComment => '[Ðéļéţé çöɱɱéñţ one t]'; + + @override + String get cmdBoardFlag => '[Ƒļåĝ… on]'; + + @override + String get cmdBoardClaim => '[Çļåîɱ ţåšķ one]'; + + @override + String get cmdBoardRelease => '[Ûñçļåîɱ ţĥîš ţåšķ one tw]'; + + @override + String get cmdBoardCopyPrompt => '[Çöþý þŕöɱþţ one]'; + + @override + String get cmdBoardCopyClaimCode => '[Çöþý çļåîɱ çöðé one t]'; + + @override + String get cmdBoardModerate => '[Ṁöðéŕåţé one]'; + + @override + String get cmdBoardSetLabels => '[Šéţ ķîñð, åŕéå åñð šîžé… one two]'; + + @override + String get cmdBoardAdminEdit => '[Éðîţ åš ɱöðéŕåţöŕ… one tw]'; + + @override + String get cmdBoardApplyTitle => '[Åþþļý šûĝĝéšţéð ţîţļé one two]'; + + @override + String get cmdBoardNotDuplicate => '[Ñöţ å ðûþļîçåţé one t]'; + + @override + String get cmdBoardMerge => '[Ṁéŕĝé îñţö… one]'; + + @override + String get cmdBoardUnmerge => '[Ûñɱéŕĝé one]'; + + @override + String get cmdBoardDecline => '[Ðéçļîñé one]'; + + @override + String get cmdBoardReopen => '[Ŕéöþéñ one]'; + + @override + String get cmdBoardBlock => '[Ɓļöçķ ûšéŕ ƒŕöɱ ţĥé ƀöåŕð one two]'; + + @override + String get cmdBoardCreateTask => '[Çŕéåţé ţåšķ one]'; + + @override + String get cmdBoardEditTask => '[Éðîţ ţåšķ one]'; + + @override + String get cmdBoardSetTaskPosts => '[Çĥåñĝé ţĥé ţåšķ\'š îššûéš one two]'; + + @override + String get cmdBoardRegeneratePrompt => '[Ŕéĝéñéŕåţé þŕöɱþţ one tw]'; + + @override + String get cmdBoardEditPrompt => '[Éðîţ þŕöɱþţ one]'; + + @override + String get cmdBoardPublishTask => '[Þûƀļîšĥ ţåšķ one]'; + + @override + String get cmdBoardLinkPr => '[Ļîñķ þûļļ ŕéǫûéšţ… one tw]'; + + @override + String get cmdBoardMarkDone => '[Ṁåŕķ ðöñé one]'; @override - String get boardInstallGuide => '[Šéŕṽéŕþöð îñšţåļļåţîöñ ĝûîðé one two th]'; + String get cmdBoardMarkShipped => '[Ṁåŕķ šĥîþþéð one]'; @override - String get boardStepPrompt => - '[2. Ĝîṽé ýöûŕ çöðîñĝ åĝéñţ ţĥé þŕöɱþţ one two thr]'; + String get cmdBoardCancelTask => '[Çåñçéļ ţåšķ one]'; @override - String get boardStepPr => '[3. Öþéñ å þûļļ ŕéǫûéšţ one two]'; + String get cmdBoardSuggestBundles => '[Šûĝĝéšţ ƀûñðļéš one t]'; @override - String get boardStepPromptLocked => - '[2. Ĝîṽé ýöûŕ çöðîñĝ åĝéñţ ţĥé þŕöɱþţ (çļåîɱ ţĥé ţåšķ ţö ĝéţ ţĥé þŕöɱþţ). one two three four fi]'; + String get cmdBoardDismissSuggestion => '[Ðîšɱîšš šûĝĝéšţîöñ one tw]'; @override - String get boardPrRules => - '[Öñé ţåšķ þéŕ þûļļ ŕéǫûéšţ, åĝåîñšţ ɱåîñ. Þûţ ţĥéšé ţŵö ļîñéš îñ îţš ðéšçŕîþţîöñ: one two three four five]'; + String get notifyBoard => '[Ɓûĝš & îɱþŕöṽéɱéñţš one tw]'; @override - String get boardPullRequest => '[Þûļļ ŕéǫûéšţ one]'; + String get notifyBoardHint => + '[Ŕéþļîéš ţö ýöûŕ îššûéš, šţåţûš çĥåñĝéš åñð ýöûŕ ţåšķ çļåîɱš one two three four]'; @override - String boardPrNumber(int number) { - return '[Þûļļ ŕéǫûéšţ #$number one t]'; + String boardEventPrClosed(String url) { + return '[Þûļļ ŕéǫûéšţ çļöšéð ŵîţĥöûţ ɱéŕĝé: $url. Ţĥé ţåšķ îš öþéñ åĝåîñ. one two three four]'; } @override - String boardPrBy(String login) { - return '[ƀý $login o]'; + String boardEventPrMerged(String url) { + return '[Þûļļ ŕéǫûéšţ ɱéŕĝéð: $url one two]'; } @override - String get boardLatestReview => '[Ļåţéšţ ŕéṽîéŵ one t]'; - - @override - String get boardActivity => '[Åçţîṽîţý one]'; + String boardEventPrOpened(String url) { + return '[Þûļļ ŕéǫûéšţ öþéñéð: $url one two]'; + } @override - String get boardNoActivity => '[Ñö åçţîṽîţý ýéţ one t]'; + String boardEventDeployed(String sha) { + return '[Šĥîþþéð îñ ðéþļöý $sha one tw]'; + } @override - String get boardClaimForPrompt => - '[Çļåîɱ ţĥîš ţåšķ ţö ĝéţ ţĥé þŕöɱþţ. one two th]'; + String get boardVerdictMet => '[Ṁéţ on]'; @override - String get boardContributeTitle => '[Ĥöŵ ţö çöñţŕîƀûţé one tw]'; + String get boardVerdictPartly => '[Þåŕţļý one]'; @override - String get boardContributeIntro => - '[Åñýöñé çåñ ƀûîļð å ţåšķ ţĥåţ îš ûþ ƒöŕ ĝŕåƀš. Çļåîɱ îţ, ļéţ å çöðîñĝ åĝéñţ ðö ţĥé ŵöŕķ ŵîţĥ ţĥé ţåšķ\'š þŕöɱþţ, åñð öþéñ å þûļļ ŕéǫûéšţ. one two three four five six seven eigh]'; + String get boardVerdictNotMet => '[Ñöţ ɱéţ one]'; @override - String get boardContribStep1Title => '[Ĝéţ ţĥé ţööļš one]'; + String get boardVerdictCantTell => '[Çåñ\'ţ ţéļļ one]'; @override - String get boardContribStep1 => - '[Îñšţåļļ Ƒļûţţéŕ, Ðåŕţ åñð ţĥé Šéŕṽéŕþöð ÇĻÎ, åñð åñ ÅÎ çöðîñĝ åĝéñţ ţĥåţ ŕéåðš ÅĜÉÑŢŠ.ɱð, šûçĥ åš Çļåûðé Çöðé. one two three four five six seven]'; + String get boardVerdictAdded => '[Åððéð on]'; @override - String get boardContribStep2Title => - '[Îñšţåļļ öŕ ûþðåţé ţĥé Šéŕṽéŕþöð ÇĻÎ one two thr]'; + String get boardVerdictUpdated => '[Ûþðåţéð one]'; @override - String get boardContribStep2 => - '[Îţ ŕûñš ţĥé šéŕṽéŕ åñð ţĥé åþþš. Ţĥé šåɱé çöɱɱåñð ûþðåţéš åñ îñšţåļļéð ÇĻÎ ţö ţĥîš ṽéŕšîöñ. Åðð Ðåŕţ\'š îñšţåļļ ðîŕéçţöŕý ţö ýöûŕ ÞÅŢĤ îƒ šéŕṽéŕþöð îš ñöţ ƒöûñð. one two three four five six seven eight nine te]'; + String get boardVerdictMissing => '[Ṁîššîñĝ one]'; @override - String get boardContribStep3Title => '[Ƒöŕķ ţĥé ŕéþöšîţöŕý one tw]'; + String get boardVerdictNotNeeded => '[Ñöţ ñééðéð one]'; @override - String get boardContribStep3 => - '[Çŕéåţé ýöûŕ öŵñ çöþý öƒ ţĥé ŕéþöšîţöŕý öñ ĜîţĤûƀ. Ýöû þûšĥ ýöûŕ çĥåñĝéš ţö ýöûŕ ƒöŕķ åñð öþéñ ţĥé þûļļ ŕéǫûéšţ ƒŕöɱ ţĥéŕé. one two three four five six seven e]'; + String get boardReviewTests => '[Ţéšţš on]'; @override - String get boardContribForkLink => '[Ƒöŕķ öñ ĜîţĤûƀ one t]'; + String get boardReviewSpecs => '[Šþéçš on]'; @override - String get boardContribStep4Title => '[Çļöñé ţĥé ŕéþöšîţöŕý one two]'; + String get boardReviewRisks => '[Ŕîšķš on]'; @override - String get boardContribStep4 => - '[Çļöñé ýöûŕ ƒöŕķ ţö ýöûŕ ɱåçĥîñé (ŕéþļåçé <ýöû> ŵîţĥ ýöûŕ ĜîţĤûƀ ûšéŕñåɱé) åñð ĝéţ ţĥé þåçķåĝéš. one two three four five six]'; + String get boardReviewUnrelated => + '[Çĥåñĝéš ţĥé ţåšķ ðîðñ\'ţ åšķ ƒöŕ one two th]'; @override - String get boardContribStep5Title => '[Çöñƒîĝûŕé ţĥé šéŕṽéŕ one two]'; + String boardReviewedSha(String sha) { + return '[Ŕéṽîéŵéð åţ $sha one]'; + } @override - String get boardContribStep5 => - '[Çŕéåţé ýöûŕ þåššŵöŕðš ƒîļé îñ ŵöñķý_šéŕṽéŕ åñð ŕéþļåçé ţĥé ÇĤÅÑĜÉ_ṀÉ ṽåļûéš. ÅÎ ķéýš åŕé öþţîöñåļ. one two three four five six se]'; + String get settingsPublications => '[Þûƀļîçåţîöñš one t]'; @override - String get boardContribStep6Title => '[Šţåŕţ ţĥé šéŕṽéŕ one t]'; + String get pubSectionHint => + '[Ļéţ þéöþļé ŵŕîţé ƒöŕ ýöûŕ ƀļöĝ îñ Ŵöñķý Ŵŕîţé åñð šéñð šţöŕîéš ţö ýöûŕ ŕéṽîéŵ ǫûéûé ŵîţĥ öñé ƀûţţöñ. one two three four five six s]'; @override - String get boardContribStep6 => - '[Ŕûñ îţ îñ ŵöñķý_šéŕṽéŕ: îţ šţåŕţš ţĥé ðéṽéļöþɱéñţ ðåţåƀåšé, åþþļîéš ţĥé ɱîĝŕåţîöñš åñð ĥöţ ŕéļöåðš. Šţåŕţ åñ åþþ ƒŕöɱ îţš ÛÎ öŕ ļéţ ýöûŕ åĝéñţ ðö îţ ţĥŕöûĝĥ ţĥé šéŕṽéŕþöð ṀÇÞ šéŕṽéŕ (.ɱçþ.ĵšöñ îš îñ ţĥé ŕéþöšîţöŕý). Šîĝñ ûþ ŵîţĥ åñý éɱåîļ; îñ ðéṽéļöþɱéñţ ţĥé çöðé îš îñ ţĥé šéŕṽéŕ ļöĝ. one two three four five six seven eight nine ten one two three four five six seven]'; + String get pubNew => '[Ñéŵ þûƀļîçåţîöñ one t]'; @override - String get boardContribStep7Title => '[Þîçķ å ţåšķ one]'; + String get pubNewHint => + '[Ŵöñķý šéñðš šûƀɱîţţéð šţöŕîéš ţö ýöûŕ ŵéƀĥööķ. Ýöû ĝéţ ţĥé šîĝñîñĝ šéçŕéţ öñçé, åƒţéŕ ýöû çŕéåţé ţĥé þûƀļîçåţîöñ. one two three four five six seven]'; @override - String get boardContribStep7 => - '[Çļåîɱ å ţåšķ ûñðéŕ Ûþ ƒöŕ ĝŕåƀš, þåšţé îţš þŕöɱþţ îñţö ýöûŕ åĝéñţ åñð ŕéṽîéŵ ţĥé ŕéšûļţ. one two three four five si]'; + String pubEdit(String name) { + return '[Éðîţ “$name” one]'; + } @override - String get boardContribStep8Title => '[Öþéñ å þûļļ ŕéǫûéšţ one tw]'; + String get pubEditButton => '[Éðîţ… on]'; @override - String get boardContribStep8 => - '[Öñé ţåšķ þéŕ þûļļ ŕéǫûéšţ. Ţĥé ðéšçŕîþţîöñ çöñţåîñš ţĥé Ŵöñķý-Ţåšķ åñð Ŵöñķý-Çļåîɱ ļîñéš ƒŕöɱ ţĥé ţåšķ þåĝé. Þûļļ ŕéǫûéšţš ŵîţĥöûţ å ṽåļîð ţåšķ åŕé çļöšéð åƒţéŕ 7 ðåýš. one two three four five six seven eight nine ten o]'; + String get pubGuide => '[Ðéṽéļöþéŕ ĝûîðé one t]'; @override - String get boardContribStep9Title => '[Šîĝñ ţĥé ÇĻÅ åñð ƒöļļöŵ ûþ one two]'; + String get pubEmpty => '[Ýöû ĥåṽé ñö þûƀļîçåţîöñš ýéţ. one two t]'; @override - String get boardContribStep9 => - '[΃ ýöû ĥåṽéñ\'ţ šîĝñéð ţĥé Šéŕṽéŕþöð çöñţŕîƀûţöŕ ļîçéñšé åĝŕééɱéñţ (ÇĻÅ) ýéţ, šîĝñ îţ öñ ĜîţĤûƀ: ţĥé ÇĻÅ Åššîšţåñţ ƀöţ åšķš ƒöŕ îţ öñ ýöûŕ þûļļ ŕéǫûéšţ, åñð ýöû ŕéþļý ŵîţĥ ţĥé ļîñé ƀéļöŵ. Ýöû šîĝñ îţ öñçé. Ţĥéñ çĥéçķ ƀåçķ öñçé ýöûŕ þûļļ ŕéǫûéšţ ĥåš ƀééñ ŕéṽîéŵéð, åñð ƒîẋ åñý îššûéš ţĥé ŕéṽîéŵ þöîñţš öûţ. one two three four five six seven eight nine ten one two three four five six seven eight]'; + String get pubName => '[Ñåɱé on]'; @override - String get boardContribLicense => - '[Çöñţŕîƀûţîöñš åŕé åççéþţéð ûñðéŕ ţĥé ŕéþöšîţöŕý\'š ƁŠÐ-3-Çļåûšé ļîçéñšé. one two three four five]'; + String get pubSiteUrl => '[Šîţé ÛŔĻ one]'; @override - String boardContribSecurity(String email) { - return '[Ƒöûñð å šéçûŕîţý îššûé? Éɱåîļ $email. Ñéṽéŕ þöšţ îţ öñ ţĥé ƀöåŕð öŕ îñ å þûļļ ŕéǫûéšţ. one two three four five]'; - } + String get pubWebhookUrl => '[Ŵéƀĥööķ ÛŔĻ one]'; @override - String get boardContributeGuide => '[Ƒûļļ ĝûîðé öñ ĜîţĤûƀ one tw]'; + String get pubTermsUrl => '[Çöñţŕîƀûţöŕ ţéŕɱš ÛŔĻ (öþţîöñåļ) one two thr]'; @override - String get boardFieldTitle => '[Ţîţļé on]'; + String get pubTemplate => '[Ţéɱþļåţé ðöçûɱéñţ (öþţîöñåļ) one two th]'; @override - String get boardTitleLength => '[Ûšé 8 ţö 120 çĥåŕåçţéŕš. one two]'; + String get pubTemplateHint => + '[Þåšţé å ļîñķ ţö öñé öƒ ýöûŕ Ŵöñķý Ŵŕîţé ðöçûɱéñţš one two three]'; @override - String get boardModeratorEditHint => - '[Ţĥé îššûé šĥöŵš Éðîţéð ƀý å ɱöðéŕåţöŕ. one two thre]'; + String get pubTemplateInvalid => + '[Þåšţé ţĥé ļîñķ öƒ å Ŵöñķý Ŵŕîţé ðöçûɱéñţ. one two thre]'; @override - String get boardFieldReason => '[Ŕéåšöñ one]'; + String get pubRequired => '[Ŕéǫûîŕéð. one]'; @override - String get boardFieldNote => '[Ñöţé (öþţîöñåļ) one t]'; + String get pubHttpsOnly => '[Ûšé åñ ĥţţþš:// åððŕéšš. one two]'; @override - String get boardFieldNoteForAuthor => - '[Ṁéššåĝé ţö ţĥé åûţĥöŕ (öþţîöñåļ) one two th]'; + String get pubFieldSummary => '[Šûɱɱåŕý one]'; @override - String get boardFlagHint => - '[Ƒļåĝĝéð îššûéš åŕé ĥîððéñ ƒöŕ ŕéṽîéŵ åƒţéŕ 3 þéöþļé ƒļåĝ ţĥéɱ. one two three four]'; + String get pubFieldTags => '[Ţåĝš on]'; @override - String get boardFlagAction => '[Ƒļåĝ on]'; + String get pubAllowedTags => '[Åļļöŵéð ţåĝš (öþţîöñåļ) one two]'; @override - String get boardRemoveTitle => '[Ŕéɱöṽé one]'; + String get pubAllowedTagsHint => + '[Çöɱɱå šéþåŕåţéð; éɱþţý åļļöŵš åñý ţåĝ one two thre]'; @override - String get boardDeclineOutOfScope => '[Öûţ öƒ šçöþé one]'; + String get pubFieldCover => '[Çöṽéŕ îɱåĝé one]'; @override - String get boardDeclineAsIntended => '[Ŵöŕķš åš îñţéñðéð one tw]'; + String get pubFieldBio => '[Åûţĥöŕ ƀîö one]'; @override - String get boardDeclineWontFix => '[Ŵöñ\'ţ ƒîẋ one]'; + String get pubFieldNote => '[Ñöţé ţö ţĥé ɱöðéŕåţöŕš one two]'; @override - String boardBlockHint(String name) { - return '[$name çåñ šţîļļ ŕéåð ţĥé ƀöåŕð ƀûţ çåñ\'ţ þöšţ, ṽöţé öŕ çöɱɱéñţ. one two three fou]'; - } + String get pubFieldOff => '[Ñöţ åšķéð one]'; @override - String boardMergeHint(int number) { - return '[Ṽöţéš öñ #$number ɱöṽé ţö ţĥé îššûé ţĥåţ ŕéɱåîñš. one two thre]'; - } + String get pubFieldOptional => '[Öþţîöñåļ one]'; @override - String get boardFieldTargetPost => '[Κšûé ţĥåţ ŕéɱåîñš one tw]'; + String get pubFieldRequired => '[Ŕéǫûîŕéð one]'; @override - String get boardInvalidPostNumber => '[Éñţéŕ åñ îššûé ñûɱƀéŕ one two]'; + String get pubEnabled => '[Åççéþţ ñéŵ šţöŕîéš one tw]'; @override - String get boardMergeSelf => - '[Åñ îššûé çåñ\'ţ ƀé ɱéŕĝéð îñţö îţšéļƒ one two thr]'; + String pubHostVerified(String host) { + return '[$host ✓ o]'; + } @override - String get boardFieldKind => '[Ķîñð on]'; + String pubHostUnverified(String host) { + return '[$host (ñöţ ṽéŕîƒîéð) one t]'; + } @override - String get boardFieldArea => '[Åŕéå on]'; + String get pubDisabled => '[Ñöţ åççéþţîñĝ šţöŕîéš one two]'; @override - String get boardFieldSize => '[Šîžé on]'; + String pubOpenCount(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: '$count šţöŕîéš îñ ŕéṽîéŵ', + one: '1 šţöŕý îñ ŕéṽîéŵ', + zero: 'Ñö šţöŕîéš îñ ŕéṽîéŵ', + ); + return '[$_temp0 one two three fou]'; + } @override - String get boardNoLabel => '[Ñöţ šéţ one]'; + String get pubManage => '[Ṁåñåĝé one]'; @override - String get boardFieldTask => '[Ţåšķ on]'; + String get pubHide => '[Ĥîðé on]'; @override - String get boardLinkPrHint => - '[Å þûļļ ŕéǫûéšţ öƒ ţĥé ŕéþöšîţöŕý. Ļéåṽé îţ éɱþţý ţö ûñļîñķ. one two three four]'; + String get pubContributorLink => + '[Çöñţŕîƀûţöŕ ļîñķ (þûţ îţ ƀéĥîñð “Ŵŕîţé ƒöŕ ûš”) one two three]'; @override - String get boardFieldPrUrl => '[Þûļļ ŕéǫûéšţ ÛŔĻ one t]'; + String get pubId => '[Þûƀļîçåţîöñ îð one t]'; @override - String get boardInvalidPrUrl => - '[Ûšé å ĝîţĥûƀ.çöɱ þûļļ ŕéǫûéšţ ÛŔĻ one two th]'; + String get pubCopy => '[Çöþý on]'; @override - String get boardRemoveScreenshotHint => - '[Ţĥé šçŕééñšĥöţ îš ðéļéţéð ƒöŕ ĝööð. one two thr]'; + String get pubCopied => '[Çöþîéð one]'; @override - String boardPromptEditorTitle(int number) { - return '[Þŕöɱþţ öƒ Ţ-$number one]'; - } + String get pubDelete => '[Ðéļéţé one]'; @override - String get boardPromptEditorHint => - '[Çöñţŕîƀûţöŕš ŕûñ ţĥîš þŕöɱþţ îñ çöðîñĝ åĝéñţš. Ŕéåð îţ åļļ ƀéƒöŕé šåṽîñĝ. one two three four fiv]'; + String get pubModerators => '[Ṁöðéŕåţöŕš one]'; @override - String get boardPromptSavePublishes => - '[Šåṽîñĝ þûƀļîšĥéš ţĥé ţåšķ. one two t]'; + String get pubModeratorsHint => + '[Ṁöðéŕåţöŕš ĝéţ çöɱɱéñţ åççéšš ţö šţöŕîéš ŵĥéñ ţĥéý åŕé šûƀɱîţţéð. Éñţéŕ ţĥé éɱåîļ åððŕéššéš öƒ ţĥéîŕ Ŵöñķý åççöûñţš, öñé þéŕ ļîñé. one two three four five six seven eight]'; @override - String get boardPromptDiffTitle => '[Çĥåñĝéš ƒŕöɱ Ŕéĝéñéŕåţé one two]'; + String get pubModeratorEmails => '[Éɱåîļ åððŕéššéš one t]'; @override - String boardLintTitle(int count) { + String pubModeratorsButton(int count) { String _temp0 = intl.Intl.pluralLogic( count, locale: localeName, - other: '$count ûñûšûåļ îñšţŕûçţîöñš', - one: '1 ûñûšûåļ îñšţŕûçţîöñ', + other: '$count ɱöðéŕåţöŕš…', + one: '1 ɱöðéŕåţöŕ…', + zero: 'Åðð ɱöðéŕåţöŕš…', ); - return '[$_temp0: çĥéçķ ƀéƒöŕé šåṽîñĝ one two three four f]'; + return '[$_temp0 one two three]'; } @override - String boardLintCommand(int line, String text) { - return '[Ļîñé $line: çöɱɱåñð $text one t]'; - } + String get pubVerification => '[Ṽéŕîƒîçåţîöñ one t]'; @override - String boardLintUrl(int line, String text) { - return '[Ļîñé $line: ļîñķ öûţšîðé ţĥé ŕéþöšîţöŕý $text one two thr]'; + String pubVerifyHint(String host) { + return '[Šéŕṽé ţĥîš åţ ĥţţþš://$host/.ŵéļļ-ķñöŵñ/ŵöñķý-þûƀļîçåţîöñš.ĵšöñ, ţĥéñ ṽéŕîƒý. Ûñţîļ ţĥéñ çöñţŕîƀûţöŕš šéé ýöûŕ ŵéƀĥööķ\'š ĥöšţ åñð å ŵåŕñîñĝ. one two three four five six seven eight ni]'; } @override - String boardLintWording(int line, String text) { - return '[Ļîñé $line: “$text” one]'; + String pubVerifiedAt(String host, String date) { + return '[$host ṽéŕîƒîéð $date one]'; } @override - String get boardReviewHeld => '[Ĥéļð on]'; + String get pubVerify => '[Ṽéŕîƒý one]'; @override - String get boardReviewCheck => '[Çĥéçķ on]'; + String pubVerified(String host) { + return '[$host îš ṽéŕîƒîéð one]'; + } @override - String get boardReviewUnchecked => '[Ûñçĥéçķéð one]'; + String get pubVerifyFailed => '[Ñöţ ṽéŕîƒîéð one]'; @override - String get boardReviewDuplicates => '[Þöššîƀļé ðûþļîçåţéš one two]'; + String get pubCredentials => '[Šîĝñîñĝ šéçŕéţ åñð ÅÞÎ ķéý one two]'; @override - String get boardReviewBundles => '[Šûĝĝéšţéð ƀûñðļéš one tw]'; + String get pubSecretHint => + '[Ŵéƀĥööķš åŕé šîĝñéð ŵîţĥ ţĥé šîĝñîñĝ šéçŕéţ. Ýöûŕ šéŕṽéŕ çåļļš ţĥé þûƀļîçåţîöñ ÅÞÎ ŵîţĥ ţĥé ÅÞÎ ķéý. one two three four five six se]'; @override - String get boardReviewDrafts => '[Ðŕåƒţ ţåšķš one]'; + String pubRotationActive(String date) { + return '[Ţĥé þŕéṽîöûš šîĝñîñĝ šéçŕéţ šţîļļ šîĝñš ûñţîļ $date. one two three]'; + } @override - String get boardReviewEmpty => '[Ñöţĥîñĝ ţö ŕéṽîéŵ. one tw]'; + String get pubRotateSecret => '[Ŕöţåţé šîĝñîñĝ šéçŕéţ one two]'; @override - String get cmdBoardVote => '[Ṽöţé on]'; + String get pubRotateSecretBody => + '[Ýöû ĝéţ å ñéŵ šéçŕéţ. Ƒöŕ 24 ĥöûŕš, ŵéƀĥööķš çåŕŕý šîĝñåţûŕéš öƒ ţĥé öļð åñð ţĥé ñéŵ šéçŕéţ. one two three four five six]'; @override - String get cmdBoardCreatePost => '[Ŕéþöŕţ îššûé one]'; + String get pubRotate => '[Ŕöţåţé one]'; @override - String get cmdBoardEditPost => '[Éðîţ îššûé one]'; + String get pubCreateApiKey => '[Çŕéåţé ÅÞÎ ķéý one t]'; @override - String get cmdBoardDeletePost => '[Ðéļéţé îššûé one]'; + String get pubRotateApiKey => '[Ŕöţåţé ÅÞÎ ķéý one t]'; @override - String get cmdBoardRemoveScreenshot => '[Ŕéɱöṽé šçŕééñšĥöţ one tw]'; + String pubRotateApiKeyLast4(String last4) { + return '[Ŕöţåţé ÅÞÎ ķéý (…$last4) one tw]'; + } @override - String get cmdBoardComment => '[Çöɱɱéñţ one]'; + String get pubRotateApiKeyBody => + '[Ţĥé çûŕŕéñţ ķéý šţöþš ŵöŕķîñĝ åţ öñçé. one two thre]'; @override - String get cmdBoardEditComment => '[Éðîţ çöɱɱéñţ one]'; + String get pubApiKey => '[ÅÞÎ ķéý one]'; @override - String get cmdBoardDeleteComment => '[Ðéļéţé çöɱɱéñţ one t]'; + String get pubSigningSecret => '[Šîĝñîñĝ šéçŕéţ one t]'; @override - String get cmdBoardFlag => '[Ƒļåĝ… on]'; + String pubSecretOnce(String what) { + return '[Çöþý ţĥé $what ñöŵ. Îţ îšñ\'ţ šĥöŵñ åĝåîñ. one two thr]'; + } @override - String get cmdBoardClaim => '[Çļåîɱ ţåšķ one]'; + String get pubSecretSaved => '[Î\'ṽé šţöŕéð îţ one t]'; @override - String get cmdBoardRelease => '[Ûñçļåîɱ ţĥîš ţåšķ one tw]'; + String get pubDeliveries => '[Ðéļîṽéŕîéš one]'; @override - String get cmdBoardCopyPrompt => '[Çöþý þŕöɱþţ one]'; + String get pubSendTest => '[Šéñð ţéšţ one]'; @override - String get cmdBoardCopyClaimCode => '[Çöþý çļåîɱ çöðé one t]'; + String get pubTestOk => '[Ýöûŕ ŵéƀĥööķ åççéþţéð ţĥé ţéšţ. one two th]'; @override - String get cmdBoardModerate => '[Ṁöðéŕåţé one]'; + String get pubTestFailed => + '[Ýöûŕ ŵéƀĥööķ ðîðñ\'ţ åççéþţ ţĥé ţéšţ one two thr]'; @override - String get cmdBoardSetLabels => '[Šéţ ķîñð, åŕéå åñð šîžé… one two]'; + String get pubNoDeliveries => '[Ñö ŵéƀĥööķš šéñţ ýéţ. one two]'; @override - String get cmdBoardAdminEdit => '[Éðîţ åš ɱöðéŕåţöŕ… one tw]'; + String pubDelivered(int status_code) { + return '[Ðéļîṽéŕéð (ĤŢŢÞ $status_code) one tw]'; + } @override - String get cmdBoardApplyTitle => '[Åþþļý šûĝĝéšţéð ţîţļé one two]'; + String pubDeliveryFailed(String error) { + return '[Ƒåîļéð: $error one]'; + } @override - String get cmdBoardNotDuplicate => '[Ñöţ å ðûþļîçåţé one t]'; + String get pubDeliveryQueued => '[Ǫûéûéð one]'; @override - String get cmdBoardMerge => '[Ṁéŕĝé îñţö… one]'; + String pubDeliveryRetrying(String error, String date) { + return '[$error · ñéẋţ ţŕý $date one]'; + } @override - String get cmdBoardUnmerge => '[Ûñɱéŕĝé one]'; + String get pubResend => '[Ŕéšéñð one]'; @override - String get cmdBoardDecline => '[Ðéçļîñé one]'; + String pubDeleteTitle(String name) { + return '[Ðéļéţé “$name”? one]'; + } @override - String get cmdBoardReopen => '[Ŕéöþéñ one]'; + String get pubDeleteBody => + '[Çöñţŕîƀûţöŕš\' ðöçûɱéñţš šţåý îñ ţĥéîŕ ðŕîṽéš, ƀûţ ţĥéý çåñ\'ţ šûƀɱîţ ţĥéɱ åñýɱöŕé, åñð ɱöðéŕåţöŕš ļöšé åççéšš. Ýöûŕ ƀļöĝ ĝéţš ñö ŵéƀĥööķ åƀöûţ îţ. one two three four five six seven eight nine]'; @override - String get cmdBoardBlock => '[Ɓļöçķ ûšéŕ ƒŕöɱ ţĥé ƀöåŕð one two]'; + String get notifySubmissions => '[Šţöŕîéš ƒöŕ þûƀļîçåţîöñš one two]'; @override - String get cmdBoardCreateTask => '[Çŕéåţé ţåšķ one]'; + String get notifySubmissionsHint => + '[Šţåţûš çĥåñĝéš åñð ɱéššåĝéš ƒŕöɱ ƀļöĝš ýöû ŵŕîţé ƒöŕ one two three fo]'; @override - String get cmdBoardEditTask => '[Éðîţ ţåšķ one]'; + String notifSubmissionChanges(String publication, String what) { + return '[$publication åšķéð ƒöŕ çĥåñĝéš ţö “$what” one two]'; + } @override - String get cmdBoardSetTaskPosts => '[Çĥåñĝé ţĥé ţåšķ\'š îššûéš one two]'; + String notifSubmissionDeclined(String publication, String what) { + return '[$publication ðéçļîñéð “$what” one]'; + } @override - String get cmdBoardRegeneratePrompt => '[Ŕéĝéñéŕåţé þŕöɱþţ one tw]'; + String notifSubmissionPublished(String publication, String what) { + return '[$publication þûƀļîšĥéð “$what” one]'; + } @override - String get cmdBoardEditPrompt => '[Éðîţ þŕöɱþţ one]'; + String notifSubmissionInReview(String publication, String what) { + return '[$publication îš ŕéṽîéŵîñĝ “$what” one t]'; + } @override - String get cmdBoardPublishTask => '[Þûƀļîšĥ ţåšķ one]'; + String notifSubmissionMessage(String publication, String what) { + return '[$publication šéñţ å ɱéššåĝé åƀöûţ “$what” one two]'; + } @override - String get cmdBoardLinkPr => '[Ļîñķ þûļļ ŕéǫûéšţ… one tw]'; + String notifSubmissionFailed(String publication, String what) { + return '[$publication çöûļðñ\'ţ ŕéçéîṽé “$what” one tw]'; + } @override - String get cmdBoardMarkDone => '[Ṁåŕķ ðöñé one]'; + String shareModerator(String publication) { + return '[Ṁöðéŕåţöŕ · $publication one]'; + } @override - String get cmdBoardMarkShipped => '[Ṁåŕķ šĥîþþéð one]'; + String activitySubmitted(String who, String publication) { + return '[$who šûƀɱîţţéð îţ ţö $publication one t]'; + } @override - String get cmdBoardCancelTask => '[Çåñçéļ ţåšķ one]'; + String activitySubmissionWithdrawn(String who, String publication) { + return '[$who ŵîţĥðŕéŵ îţ ƒŕöɱ $publication one t]'; + } @override - String get cmdBoardSuggestBundles => '[Šûĝĝéšţ ƀûñðļéš one t]'; + String activitySubmissionDisconnected(String who, String publication) { + return '[$who ðîšçöññéçţéð îţ ƒŕöɱ $publication one two]'; + } @override - String get cmdBoardDismissSuggestion => '[Ðîšɱîšš šûĝĝéšţîöñ one tw]'; + String activitySubmissionReconnected(String who, String publication) { + return '[$who çöññéçţéð îţ ţö $publication åĝåîñ one two]'; + } @override - String get notifyBoard => '[Ɓûĝš & îɱþŕöṽéɱéñţš one tw]'; + String activitySubmissionStatus(String publication, String status) { + return '[$publication: $status o]'; + } @override - String get notifyBoardHint => - '[Ŕéþļîéš ţö ýöûŕ îššûéš, šţåţûš çĥåñĝéš åñð ýöûŕ ţåšķ çļåîɱš one two three four]'; + String get submissionStatusDraft => '[Ðŕåƒţ on]'; @override - String boardEventPrClosed(String url) { - return '[Þûļļ ŕéǫûéšţ çļöšéð ŵîţĥöûţ ɱéŕĝé: $url. Ţĥé ţåšķ îš öþéñ åĝåîñ. one two three four]'; - } + String get submissionStatusInReview => '[Îñ ŕéṽîéŵ one]'; @override - String boardEventPrMerged(String url) { - return '[Þûļļ ŕéǫûéšţ ɱéŕĝéð: $url one two]'; - } + String get submissionStatusChangesRequested => '[Çĥåñĝéš ŕéǫûéšţéð one tw]'; @override - String boardEventPrOpened(String url) { - return '[Þûļļ ŕéǫûéšţ öþéñéð: $url one two]'; - } + String get submissionStatusDeclined => '[Ðéçļîñéð one]'; @override - String boardEventDeployed(String sha) { - return '[Šĥîþþéð îñ ðéþļöý $sha one tw]'; - } + String get submissionStatusPublished => '[Þûƀļîšĥéð one]'; @override - String get boardVerdictMet => '[Ṁéţ on]'; + String get submissionStatusWithdrawn => '[Ŵîţĥðŕåŵñ one]'; @override - String get boardVerdictPartly => '[Þåŕţļý one]'; + String pubStartTitle(String name) { + return '[Ŵŕîţé ƒöŕ $name one]'; + } @override - String get boardVerdictNotMet => '[Ñöţ ɱéţ one]'; + String pubStartHostVerified(String host) { + return '[$host ✓ o]'; + } @override - String get boardVerdictCantTell => '[Çåñ\'ţ ţéļļ one]'; + String pubStartHostUnverified(String site, String webhook) { + return '[Ŵöñķý ĥåšñ\'ţ ṽéŕîƒîéð ţĥåţ ţĥîš þûƀļîçåţîöñ ƀéļöñĝš ţö $site. Ýöûŕ šţöŕý îš šéñţ ţö $webhook. one two three four five]'; + } @override - String get boardVerdictAdded => '[Åððéð on]'; + String pubStartConsent(String name) { + return '[Ýöû\'ļļ ŵŕîţé îñ ýöûŕ öŵñ Ŵöñķý ðöçûɱéñţ. Ŵĥéñ ýöû þŕéšš Šûƀɱîţ, $name ŕéçéîṽéš ţĥé ţéẋţ åñð îɱåĝéš öƒ ţĥé ðöçûɱéñţ, ţĥé ƒîéļðš ýöû ƒîļļ îñ åñð ýöûŕ ðîšþļåý ñåɱé, åñð îţš ɱöðéŕåţöŕš çåñ ŕéåð åñð çöɱɱéñţ öñ ţĥé ðöçûɱéñţ. one two three four five six seven eight nine ten one two three]'; + } @override - String get boardVerdictUpdated => '[Ûþðåţéð one]'; + String get pubStartWhich => '[Šţöŕý on]'; @override - String get boardVerdictMissing => '[Ṁîššîñĝ one]'; + String pubStartContinue(String name) { + return '[Çöñţîñûé “$name” one]'; + } @override - String get boardVerdictNotNeeded => '[Ñöţ ñééðéð one]'; + String get pubStartNew => '[Šţåŕţ å ñéŵ šţöŕý one t]'; @override - String get boardReviewTests => '[Ţéšţš on]'; + String pubStartTerms(String name, String url) { + return '[Î åĝŕéé ţö $name\'š çöñţŕîƀûţöŕ ţéŕɱš ($url) one two th]'; + } @override - String get boardReviewSpecs => '[Šþéçš on]'; + String pubStartTermsRequired(String name) { + return '[Åĝŕéé ţö $name\'š çöñţŕîƀûţöŕ ţéŕɱš ţö šţåŕţ. one two thre]'; + } @override - String get boardReviewRisks => '[Ŕîšķš on]'; + String get pubStartButton => '[Šţåŕţ ŵŕîţîñĝ one t]'; @override - String get boardReviewUnrelated => - '[Çĥåñĝéš ţĥé ţåšķ ðîðñ\'ţ åšķ ƒöŕ one two th]'; + String pubStartBlocked(String name) { + return '[$name îšñ\'ţ åççéþţîñĝ šţöŕîéš ƒŕöɱ ýöû. one two thr]'; + } @override - String boardReviewedSha(String sha) { - return '[Ŕéṽîéŵéð åţ $sha one]'; + String pubStartClosed(String name) { + return '[$name îšñ\'ţ åççéþţîñĝ šţöŕîéš ŕîĝĥţ ñöŵ. one two thr]'; } } diff --git a/packages/wonky_app/lib/src/notifications/notifications_button.dart b/packages/wonky_app/lib/src/notifications/notifications_button.dart index 40902955..58d0b89f 100644 --- a/packages/wonky_app/lib/src/notifications/notifications_button.dart +++ b/packages/wonky_app/lib/src/notifications/notifications_button.dart @@ -461,6 +461,25 @@ String notificationText(WonkyAppLocalizations l, NotificationView n) { final String m when m.isNotEmpty => m, _ => l.notifBoardUpdate('${_payload(n)['title'] ?? ''}'), }, + NotificationKind.submission => _submissionText(l, n, what), + }; +} + +/// (M14) A publication's update on a story (specs/18 §5.3). +String _submissionText( + WonkyAppLocalizations l, + NotificationView n, + String what, +) { + final p = _payload(n); + final pub = '${p['publication'] ?? l.someone}'; + return switch ((p['event'], p['status'])) { + ('deliveryFailed', _) => l.notifSubmissionFailed(pub, what), + ('status', 'changesRequested') => l.notifSubmissionChanges(pub, what), + ('status', 'declined') => l.notifSubmissionDeclined(pub, what), + ('status', 'published') => l.notifSubmissionPublished(pub, what), + ('status', 'inReview') => l.notifSubmissionInReview(pub, what), + _ => l.notifSubmissionMessage(pub, what), }; } @@ -496,6 +515,7 @@ IconData _kindIcon(NotificationKind k) => switch (k) { NotificationKind.boardReply => LucideIcons.messageSquareReply, NotificationKind.boardStatus => LucideIcons.bug, NotificationKind.boardClaim => LucideIcons.hand, + NotificationKind.submission => LucideIcons.newspaper, }; /// One notification row: avatar with the kind icon, text, excerpt, time and diff --git a/packages/wonky_app/lib/src/publications/publication_repository.dart b/packages/wonky_app/lib/src/publications/publication_repository.dart new file mode 100644 index 00000000..e94741b8 --- /dev/null +++ b/packages/wonky_app/lib/src/publications/publication_repository.dart @@ -0,0 +1,129 @@ +import 'package:wonky_client/wonky_client.dart'; + +import '../data/api.dart'; + +/// Publications and submissions (specs/18 §9): starting a story from a +/// contributor link, a document's submission, and the owner's settings. +abstract class PublicationRepository { + // Contributor. + Future resolve(String publicId); + Future startSubmission( + String publicId, { + String? ref, + required bool agreed, + }); + + // A document's submission. + Future submission(UuidValue itemUuid); + Future submit( + UuidValue itemUuid, + SubmissionValues values, { + required bool agreed, + }); + Future withdraw(UuidValue itemUuid); + Future disconnect(UuidValue itemUuid); + Future reconnect(UuidValue itemUuid); + + // Owner. + Future> list(); + Future create(PublicationInput input); + Future update(String publicId, PublicationInput input); + Future delete(String publicId); + Future verify(String publicId); + Future rotateSecret(String publicId); + Future createApiKey(String publicId); + Future setModerators( + String publicId, + List emails, + ); + Future> deliveries(String publicId); + Future resend(String publicId, String webhookId); + Future sendTest(String publicId); +} + +/// [PublicationRepository] on the `publication` and `submission` endpoints. +class ServerPublicationRepository implements PublicationRepository { + ServerPublicationRepository(this.api); + + final Api api; + + @override + Future resolve(String publicId) => + api.guard((c) => c.publication.resolve(publicId)); + + @override + Future startSubmission( + String publicId, { + String? ref, + required bool agreed, + }) => api.guard((c) => c.publication.startSubmission(publicId, ref, agreed)); + + @override + Future submission(UuidValue itemUuid) => + api.guard((c) => c.submission.get(itemUuid)); + + @override + Future submit( + UuidValue itemUuid, + SubmissionValues values, { + required bool agreed, + }) => api.guard((c) => c.submission.submit(itemUuid, values, agreed)); + + @override + Future withdraw(UuidValue itemUuid) => + api.guard((c) => c.submission.withdraw(itemUuid)); + + @override + Future disconnect(UuidValue itemUuid) => + api.guard((c) => c.submission.disconnect(itemUuid)); + + @override + Future reconnect(UuidValue itemUuid) => + api.guard((c) => c.submission.reconnect(itemUuid)); + + @override + Future> list() => + api.guard((c) => c.publication.list()); + + @override + Future create(PublicationInput input) => + api.guard((c) => c.publication.create(input)); + + @override + Future update(String publicId, PublicationInput input) => + api.guard((c) => c.publication.update(publicId, input)); + + @override + Future delete(String publicId) => + api.guard((c) => c.publication.delete(publicId)); + + @override + Future verify(String publicId) => + api.guard((c) => c.publication.verify(publicId)); + + @override + Future rotateSecret(String publicId) => + api.guard((c) => c.publication.rotateSecret(publicId)); + + @override + Future createApiKey(String publicId) => + api.guard((c) => c.publication.createApiKey(publicId)); + + @override + Future setModerators( + String publicId, + List emails, + ) => api.guard((c) => c.publication.setModerators(publicId, emails)); + + @override + Future> deliveries(String publicId) => + api.guard((c) => c.publication.deliveries(publicId)); + + @override + Future resend(String publicId, String webhookId) => + api.guard((c) => c.publication.resend(publicId, webhookId)); + + @override + Future sendTest(String publicId) => + api.guard((c) => c.publication.sendTest(publicId)); +} diff --git a/packages/wonky_app/lib/src/publications/publications_section.dart b/packages/wonky_app/lib/src/publications/publications_section.dart new file mode 100644 index 00000000..005fcda9 --- /dev/null +++ b/packages/wonky_app/lib/src/publications/publications_section.dart @@ -0,0 +1,753 @@ +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:intl/intl.dart' as intl; +import 'package:shad/shad.dart'; +import 'package:wonky_client/wonky_client.dart'; + +import '../bootstrap/app_urls.dart'; +import '../data/api.dart'; +import '../l10n/wonky_app_localizations.dart'; +import '../settings/settings_screen.dart'; +import '../shell/dialogs.dart'; +import '../shell/form_dialog.dart'; +import '../shell/shell_services.dart'; +import 'publication_repository.dart'; + +/// The developer guide for blog owners (specs/18 §12 PUB-7). +const publicationGuideUrl = + 'https://github.com/serverpod/wonky/blob/main/docs/blog-integration.md'; + +/// Wonky Work settings › Publications (specs/18 §8.1): the user's +/// publications, their credentials, moderators, verification and webhook +/// deliveries. +class PublicationsSection extends StatefulWidget { + const PublicationsSection({super.key, required this.services}); + + final ShellServices services; + + @override + State createState() => _PublicationsSectionState(); +} + +class _PublicationsSectionState extends State { + List? _list; + Object? _loadError; + + /// The secret shown once: (publicId, label, value). + (String, String, String)? _secret; + + /// The publication whose details are open. + String? _open; + List? _deliveries; + + ShellServices get s => widget.services; + PublicationRepository get repo => s.repositories.publications; + + @override + void initState() { + super.initState(); + _reload(); + } + + Future _reload() async { + try { + final list = await repo.list(); + if (mounted) { + setState(() { + _list = list; + _loadError = null; + }); + } + } catch (e) { + if (mounted) setState(() => _loadError = e); + } + } + + void _replace(PublicationSettings p) => setState(() { + _list = [ + for (final x in _list ?? const []) + x.publicId == p.publicId ? p : x, + ]; + }); + + Future _guard(Future Function() run) async { + try { + return await run(); + } catch (e) { + if (mounted) { + final l = WonkyAppLocalizations.of(context); + s.toasts.error(l.errorGeneric, description: errorMessage(e)); + } + return null; + } + } + + void _copy(String text) { + Clipboard.setData(ClipboardData(text: text)); + s.toasts.show(WonkyAppLocalizations.of(context).pubCopied); + } + + // ------------------------------------------------------------ editing + + Future _edit([PublicationSettings? p]) async { + final l = WonkyAppLocalizations.of(context); + final f = p?.fields; + String? required(String v) => v.trim().isEmpty ? l.pubRequired : null; + String? https(String v) { + final t = v.trim(); + if (t.isEmpty) return null; + return t.startsWith('https://') ? null : l.pubHttpsOnly; + } + + Map modes() => { + 'off': l.pubFieldOff, + 'optional': l.pubFieldOptional, + 'required': l.pubFieldRequired, + }; + final r = await showWonkyFormDialog( + context, + WonkyDialogSpec( + title: p == null ? l.pubNew : l.pubEdit(p.name), + description: p == null ? l.pubNewHint : null, + dialogKey: 'dialog.publication', + width: 520, + fields: [ + TextFieldSpec( + id: 'name', + label: l.pubName, + initial: p?.name ?? '', + maxLength: 60, + validator: required, + ), + TextFieldSpec( + id: 'siteUrl', + label: l.pubSiteUrl, + placeholder: 'https://blog.example.com', + initial: p?.siteUrl ?? '', + validator: (v) => required(v) ?? https(v), + ), + TextFieldSpec( + id: 'webhookUrl', + label: l.pubWebhookUrl, + placeholder: 'https://blog.example.com/api/wonky/webhook', + initial: p?.webhookUrl ?? '', + validator: (v) => required(v) ?? https(v), + ), + TextFieldSpec( + id: 'termsUrl', + label: l.pubTermsUrl, + initial: p?.termsUrl ?? '', + validator: https, + ), + TextFieldSpec( + id: 'template', + label: l.pubTemplate, + placeholder: l.pubTemplateHint, + initial: p?.templateItemUuid == null + ? '' + : '${s.urls.apps[WonkyAppKind.write]}d/${p!.templateItemUuid!.uuid}', + validator: (v) => v.trim().isEmpty || _uuidIn(v) != null + ? null + : l.pubTemplateInvalid, + ), + SelectFieldSpec( + id: 'summary', + label: l.pubFieldSummary, + options: modes(), + initial: (f?.summary ?? PublicationFieldMode.optional).name, + ), + SelectFieldSpec( + id: 'tags', + label: l.pubFieldTags, + options: modes(), + initial: (f?.tags ?? PublicationFieldMode.optional).name, + ), + TextFieldSpec( + id: 'allowedTags', + label: l.pubAllowedTags, + placeholder: l.pubAllowedTagsHint, + initial: f?.allowedTags.join(', ') ?? '', + ), + SelectFieldSpec( + id: 'coverImage', + label: l.pubFieldCover, + options: modes(), + initial: (f?.coverImage ?? PublicationFieldMode.off).name, + ), + SelectFieldSpec( + id: 'authorBio', + label: l.pubFieldBio, + options: modes(), + initial: (f?.authorBio ?? PublicationFieldMode.off).name, + ), + SelectFieldSpec( + id: 'note', + label: l.pubFieldNote, + options: modes(), + initial: (f?.note ?? PublicationFieldMode.optional).name, + ), + CheckboxFieldSpec( + id: 'enabled', + label: l.pubEnabled, + initial: p?.enabled ?? true, + ), + ], + buttons: [ + DialogButtonSpec( + id: 'cancel', + label: l.actionCancel, + validates: false, + ), + DialogButtonSpec( + id: 'save', + label: p == null ? l.actionCreate : l.actionSave, + primary: true, + ), + ], + ), + ); + if (r == null || r.buttonId != 'save' || !mounted) return; + PublicationFieldMode mode(String id) => + PublicationFieldMode.values.asNameMap()[r.text(id)] ?? + PublicationFieldMode.off; + final input = PublicationInput( + name: r.text('name').trim(), + siteUrl: r.text('siteUrl').trim(), + webhookUrl: r.text('webhookUrl').trim(), + termsUrl: r.text('termsUrl').trim().isEmpty + ? null + : r.text('termsUrl').trim(), + templateItemUuid: _uuidIn(r.text('template')), + fields: PublicationFields( + summary: mode('summary'), + tags: mode('tags'), + allowedTags: [ + for (final t in r.text('allowedTags').split(',')) + if (t.trim().isNotEmpty) t.trim(), + ], + coverImage: mode('coverImage'), + authorBio: mode('authorBio'), + note: mode('note'), + ), + enabled: r.flag('enabled'), + ); + if (p == null) { + final created = await _guard(() => repo.create(input)); + if (created == null || !mounted) return; + setState(() { + _list = [...?_list, created.settings]; + _open = created.settings.publicId; + _secret = ( + created.settings.publicId, + l.pubSigningSecret, + created.secret, + ); + _deliveries = null; + }); + await _loadDeliveries(created.settings); + } else { + final updated = await _guard( + () => repo.update(p.publicId, input), + ); + if (updated != null && mounted) _replace(updated); + } + } + + /// The document uuid in a pasted Wonky Write link (or a bare uuid). + static UuidValue? _uuidIn(String text) { + final m = RegExp( + r'[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}', + ).firstMatch(text); + return m == null ? null : UuidValue.fromString(m[0]!.toLowerCase()); + } + + Future _moderators(PublicationSettings p) async { + final l = WonkyAppLocalizations.of(context); + final r = await showWonkyFormDialog( + context, + WonkyDialogSpec( + title: l.pubModerators, + description: l.pubModeratorsHint, + dialogKey: 'dialog.publicationModerators', + width: 480, + fields: [ + TextFieldSpec( + id: 'emails', + label: l.pubModeratorEmails, + multiline: true, + initial: [for (final m in p.moderators) m.email].join('\n'), + ), + ], + buttons: [ + DialogButtonSpec( + id: 'cancel', + label: l.actionCancel, + validates: false, + ), + DialogButtonSpec(id: 'save', label: l.actionSave, primary: true), + ], + ), + ); + if (r == null || r.buttonId != 'save' || !mounted) return; + final emails = [ + for (final e in r.text('emails').split(RegExp(r'[\s,;]+'))) + if (e.trim().isNotEmpty) e.trim(), + ]; + final updated = await _guard( + () => repo.setModerators(p.publicId, emails), + ); + if (updated != null && mounted) _replace(updated); + } + + Future _verify(PublicationSettings p) async { + final l = WonkyAppLocalizations.of(context); + final r = await _guard( + () => repo.verify(p.publicId), + ); + if (r == null || !mounted) return; + _replace(r.settings); + if (r.ok) { + s.toasts.show(l.pubVerified(Uri.parse(p.siteUrl).host)); + } else { + s.toasts.error(l.pubVerifyFailed, description: r.message); + } + } + + Future _sendTest(PublicationSettings p) async { + final l = WonkyAppLocalizations.of(context); + final r = await _guard( + () => repo.sendTest(p.publicId), + ); + if (r == null || !mounted) return; + if (r.ok) { + s.toasts.show(l.pubTestOk); + } else { + s.toasts.error(l.pubTestFailed, description: r.message); + } + await _loadDeliveries(p); + } + + Future _rotateSecret(PublicationSettings p) async { + final l = WonkyAppLocalizations.of(context); + final ok = await confirmDialog( + context, + title: l.pubRotateSecret, + description: l.pubRotateSecretBody, + confirmLabel: l.pubRotate, + ); + if (!ok) return; + final r = await _guard( + () => repo.rotateSecret(p.publicId), + ); + if (r == null || !mounted) return; + _replace(r.settings); + setState(() => _secret = (p.publicId, l.pubSigningSecret, r.secret)); + } + + Future _apiKey(PublicationSettings p) async { + final l = WonkyAppLocalizations.of(context); + if (p.hasApiKey) { + final ok = await confirmDialog( + context, + title: l.pubRotateApiKey, + description: l.pubRotateApiKeyBody, + confirmLabel: l.pubRotate, + destructive: true, + ); + if (!ok) return; + } + final r = await _guard( + () => repo.createApiKey(p.publicId), + ); + if (r == null || !mounted) return; + _replace(r.settings); + setState(() => _secret = (p.publicId, l.pubApiKey, r.secret)); + } + + Future _delete(PublicationSettings p) async { + final l = WonkyAppLocalizations.of(context); + final ok = await confirmDialog( + context, + title: l.pubDeleteTitle(p.name), + description: l.pubDeleteBody, + confirmLabel: l.pubDelete, + destructive: true, + ); + if (!ok) return; + final done = await _guard(() async { + await repo.delete(p.publicId); + return true; + }); + if (done == true && mounted) { + setState(() { + _list = [ + for (final x in _list ?? const []) + if (x.publicId != p.publicId) x, + ]; + _open = null; + }); + } + } + + Future _loadDeliveries(PublicationSettings p) async { + final list = await _guard>( + () => repo.deliveries(p.publicId), + ); + if (list != null && mounted && _open == p.publicId) { + setState(() => _deliveries = list); + } + } + + Future _resend(PublicationSettings p, PublicationDeliveryView d) async { + await _guard( + () => repo.resend(p.publicId, d.webhookId), + ); + await _loadDeliveries(p); + } + + void _toggle(PublicationSettings p) { + setState(() { + _open = _open == p.publicId ? null : p.publicId; + _deliveries = null; + }); + if (_open != null) _loadDeliveries(p); + } + + // -------------------------------------------------------------- views + + String _date(DateTime? d) => + d == null ? '—' : intl.DateFormat.yMMMd().add_Hm().format(d.toLocal()); + + Widget _mono(BuildContext context, String text, {Key? key}) { + final theme = ShadTheme.of(context); + return Container( + key: key, + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + decoration: BoxDecoration( + color: theme.colorScheme.muted, + borderRadius: BorderRadius.circular(6), + ), + child: Text( + text, + style: TextStyle( + fontFamily: 'packages/shad/GeistMono', + fontSize: 12, + color: theme.colorScheme.foreground, + ), + ), + ); + } + + Widget _copyRow(BuildContext context, String label, String value, String id) { + final theme = ShadTheme.of(context); + final l = WonkyAppLocalizations.of(context); + return Padding( + padding: const EdgeInsets.only(bottom: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(label, style: theme.textTheme.small), + const SizedBox(height: 4), + Row( + children: [ + Expanded(child: _mono(context, value)), + const SizedBox(width: 6), + ShadButton.ghost( + key: ValueKey('settings.publications.copy.$id'), + size: ShadButtonSize.sm, + onPressed: () => _copy(value), + child: Text(l.pubCopy), + ), + ], + ), + ], + ), + ); + } + + Widget _row(BuildContext context, PublicationSettings p) { + final theme = ShadTheme.of(context); + final l = WonkyAppLocalizations.of(context); + final host = Uri.parse(p.siteUrl).host; + final open = _open == p.publicId; + return Column( + key: ValueKey('settings.publications.${p.publicId}'), + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.symmetric(vertical: 6), + child: Row( + children: [ + Icon(LucideIcons.newspaper, size: 16), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(p.name, style: theme.textTheme.small), + Text( + [ + p.verifiedHost != null + ? l.pubHostVerified(host) + : l.pubHostUnverified(host), + if (!p.enabled) l.pubDisabled, + l.pubOpenCount(p.openSubmissionCount), + ].join(' · '), + style: theme.textTheme.muted.copyWith(fontSize: 12), + ), + ], + ), + ), + ShadButton.ghost( + key: ValueKey( + 'settings.publications.open.${p.publicId}', + ), + size: ShadButtonSize.sm, + onPressed: () => _toggle(p), + child: Text(open ? l.pubHide : l.pubManage), + ), + ], + ), + ), + if (open) _details(context, p), + ], + ); + } + + Widget _details(BuildContext context, PublicationSettings p) { + final theme = ShadTheme.of(context); + final l = WonkyAppLocalizations.of(context); + final secret = _secret; + final deliveries = _deliveries; + Widget heading(String text) => Padding( + padding: const EdgeInsets.only(top: 14, bottom: 6), + child: Text( + text, + style: theme.textTheme.small.copyWith(fontWeight: FontWeight.w600), + ), + ); + return Container( + padding: const EdgeInsets.fromLTRB(26, 4, 0, 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (secret != null && secret.$1 == p.publicId) + Padding( + padding: const EdgeInsets.only(bottom: 12), + child: ShadAlert( + key: const ValueKey('settings.publications.secret'), + icon: const Icon(LucideIcons.keyRound), + title: Text(l.pubSecretOnce(secret.$2)), + description: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 6), + _mono(context, secret.$3), + const SizedBox(height: 6), + Row( + children: [ + ShadButton.outline( + size: ShadButtonSize.sm, + onPressed: () => _copy(secret.$3), + child: Text(l.pubCopy), + ), + const SizedBox(width: 6), + ShadButton.ghost( + size: ShadButtonSize.sm, + onPressed: () => setState(() => _secret = null), + child: Text(l.pubSecretSaved), + ), + ], + ), + ], + ), + ), + ), + _copyRow(context, l.pubContributorLink, p.contributorLink, 'link'), + _copyRow(context, l.pubId, p.publicId, 'id'), + Wrap( + spacing: 6, + runSpacing: 6, + children: [ + ShadButton.outline( + key: const ValueKey('settings.publications.edit'), + size: ShadButtonSize.sm, + onPressed: () => _edit(p), + child: Text(l.pubEditButton), + ), + ShadButton.outline( + key: const ValueKey('settings.publications.moderators'), + size: ShadButtonSize.sm, + onPressed: () => _moderators(p), + child: Text(l.pubModeratorsButton(p.moderators.length)), + ), + ShadButton.ghost( + key: const ValueKey('settings.publications.delete'), + size: ShadButtonSize.sm, + onPressed: () => _delete(p), + child: Text(l.pubDelete), + ), + ], + ), + heading(l.pubVerification), + Text( + p.verifiedHost != null + ? l.pubVerifiedAt(p.verifiedHost!, _date(p.verifiedAt)) + : l.pubVerifyHint(Uri.parse(p.siteUrl).host), + style: theme.textTheme.muted.copyWith(fontSize: 12), + ), + if (p.verifiedHost == null) ...[ + const SizedBox(height: 6), + _mono(context, '{ "publications": ["${p.publicId}"] }'), + ], + const SizedBox(height: 6), + ShadButton.outline( + key: const ValueKey('settings.publications.verify'), + size: ShadButtonSize.sm, + onPressed: () => _verify(p), + child: Text(l.pubVerify), + ), + heading(l.pubCredentials), + Text( + p.previousSecretUntil != null + ? l.pubRotationActive(_date(p.previousSecretUntil)) + : l.pubSecretHint, + style: theme.textTheme.muted.copyWith(fontSize: 12), + ), + const SizedBox(height: 6), + Wrap( + spacing: 6, + runSpacing: 6, + children: [ + ShadButton.outline( + key: const ValueKey('settings.publications.rotate'), + size: ShadButtonSize.sm, + onPressed: () => _rotateSecret(p), + child: Text(l.pubRotateSecret), + ), + ShadButton.outline( + key: const ValueKey('settings.publications.apiKey'), + size: ShadButtonSize.sm, + onPressed: () => _apiKey(p), + child: Text( + p.hasApiKey + ? l.pubRotateApiKeyLast4(p.apiKeyLast4 ?? '') + : l.pubCreateApiKey, + ), + ), + ], + ), + heading(l.pubDeliveries), + Row( + children: [ + ShadButton.outline( + key: const ValueKey('settings.publications.test'), + size: ShadButtonSize.sm, + onPressed: () => _sendTest(p), + child: Text(l.pubSendTest), + ), + ], + ), + const SizedBox(height: 6), + if (deliveries == null) + const ShadSpinner() + else if (deliveries.isEmpty) + Text(l.pubNoDeliveries, style: theme.textTheme.muted) + else + for (final d in deliveries) _delivery(context, p, d), + ], + ), + ); + } + + Widget _delivery( + BuildContext context, + PublicationSettings p, + PublicationDeliveryView d, + ) { + final theme = ShadTheme.of(context); + final l = WonkyAppLocalizations.of(context); + final state = d.deliveredAt != null + ? l.pubDelivered(d.lastStatus ?? 200) + : d.failedAt != null + ? l.pubDeliveryFailed(d.lastError ?? '') + : d.attempts == 0 + ? l.pubDeliveryQueued + : l.pubDeliveryRetrying(d.lastError ?? '', _date(d.nextAttemptAt)); + return Padding( + key: ValueKey('settings.publications.delivery.${d.webhookId}'), + padding: const EdgeInsets.symmetric(vertical: 4), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + '${d.type} · ${_date(d.createdAt)}', + style: theme.textTheme.small.copyWith(fontSize: 12), + ), + Text( + state, + style: theme.textTheme.muted.copyWith(fontSize: 12), + ), + ], + ), + ), + ShadButton.ghost( + size: ShadButtonSize.sm, + onPressed: () => _resend(p, d), + child: Text(l.pubResend), + ), + ], + ), + ); + } + + @override + Widget build(BuildContext context) { + final l = WonkyAppLocalizations.of(context); + final theme = ShadTheme.of(context); + final list = _list; + return SettingsGroup( + title: l.settingsPublications, + description: l.pubSectionHint, + children: [ + Wrap( + spacing: 6, + runSpacing: 6, + children: [ + ShadButton( + key: const ValueKey('settings.publications.new'), + size: ShadButtonSize.sm, + leading: const Icon(LucideIcons.plus, size: 16), + onPressed: _edit, + child: Text(l.pubNew), + ), + ShadButton.ghost( + key: const ValueKey('settings.publications.guide'), + size: ShadButtonSize.sm, + leading: const Icon(LucideIcons.bookOpen, size: 16), + onPressed: () => s.crossApp.openExternal(publicationGuideUrl), + child: Text(l.pubGuide), + ), + ], + ), + const SizedBox(height: 10), + if (_loadError != null) + Text(errorMessage(_loadError!), style: theme.textTheme.muted) + else if (list == null) + const ShadSpinner() + else if (list.isEmpty) + Text( + l.pubEmpty, + key: const ValueKey('settings.publications.empty'), + style: theme.textTheme.muted, + ) + else + for (final p in list) _row(context, p), + ], + ); + } +} diff --git a/packages/wonky_app/lib/src/publications/start_story.dart b/packages/wonky_app/lib/src/publications/start_story.dart new file mode 100644 index 00000000..de097b51 --- /dev/null +++ b/packages/wonky_app/lib/src/publications/start_story.dart @@ -0,0 +1,95 @@ +import 'package:flutter/widgets.dart'; +import 'package:wonky_client/wonky_client.dart'; + +import '../l10n/wonky_app_localizations.dart'; +import '../shell/form_dialog.dart'; +import '../shell/shell_services.dart'; + +/// The `/new?publication=pub_…` route of Write (specs/18 §3): asks for +/// consent (once per publication, again when what was agreed changed), +/// offers the contributor's open stories, and creates the document of a +/// new one. Returns the document to open, or null when cancelled. +Future startPublicationStory( + BuildContext context, + ShellServices services, + String publicId, { + String? ref, +}) async { + final repo = services.repositories.publications; + final l = WonkyAppLocalizations.of(context); + final card = await repo.resolve(publicId); + if (!context.mounted) return null; + if (card.blocked || !card.enabled) { + await showWonkyFormDialog( + context, + WonkyDialogSpec( + title: card.name, + description: card.blocked + ? l.pubStartBlocked(card.name) + : l.pubStartClosed(card.name), + dialogKey: 'dialog.publicationStart', + alert: true, + buttons: [DialogButtonSpec(id: 'cancel', label: l.actionOk)], + ), + ); + return null; + } + if (!card.consentNeeded && card.openSubmissions.isEmpty) { + final started = await repo.startSubmission( + publicId, + ref: ref, + agreed: false, + ); + return started.itemUuid; + } + final host = card.verified + ? l.pubStartHostVerified(card.shownHost) + : l.pubStartHostUnverified(card.siteHost, card.webhookHost); + final r = await showWonkyFormDialog( + context, + WonkyDialogSpec( + title: l.pubStartTitle(card.name), + description: [ + host, + if (card.consentNeeded) l.pubStartConsent(card.name), + ].join('\n\n'), + dialogKey: 'dialog.publicationStart', + width: 480, + fields: [ + if (card.openSubmissions.isNotEmpty) + SelectFieldSpec( + id: 'story', + label: l.pubStartWhich, + options: { + for (final o in card.openSubmissions) + o.itemUuid.uuid: l.pubStartContinue(o.name), + 'new': l.pubStartNew, + }, + initial: card.openSubmissions.first.itemUuid.uuid, + ), + if (card.consentNeeded && card.termsUrl != null) + CheckboxFieldSpec( + id: 'terms', + label: l.pubStartTerms(card.name, card.termsUrl!), + ), + ], + buttons: [ + DialogButtonSpec(id: 'cancel', label: l.actionCancel, validates: false), + DialogButtonSpec(id: 'start', label: l.pubStartButton, primary: true), + ], + ), + ); + if (r == null || r.buttonId != 'start') return null; + final story = r.values['story'] as String?; + if (story != null && story != 'new') return UuidValue.fromString(story); + if (card.consentNeeded && card.termsUrl != null && !r.flag('terms')) { + services.toasts.error(l.pubStartTermsRequired(card.name)); + return null; + } + final started = await repo.startSubmission( + publicId, + ref: ref, + agreed: card.consentNeeded, + ); + return started.itemUuid; +} diff --git a/packages/wonky_app/lib/src/publications/submission_undo.dart b/packages/wonky_app/lib/src/publications/submission_undo.dart new file mode 100644 index 00000000..f1f167e5 --- /dev/null +++ b/packages/wonky_app/lib/src/publications/submission_undo.dart @@ -0,0 +1,47 @@ +import 'package:wonky_client/wonky_client.dart'; +import 'package:wonky_core/wonky_core.dart' hide ActorKind; + +import '../shell/shell_services.dart'; + +/// Undo of disconnecting a document from its publication (specs/18 §4.4): +/// undo reconnects, redo disconnects again. Submitting and withdrawing +/// reach the blog and are not undoable. +class SubmissionUndoEntry extends UndoEntry { + const SubmissionUndoEntry({required this.itemUuid}); + + final String itemUuid; + + static const domainName = 'publications'; + + @override + String get domain => domainName; + + @override + UndoEntry? rebase(RemoteChange change) => this; +} + +/// Applies [SubmissionUndoEntry]s through the publication repository. +class SubmissionUndoHandler extends UndoHandler { + SubmissionUndoHandler(this.services); + + final ShellServices services; + + @override + String get domain => SubmissionUndoEntry.domainName; + + @override + Future undo(SubmissionUndoEntry e) async { + await services.repositories.publications.reconnect( + UuidValue.fromString(e.itemUuid), + ); + return e; + } + + @override + Future redo(SubmissionUndoEntry e) async { + await services.repositories.publications.disconnect( + UuidValue.fromString(e.itemUuid), + ); + return e; + } +} diff --git a/packages/wonky_app/lib/src/settings/sections/other_sections.dart b/packages/wonky_app/lib/src/settings/sections/other_sections.dart index 954c446a..58515d32 100644 --- a/packages/wonky_app/lib/src/settings/sections/other_sections.dart +++ b/packages/wonky_app/lib/src/settings/sections/other_sections.dart @@ -106,7 +106,8 @@ class NotificationsSection extends StatelessWidget { ? p.notificationSettings['shares'] : null)) as String? ?? - 'inApp'; + // Stories for publications email by default (specs/18 §5.3). + (k == 'submissions' ? 'email' : 'inApp'); Widget choice(String k) => ShadSelect( key: ValueKey('settings.notifications.$k'), initialValue: v(k), @@ -141,6 +142,11 @@ class NotificationsSection extends StatelessWidget { description: l.notifyBoardHint, control: choice('board'), ), + SettingsRow( + label: l.notifySubmissions, + description: l.notifySubmissionsHint, + control: choice('submissions'), + ), SettingsRow( label: l.notifyDigest, description: l.notifyDigestHint, diff --git a/packages/wonky_app/lib/src/settings/settings_catalog.dart b/packages/wonky_app/lib/src/settings/settings_catalog.dart index 8f66b4d9..e685b86a 100644 --- a/packages/wonky_app/lib/src/settings/settings_catalog.dart +++ b/packages/wonky_app/lib/src/settings/settings_catalog.dart @@ -27,6 +27,7 @@ const workSettingsSectionIds = [ 'ai', 'ai-providers', 'developer', + 'publications', 'about', ]; diff --git a/packages/wonky_app/lib/src/settings/settings_screen.dart b/packages/wonky_app/lib/src/settings/settings_screen.dart index f17bbcff..c7df775f 100644 --- a/packages/wonky_app/lib/src/settings/settings_screen.dart +++ b/packages/wonky_app/lib/src/settings/settings_screen.dart @@ -14,6 +14,7 @@ import 'sections/account_section.dart'; import 'sections/appearance_section.dart'; import 'sections/keyboard_section.dart'; import 'sections/other_sections.dart'; +import '../publications/publications_section.dart'; import 'sections/security_section.dart'; import 'sections/storage_section.dart'; import 'settings_catalog.dart'; @@ -132,6 +133,14 @@ class SettingsScreen extends StatelessWidget { LucideIcons.squareTerminal, (_) => DeveloperSection(services: s), ), + // (M14) Blogs that take stories from Wonky Write (specs/18 §8.1). + if (s.repositories.hasPublications) + w( + 'publications', + l.settingsPublications, + LucideIcons.newspaper, + (_) => PublicationsSection(services: s), + ), w( 'about', l.settingsAbout, diff --git a/packages/wonky_app/lib/src/sharing/share_dialog.dart b/packages/wonky_app/lib/src/sharing/share_dialog.dart index 504c9781..e9742733 100644 --- a/packages/wonky_app/lib/src/sharing/share_dialog.dart +++ b/packages/wonky_app/lib/src/sharing/share_dialog.dart @@ -347,6 +347,7 @@ class _ShareDialogState extends State { p.role, invitedEmail: p.user == null ? p.invitedEmail : null, inheritedFrom: p.inheritedFromName, + moderatorOf: p.viaPublication, isMe: p.user?.id == me, editable: canShare && p.inheritedFromUuid == null, ), @@ -583,6 +584,7 @@ class _ShareDialogState extends State { bool editable = false, String? invitedEmail, String? inheritedFrom, + String? moderatorOf, }) { final l = WonkyAppLocalizations.of(context); final theme = ShadTheme.of(context); @@ -593,6 +595,7 @@ class _ShareDialogState extends State { if (user != null) email, if (invitedEmail != null) l.sharePending, if (inheritedFrom != null) l.shareInherited(inheritedFrom), + if (moderatorOf != null) l.shareModerator(moderatorOf), ].join(' · '); Widget trailing; if (isOwnerRow || !editable || isMe) { diff --git a/packages/wonky_app/lib/src/shell/dialogs.dart b/packages/wonky_app/lib/src/shell/dialogs.dart index aec3bda6..996b7b47 100644 --- a/packages/wonky_app/lib/src/shell/dialogs.dart +++ b/packages/wonky_app/lib/src/shell/dialogs.dart @@ -213,9 +213,54 @@ String activityText(WonkyAppLocalizations l, ActivityEventView e) { ActivityType.restored => l.activityRestored(who), ActivityType.exported => l.activityExported(who), ActivityType.uploaded => l.activityUploaded(who), + ActivityType.submission => _submissionActivity(l, e, who), }; } +/// (M14) Submitted to, withdrawn from or disconnected from a publication, +/// or the publication's status change (specs/18 §6). +String _submissionActivity( + WonkyAppLocalizations l, + ActivityEventView e, + String who, +) { + Map m; + try { + final v = jsonDecode(e.summary); + m = v is Map ? v.cast() : const {}; + } on FormatException { + m = const {}; + } + final pub = '${m['publication'] ?? ''}'; + return switch (m['action']) { + 'withdrawn' => l.activitySubmissionWithdrawn(who, pub), + 'disconnected' => l.activitySubmissionDisconnected(who, pub), + 'reconnected' => l.activitySubmissionReconnected(who, pub), + 'status' => l.activitySubmissionStatus( + pub, + submissionStatusLabel( + l, + SubmissionStatus.values.asNameMap()['${m['status']}'] ?? + SubmissionStatus.inReview, + ), + ), + _ => l.activitySubmitted(who, pub), + }; +} + +/// The label of a submission status (specs/18 §2.1). +String submissionStatusLabel( + WonkyAppLocalizations l, + SubmissionStatus status, +) => switch (status) { + SubmissionStatus.draft => l.submissionStatusDraft, + SubmissionStatus.inReview => l.submissionStatusInReview, + SubmissionStatus.changesRequested => l.submissionStatusChangesRequested, + SubmissionStatus.declined => l.submissionStatusDeclined, + SubmissionStatus.published => l.submissionStatusPublished, + SubmissionStatus.withdrawn => l.submissionStatusWithdrawn, +}; + /// The detail line of an edit event (Slides 09 §5): "3 slides · 1 slide /// deleted · theme changed · with Claude", from the counters and sets of /// its summary; null when there is nothing to add (documents, diff --git a/packages/wonky_app/lib/src/shell/shell_services.dart b/packages/wonky_app/lib/src/shell/shell_services.dart index 47305586..1a466f72 100644 --- a/packages/wonky_app/lib/src/shell/shell_services.dart +++ b/packages/wonky_app/lib/src/shell/shell_services.dart @@ -35,6 +35,8 @@ import '../mcp_bridge/mcp_control.dart'; import '../storage/storage_controller.dart'; import '../storage/quota_error_presenter.dart'; import '../board/board_repository.dart'; +import '../publications/publication_repository.dart'; +import '../publications/submission_undo.dart'; import '../storage/storage_checks.dart'; import '../menus/shell_menus.dart'; import '../undo/drive_undo.dart'; @@ -68,8 +70,10 @@ class ShellRepositories { required this.meta, ActivityRepository? activity, BoardRepository? board, + PublicationRepository? publications, }) : _activity = activity, // ignore: prefer_initializing_formals - _board = board; // ignore: prefer_initializing_formals + _board = board, // ignore: prefer_initializing_formals + _publications = publications; // ignore: prefer_initializing_formals final DriveRepository drive; final UserRepository users; @@ -82,6 +86,16 @@ class ShellRepositories { final MetaRepository meta; final ActivityRepository? _activity; final BoardRepository? _board; + final PublicationRepository? _publications; + + /// Publications and submissions (specs/18); throws when the shell was + /// built without one. + PublicationRepository get publications => + _publications ?? + (throw StateError('No PublicationRepository installed.')); + + /// Whether [publications] is available. + bool get hasPublications => _publications != null; /// Bugs & improvements (specs/16); throws when the shell was built /// without one. @@ -130,6 +144,9 @@ class ShellServices implements ActiveDocumentHost { ); undo.registerHandler(DriveUndoHandler(repositories.drive)); undo.registerHandler(CommentsUndoHandler(this)); + if (repositories.hasPublications) { + undo.registerHandler(SubmissionUndoHandler(this)); + } undo.registerHandler(VersionsUndoHandler(this)); quotaErrors.attach(); } diff --git a/packages/wonky_app/lib/src/shell/wonky_shell.dart b/packages/wonky_app/lib/src/shell/wonky_shell.dart index d41cf7ac..3a37ab36 100644 --- a/packages/wonky_app/lib/src/shell/wonky_shell.dart +++ b/packages/wonky_app/lib/src/shell/wonky_shell.dart @@ -32,6 +32,7 @@ import '../mcp_bridge/mcp_bridge_scope.dart'; import '../routing/router.dart'; import '../storage/live_storage_controller.dart'; import '../board/board_repository.dart'; +import '../publications/publication_repository.dart'; import 'overlays/shell_overlays.dart'; import 'shell_services.dart'; import '../undo/undo_service.dart'; @@ -141,6 +142,7 @@ class WonkyShell extends StatefulWidget { meta: ServerMetaRepository(api), activity: ServerActivityRepository(api), board: ServerBoardRepository(api), + publications: ServerPublicationRepository(api), ), urls: wc.urls, connectivity: connectivity, diff --git a/packages/wonky_app/lib/src/testing/command_test_harness.dart b/packages/wonky_app/lib/src/testing/command_test_harness.dart index b5195b36..81716ee5 100644 --- a/packages/wonky_app/lib/src/testing/command_test_harness.dart +++ b/packages/wonky_app/lib/src/testing/command_test_harness.dart @@ -25,6 +25,8 @@ import '../spellcheck/shell_spelling.dart'; import '../storage/storage_controller.dart'; import '../undo/undo_service.dart'; import '../board/board_repository.dart'; +import '../publications/publication_repository.dart'; +import 'fake_publication_repository.dart'; import 'fake_cross_app.dart'; import 'fake_repositories.dart'; @@ -106,6 +108,7 @@ class CommandTestHarness { MetaRepository? meta, ActivityRepository? activity, BoardRepository? board, + PublicationRepository? publications, LocalStore? store, UuidV7Generator? ids, StorageController? storage, @@ -140,6 +143,7 @@ class CommandTestHarness { meta: meta ?? UnfakedMetaRepository(), activity: activity, board: board, + publications: publications ?? FakePublicationRepository(), ), urls: urls, crossApp: crossApp ?? FakeCrossApp(urls), diff --git a/packages/wonky_app/lib/src/testing/fake_publication_repository.dart b/packages/wonky_app/lib/src/testing/fake_publication_repository.dart new file mode 100644 index 00000000..e180aa12 --- /dev/null +++ b/packages/wonky_app/lib/src/testing/fake_publication_repository.dart @@ -0,0 +1,221 @@ +import 'package:wonky_client/wonky_client.dart'; + +import '../publications/publication_repository.dart'; + +/// An in-memory [PublicationRepository] (suite 15 §5): one contributor +/// card, document submissions by item, and the owner's publications. Calls +/// are recorded in [calls]. +class FakePublicationRepository implements PublicationRepository { + FakePublicationRepository({this.card}); + + /// What [resolve] answers. + PublicationCard? card; + + /// Submissions by document. + final submissions = {}; + + /// The owner's publications. + final publications = []; + + /// What [startSubmission] creates. + UuidValue startedItem = UuidValue.fromString( + '01900000-0000-7000-8000-0000000000aa', + ); + + /// The calls made, e.g. `submit`, `startSubmission:agreed`. + final calls = []; + + /// The values of the last [submit]. + SubmissionValues? lastValues; + + static PublicationFields fields() => PublicationFields( + summary: PublicationFieldMode.optional, + tags: PublicationFieldMode.optional, + allowedTags: [], + coverImage: PublicationFieldMode.off, + authorBio: PublicationFieldMode.off, + note: PublicationFieldMode.optional, + ); + + /// A submission view with defaults. + static SubmissionView view( + UuidValue itemUuid, { + SubmissionStatus status = SubmissionStatus.draft, + String name = 'Serverpod blog', + bool accepting = true, + int? lastSubmittedRevision, + String? lastMessage, + String? publicUrl, + UuidValue? feedbackThreadUuid, + SubmissionDeliveryState? delivery, + }) => SubmissionView( + id: 'sub_${itemUuid.uuid}', + itemUuid: itemUuid, + status: status, + delivery: delivery, + publicationId: 'pub_AAAAAAAAAAAAAAAAAAAAAA', + publicationName: name, + shownHost: 'blog.example.com', + verified: true, + accepting: accepting, + fields: fields(), + consentNeeded: false, + values: SubmissionValues(title: 'Untitled story', tags: []), + publicUrl: publicUrl, + feedbackThreadUuid: feedbackThreadUuid, + lastMessage: lastMessage, + lastSubmittedRevision: lastSubmittedRevision, + revisions: [], + updatedAt: DateTime.utc(2026, 10, 20), + ); + + @override + Future resolve(String publicId) async { + calls.add('resolve'); + return card!; + } + + @override + Future startSubmission( + String publicId, { + String? ref, + required bool agreed, + }) async { + calls.add(agreed ? 'startSubmission:agreed' : 'startSubmission'); + submissions[startedItem] = view(startedItem); + return SubmissionStarted(itemUuid: startedItem); + } + + @override + Future submission(UuidValue itemUuid) async => + submissions[itemUuid]; + + @override + Future submit( + UuidValue itemUuid, + SubmissionValues values, { + required bool agreed, + }) async { + calls.add('submit'); + lastValues = values; + final v = submissions[itemUuid]!.copyWith( + status: SubmissionStatus.inReview, + values: values, + lastSubmittedRevision: 1 << 30, + ); + return submissions[itemUuid] = v; + } + + @override + Future withdraw(UuidValue itemUuid) async { + calls.add('withdraw'); + return submissions[itemUuid] = submissions[itemUuid]!.copyWith( + status: SubmissionStatus.withdrawn, + ); + } + + final _disconnected = {}; + + @override + Future disconnect(UuidValue itemUuid) async { + calls.add('disconnect'); + _disconnected[itemUuid] = submissions.remove(itemUuid)!; + } + + @override + Future reconnect(UuidValue itemUuid) async { + calls.add('reconnect'); + final v = _disconnected.remove(itemUuid); + if (v != null) submissions[itemUuid] = v; + return v; + } + + PublicationSettings _settings(PublicationInput input, String id) => + PublicationSettings( + publicId: id, + name: input.name, + siteUrl: input.siteUrl, + webhookUrl: input.webhookUrl, + termsUrl: input.termsUrl, + fields: input.fields, + moderators: [], + hasApiKey: false, + enabled: input.enabled, + contributorLink: 'https://wonky.work/write/new?publication=$id', + openSubmissionCount: 0, + createdAt: DateTime.utc(2026, 10, 20), + ); + + @override + Future> list() async => [...publications]; + + @override + Future create(PublicationInput input) async { + calls.add('create'); + final p = _settings(input, 'pub_${'B' * 22}'); + publications.add(p); + return PublicationSecret(settings: p, secret: 'whsec_c2VjcmV0'); + } + + @override + Future update( + String publicId, + PublicationInput input, + ) async { + calls.add('update'); + final p = _settings(input, publicId); + publications[publications.indexWhere((x) => x.publicId == publicId)] = p; + return p; + } + + @override + Future delete(String publicId) async { + calls.add('delete'); + publications.removeWhere((p) => p.publicId == publicId); + } + + PublicationSettings _one(String id) => + publications.firstWhere((p) => p.publicId == id); + + @override + Future verify(String publicId) async => + PublicationCheckResult( + ok: false, + message: 'HTTP 404', + settings: _one(publicId), + ); + + @override + Future rotateSecret(String publicId) async => + PublicationSecret(settings: _one(publicId), secret: 'whsec_bmV3'); + + @override + Future createApiKey(String publicId) async { + calls.add('createApiKey'); + return PublicationSecret( + settings: _one(publicId).copyWith(hasApiKey: true, apiKeyLast4: 'abcd'), + secret: 'wpk_${'k' * 40}', + ); + } + + @override + Future setModerators( + String publicId, + List emails, + ) async => _one(publicId).copyWith( + moderators: [for (final e in emails) PublicationModeratorView(email: e)], + ); + + @override + Future> deliveries(String publicId) async => []; + + @override + Future resend( + String publicId, + String webhookId, + ) async => throw UnimplementedError(); + + @override + Future sendTest(String publicId) async => + PublicationCheckResult(ok: true, settings: _one(publicId)); +} diff --git a/packages/wonky_app/lib/testing.dart b/packages/wonky_app/lib/testing.dart index f7d36b2a..d4bf3e98 100644 --- a/packages/wonky_app/lib/testing.dart +++ b/packages/wonky_app/lib/testing.dart @@ -17,6 +17,7 @@ export 'src/testing/command_sweep.dart'; export 'src/testing/command_test_harness.dart'; export 'src/testing/fake_board_repository.dart'; export 'src/testing/fake_cross_app.dart'; +export 'src/testing/fake_publication_repository.dart'; export 'src/testing/fake_storage.dart'; export 'src/testing/fake_repositories.dart' hide diff --git a/packages/wonky_app/lib/wonky_app.dart b/packages/wonky_app/lib/wonky_app.dart index 28607a54..79f964ea 100644 --- a/packages/wonky_app/lib/wonky_app.dart +++ b/packages/wonky_app/lib/wonky_app.dart @@ -53,6 +53,10 @@ export 'src/core/toasts.dart'; export 'src/board/board_commands.dart'; export 'src/board/board_hub.dart'; export 'src/board/board_repository.dart'; +export 'src/publications/publication_repository.dart'; +export 'src/publications/publications_section.dart'; +export 'src/publications/start_story.dart'; +export 'src/publications/submission_undo.dart'; export 'src/board/board_undo.dart'; export 'src/board/pages/board_page.dart' show BoardPage; export 'src/board/pages/board_routes.dart'; diff --git a/packages/wonky_app/test/publications/publications_section_test.dart b/packages/wonky_app/test/publications/publications_section_test.dart new file mode 100644 index 00000000..f1ef6a2f --- /dev/null +++ b/packages/wonky_app/test/publications/publications_section_test.dart @@ -0,0 +1,124 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:wonky_app/testing.dart'; +import 'package:wonky_app/wonky_app.dart'; +import 'package:wonky_client/wonky_client.dart'; + +import '../support/screen_pump.dart'; + +Finder _key(String k) => find.byKey(ValueKey(k)); + +void main() { + late CommandTestHarness h; + late FakePublicationRepository repo; + + setUp(() { + repo = FakePublicationRepository(); + h = CommandTestHarness(publications: repo); + }); + tearDown(() => h.dispose()); + + Future pump(WidgetTester tester, Brightness b) => pumpScreen( + tester, + h, + SingleChildScrollView(child: PublicationsSection(services: h.services)), + brightness: b, + ); + + for (final b in Brightness.values) { + group('Given no publications (${b.name})', () { + testWidgets('then the empty state shows', (tester) async { + await pump(tester, b); + + expect(_key('settings.publications.empty'), findsOneWidget); + }); + + testWidgets('when creating one then the signing secret is shown once ' + 'with the contributor link', (tester) async { + await pump(tester, b); + + await tester.tap(_key('settings.publications.new')); + await tester.pumpAndSettle(); + await tester.enterText(_key('dialog.publication.name'), 'My blog'); + await tester.enterText( + _key('dialog.publication.siteUrl'), + 'https://blog.example.com', + ); + await tester.enterText( + _key('dialog.publication.webhookUrl'), + 'https://blog.example.com/hook', + ); + await tester.tap(_key('dialog.publication.save')); + await tester.pumpAndSettle(); + + expect(repo.calls, contains('create')); + expect(_key('settings.publications.secret'), findsOneWidget); + expect(find.text('whsec_c2VjcmV0'), findsOneWidget); + expect( + find.text('https://wonky.work/write/new?publication=pub_${'B' * 22}'), + findsOneWidget, + ); + await tester.tap(find.text("I've stored it")); + await tester.pumpAndSettle(); + expect(find.text('whsec_c2VjcmV0'), findsNothing); + }); + + testWidgets('when the webhook is not https then it is refused', ( + tester, + ) async { + await pump(tester, b); + + await tester.tap(_key('settings.publications.new')); + await tester.pumpAndSettle(); + await tester.enterText(_key('dialog.publication.name'), 'My blog'); + await tester.enterText( + _key('dialog.publication.siteUrl'), + 'https://blog.example.com', + ); + await tester.enterText( + _key('dialog.publication.webhookUrl'), + 'http://blog.example.com/hook', + ); + await tester.tap(_key('dialog.publication.save')); + await tester.pumpAndSettle(); + + expect(repo.calls, isNot(contains('create'))); + expect(find.text('Use an https:// address.'), findsOneWidget); + }); + }); + } + + group('Given a publication', () { + setUp(() { + repo.publications.add( + PublicationSettings( + publicId: 'pub_${'C' * 22}', + name: 'Serverpod blog', + siteUrl: 'https://blog.example.com', + webhookUrl: 'https://blog.example.com/hook', + fields: FakePublicationRepository.fields(), + moderators: [], + hasApiKey: false, + enabled: true, + contributorLink: 'https://wonky.work/write/new?publication=x', + openSubmissionCount: 2, + createdAt: DateTime.utc(2026, 10, 20), + ), + ); + }); + + testWidgets('when managing it and creating an API key then the key is ' + 'shown once', (tester) async { + await pump(tester, Brightness.light); + + expect(find.textContaining('2 stories in review'), findsOneWidget); + await tester.tap(_key('settings.publications.open.pub_${'C' * 22}')); + await tester.pumpAndSettle(); + await tester.tap(_key('settings.publications.apiKey')); + await tester.pumpAndSettle(); + + expect(repo.calls, contains('createApiKey')); + expect(find.text('wpk_${'k' * 40}'), findsOneWidget); + }); + }); +} diff --git a/packages/wonky_app/test/publications/start_story_test.dart b/packages/wonky_app/test/publications/start_story_test.dart new file mode 100644 index 00000000..e043acc3 --- /dev/null +++ b/packages/wonky_app/test/publications/start_story_test.dart @@ -0,0 +1,182 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:wonky_app/testing.dart'; +import 'package:wonky_app/wonky_app.dart'; +import 'package:wonky_client/wonky_client.dart'; + +import '../support/screen_pump.dart'; + +Finder _key(String k) => find.byKey(ValueKey(k)); + +/// Runs [startPublicationStory] from a button so it gets a context below +/// the shell. +class _Starter extends StatelessWidget { + const _Starter({required this.onDone}); + + final void Function(UuidValue?) onDone; + + @override + Widget build(BuildContext context) => GestureDetector( + key: const ValueKey('start'), + behavior: HitTestBehavior.opaque, + onTap: () async { + final s = ShellScope.of(context); + onDone( + await startPublicationStory(context, s, 'pub_${'A' * 22}', ref: 'x'), + ); + }, + child: const SizedBox(width: 100, height: 40), + ); +} + +PublicationCard _card({ + bool consentNeeded = true, + String? termsUrl, + List open = const [], + bool blocked = false, + bool verified = true, +}) => PublicationCard( + publicId: 'pub_${'A' * 22}', + name: 'Serverpod blog', + shownHost: verified ? 'blog.example.com' : 'hooks.example.net', + verified: verified, + siteHost: 'blog.example.com', + webhookHost: 'hooks.example.net', + termsUrl: termsUrl, + fields: FakePublicationRepository.fields(), + ownerName: 'Owner', + enabled: true, + consentNeeded: consentNeeded, + blocked: blocked, + openSubmissions: open, +); + +void main() { + late CommandTestHarness h; + late FakePublicationRepository repo; + UuidValue? result; + var done = false; + + Future start(WidgetTester tester) async { + done = false; + await pumpScreen( + tester, + h, + _Starter( + onDone: (u) { + result = u; + done = true; + }, + ), + ); + await tester.tap(_key('start')); + await tester.pumpAndSettle(); + } + + setUp(() { + repo = FakePublicationRepository(); + h = CommandTestHarness(publications: repo); + }); + tearDown(() => h.dispose()); + + group('Given a contributor link of a verified publication', () { + testWidgets('when consent is needed then the dialog explains what is ' + 'shared and starting creates the story with consent', (tester) async { + repo.card = _card(); + await start(tester); + + expect(find.textContaining('Serverpod blog receives'), findsOneWidget); + expect(find.textContaining('blog.example.com ✓'), findsOneWidget); + await tester.tap(find.text('Start writing')); + await tester.pumpAndSettle(); + + expect(done, isTrue); + expect(result, repo.startedItem); + expect(repo.calls, contains('startSubmission:agreed')); + }); + + testWidgets('when consent was given and nothing is open then the story ' + 'starts without a dialog', (tester) async { + repo.card = _card(consentNeeded: false); + await start(tester); + + expect(_key('dialog.publicationStart'), findsNothing); + expect(result, repo.startedItem); + expect(repo.calls, contains('startSubmission')); + }); + + testWidgets('when there are terms and they are not agreed to then ' + 'nothing starts', (tester) async { + repo.card = _card(termsUrl: 'https://blog.example.com/terms'); + await start(tester); + + await tester.tap(find.text('Start writing')); + await tester.pumpAndSettle(); + + expect(result, isNull); + expect(repo.calls, isNot(contains('startSubmission:agreed'))); + }); + + testWidgets('when a draft is open then it is offered and continuing ' + 'opens it without creating', (tester) async { + final draft = UuidValue.fromString( + '01900000-0000-7000-8000-0000000000d1', + ); + repo.card = _card( + consentNeeded: false, + open: [ + PublicationOpenSubmission( + itemUuid: draft, + name: 'My draft', + status: SubmissionStatus.draft, + updatedAt: DateTime.utc(2026, 10, 19), + ), + ], + ); + await start(tester); + + await tester.tap(find.text('Start writing')); + await tester.pumpAndSettle(); + + expect(result, draft); + expect(repo.calls, isNot(contains('startSubmission'))); + }); + }); + + group('Given an unverified publication', () { + testWidgets('then the dialog names the webhook host', (tester) async { + repo.card = _card(verified: false); + await start(tester); + + expect(find.textContaining('hooks.example.net'), findsOneWidget); + expect(find.textContaining('hasn\'t verified'), findsOneWidget); + }); + }); + + group('Given a publication that blocked the contributor', () { + testWidgets('then it says so and nothing starts', (tester) async { + repo.card = _card(blocked: true); + await start(tester); + + expect( + find.textContaining('isn\'t accepting stories from you'), + findsOneWidget, + ); + await tester.tap(find.text('OK')); + await tester.pumpAndSettle(); + expect(result, isNull); + expect(repo.calls, ['resolve']); + }); + }); + + test('when a /new query has a publication then the request carries it', () { + final r = NewItemRequest.fromQuery({ + 'publication': 'pub_${'A' * 22}', + 'ref': 'cfp', + }); + + expect(r.publicationId, 'pub_${'A' * 22}'); + expect(r.ref, 'cfp'); + expect(r.path, '/new?publication=pub_${'A' * 22}&ref=cfp'); + }); +} diff --git a/specs/03-app-shell-and-navigation.md b/specs/03-app-shell-and-navigation.md index 9e2a2a95..84247cae 100644 --- a/specs/03-app-shell-and-navigation.md +++ b/specs/03-app-shell-and-navigation.md @@ -65,7 +65,7 @@ exception and must reuse the presentation-session state model. | `/shared`, `/starred`, `/recent`, `/offline` (app homes), `/trash` | Drive views | | `/search?q=…` | Search results | | `/templates` | Template gallery | -| `/new?folder=&template=` (Write, Sheets, Slides; v2) | Creates an item of the app's kind (offline-first where supported) and replaces the route with its editor; used by Drive's *New* menu and *From template* | +| `/new?folder=&template=` (Write, Sheets, Slides; v2) | Creates an item of the app's kind (offline-first where supported) and replaces the route with its editor; used by Drive's *New* menu and *From template*. (M14) Write: `/new?publication=pub_…&ref=` starts a story for a publication (online; consent dialog; [18 §3](18-publications-and-submissions.md)) | | `/import?file=` (Write, Sheets; v2) | Imports an uploaded Drive file with the app's import dialog (Drive 02 §7.2) | | `/settings/:section` | Wonky Work settings (suite sections, 04 §4) — (v2) | | `/settings/app`, `/settings/app/:section` | The current app's settings (04 §4) — (v2) | diff --git a/specs/06-sharing-and-permissions.md b/specs/06-sharing-and-permissions.md index af441ecc..a258bb9e 100644 --- a/specs/06-sharing-and-permissions.md +++ b/specs/06-sharing-and-permissions.md @@ -47,6 +47,7 @@ fields: grantedById: int grantedAt: DateTime expiresAt: DateTime? # optional expiring access (Editors+ can set for others) + viaPublicationId: int? # (M14) moderator grant of a submission (18 §5.1); removed with it indexes: perm_item_user_idx: { fields: itemId, userId, inheritedFromId, unique: true } perm_user_idx: { fields: userId } @@ -148,6 +149,9 @@ the new owner's storage — checked at request and at acceptance, [Drive 03 §7. Sharing changes are **not undoable**; destructive ones (remove, transfer) confirm. +(M14) Submitting a document to a publication grants its moderators Commenter without a +notification; the dialog shows them as "Moderator · " ([18 §5.1](18-publications-and-submissions.md)). + ## 5. Share dialog (shared UI, `wonky_app`) ``` diff --git a/specs/07-collaboration.md b/specs/07-collaboration.md index 9a7fbee0..2cb906b1 100644 --- a/specs/07-collaboration.md +++ b/specs/07-collaboration.md @@ -96,6 +96,7 @@ fields: threadId: int, relation(parent=comment_thread, onDelete=Cascade) authorId: int authorKind: ActorKind + publicationId: int? # (M14) set on a publication's messages (authorKind: system), 18 §5.2 body: String # Markdown (inline subset: bold, italic, code, links, mentions) mentions: List reactions: String # JSON {emoji: [userId]} @@ -171,6 +172,7 @@ fields: kind: NotificationKind # mention, reply, assigned, shared, accessRequest, suggestion, scriptFailure, # (v2) storage (quota warnings and the one-time v2 notice, Drive 03 §9); # (M12) boardReply, boardStatus, boardClaim (16 §12); + # (M14) submission (18 §5.3); # Slides adds kinds only through Slides 09 itemId: int? payload: String # JSON @@ -191,7 +193,9 @@ fields: wrote or voted on was planned, built, shipped, declined or merged, or my post was held or removed, `boardClaim` claim warnings, expiry and release or PR-closed notices; default in-app + digest email; links `/drive/improvements/p/` and `/t/`, - [16 §12](16-bugs-and-improvements.md)) — plus + [16 §12](16-bugs-and-improvements.md)), (M14) `submissions` (status changes and messages from a + publication on documents I can edit; default in-app + immediate email, + [18 §5.3](18-publications-and-submissions.md)) — plus `digest: bool` (default true). `off` creates no notification. - Email: **mentions and assignments** set to email are sent right away (a `FutureCall` without delay, `NotificationEmailFutureCall`); everything else set to email goes into the **digest diff --git a/specs/08-commands-and-undo.md b/specs/08-commands-and-undo.md index edd7422c..11855dff 100644 --- a/specs/08-commands-and-undo.md +++ b/specs/08-commands-and-undo.md @@ -141,7 +141,7 @@ any), the current selection, the user's role on the document, the `UndoService`, | Area | Undoable | Not undoable (by design) | |------|----------|--------------------------| | Write content | All text/structure/format edits, paste, find-replace-all, AI insertions | — | -| Write metadata | Title rename, theme assignment, theme edits, page setup, document language | Sharing changes | +| Write metadata | Title rename, theme assignment, theme edits, page setup, document language, (M14) disconnecting a submission | Sharing changes, (M14) submitting and withdrawing a submission (sent outside Wonky; 18 §4.4) | | Sheets content | Cell values, formulas, formats, row/col ops, sheet ops, merges, CF/DV rules, filters, sorts, charts, pivots, named ranges, protected ranges | — | | Sheets settings | Spreadsheet settings (locale, recalc, iterative calc), sheet properties (name, color, gridlines, frozen panes) | — | | Slides content (v2) | Slides, groups, elements, text, styles, builds, transitions, themes/masters/layouts, code states, chart links (update/unlink), notes — through `slides.rows` | — | diff --git a/specs/13-security-and-operations.md b/specs/13-security-and-operations.md index 4e57cf23..c4a55fce 100644 --- a/specs/13-security-and-operations.md +++ b/specs/13-security-and-operations.md @@ -26,6 +26,7 @@ | (M12) Prompt injection into triage, task prompts and PR reviews | Jev returns typed answers only; Gemini gets post and PR text as delimited untrusted data and answers through schemas; task prompts need admin review and sit in a fixed template; PR reviews are advisory and the server never runs PR code (16 §10.2, §13.5) | | (M12) Forged GitHub webhooks, claim takeover | HMAC-SHA256 check (`githubWebhookSecret`), delivery dedupe, per-claim codes compared in constant time (16 §13.3, §13.7) | | (M12) Runaway AI spend on the board | Separate daily token budgets for Jev and Gemini, per-PR review limits, per-user rate limits (16 §6.1, §11, §13.5) | +| (M14) Publications: forged contributor links, SSRF through webhook URLs, forged or replayed deliveries, stolen API keys, moderator overreach, submission spam | Links carry only a public publication id and the consent dialog names the verified site host (or the webhook host); outbound calls through the SSRF-safe client; Standard Webhooks signatures with timestamp window and ids; hashed, scoped, rotatable API keys with rate limits; moderators get Commenter only, removed with the submission; per-user limits and blocks ([18 §11](18-publications-and-submissions.md)) | | Session token theft via XSS (web) | Cookie auth: tokens in an httpOnly, `secure`, `SameSite=lax` cookie shared by both apps; `allowedOrigins` restricts credentialed cross-origin calls (01 §2.5) | ## 2. Privacy @@ -47,6 +48,9 @@ deck's ops (cell values before and after, authors) are kept 30 days, then pruned by `revlog.pruneOps`; a slim row (revision, client op id, author, time) stays 365 days for idempotent resends. Purging a file deletes its ops. +- (M14) Submissions send a document's text, images, fields and the submitter's display name to + the publication the user chose, after a consent dialog; publication signing secrets are stored + unencrypted because they must sign ([18 §11](18-publications-and-submissions.md)). - Export of all user data (*Settings › Account › Download your data*: zip of documents as Markdown, spreadsheets as XLSX, comments as JSON) — P1. diff --git a/specs/14-roadmap.md b/specs/14-roadmap.md index e1d8c233..1fe2fd96 100644 --- a/specs/14-roadmap.md +++ b/specs/14-roadmap.md @@ -251,6 +251,17 @@ when the cache can't be opened and before *Clear local data* (15), the `cascaded (P2, 17 part 6 §6), and character-level merge of concurrent text edits in Slides ([Slides 02 §4.5](wonky_slides/02-data-model.md)). +### 2.1c Publications & submissions (M14, built) + +| Milestone | Goal | Exit criteria | +|-----------|------|---------------| +| **M14 · Publications** ([18](18-publications-and-submissions.md), PUB-1…PUB-8) | Blogs register a publication and link to Wonky Write; contributors write and *Submit* to the blog's review queue; moderators comment in the document; the blog's decisions and messages come back as a feedback thread and notifications | J-P1 green against a fake blog receiver; API access matrix and transitions tested; signing vectors and SSRF matrix green; light/dark goldens of the consent dialog, submit dialog, chip and settings section; developer guide verified by building the sample receiver | + +**M14 status** (2026-10-20): built, see [18 §13](18-publications-and-submissions.md). Server +suites (flow, API over HTTP, owner endpoints, rules, the guide's signing vector) and client +suites (start flow, settings section, Write title row, submit, disconnect undo) are green. +Open: J-P1 E2E, goldens, a walkthrough against a live server. + ### 2.2 Executing the plan with parallel agents (v2) The app plans list **work packages** (Drive 05 §4: D-1…D-18; Slides 12 §4: SL-1…SL-45). Each diff --git a/specs/18-publications-and-submissions.md b/specs/18-publications-and-submissions.md new file mode 100644 index 00000000..9749c4c9 --- /dev/null +++ b/specs/18-publications-and-submissions.md @@ -0,0 +1,440 @@ +# 18 · Publications and submissions (M14, built) + +Lets a blog (or any site with an editorial queue) take stories written in Wonky Write. The blog +links to Wonky Write; the contributor writes in a normal Wonky document and presses **Submit**; +the story lands in the blog's review queue, where a moderator approves it, asks for changes or +declines it. Moderators read and comment on the document in Wonky, and their decisions come +back into the document as messages. + +Status: **built** (M14); open items in §13. The developer +guide for blog owners is [`docs/blog-integration.md`](../docs/blog-integration.md). As-built +notes are in §13. + +## 1. Decisions + +| # | Decision | Reason | +|---|----------|--------| +| P1 | The blog registers a **publication** in Wonky once; the contributor link carries only its public id (`/write/new?publication=pub_…`) | The link can't choose where content goes, and holds no secret. A static link works on a static site | +| P2 | No secret ever lives in a link or a document. The signing secret and the API key stay on the server and with the blog | Sharing, copying, exporting, versions, MCP and AI can't leak them | +| P3 | Any editor of the document can submit | The blog's moderators are the gate; the worst a wrong submission does is add an entry to the queue | +| P4 | The action is called **Submit** (not *Publish*) | It goes to review, not live | +| P5 | Wonky pushes each submission to the blog's webhook, signed per [Standard Webhooks](https://www.standardwebhooks.com/); the blog calls Wonky's publication API back with a status and messages | Small amount of code on the blog side; signatures and timestamps make forged or replayed deliveries detectable | +| P6 | Each moderator account gets **Commenter** on a submitted document (06 §1: read, comment, suggest), and loses it when the submission is withdrawn, declined or disconnected | Inline comments and suggestions are the best way to give feedback on writing | +| P7 | The webhook and all outbound calls go through the SSRF-safe client of the URL fetch proxy (13 §1) | The webhook URL is user-supplied | +| P8 | A submit names a version (07 §5) and records the revision; the blog approves the revision it received | Moderators approve exactly what they reviewed; authors and moderators see diffs between submissions in version history | + +## 2. Concepts + +- **Publication**: a registered destination, owned by one Wonky user (the blog owner). It has a + name, a site URL, a webhook URL, moderators, submission fields, an optional template and terms + link, a signing secret and an API key. +- **Submission**: the link between one Write document and one publication. A document has at + most one submission. It starts as a draft when the contributor starts from the link and + becomes *In review* with the first submit. +- **Submitted revision**: one submit of a submission (the first one or a resubmit): document + revision, named version, fields, the images it references. +- **Feedback thread**: one document-level comment thread per submission (Write 08 §1, + `anchorKind: document`) where the publication's messages appear and authors reply. + +### 2.1 Submission status + +``` + draft ──submit──▶ inReview ──(blog)──▶ changesRequested ──resubmit──▶ inReview + ▲ │ ▲ │ + │ │ └──────────────── resubmit (changes) ─────────────┘ + │ ├──(blog)──▶ declined (final; Submit hidden) + │ └──(blog)──▶ published ──submit update──▶ inReview (publicUrl kept) + inReview / changesRequested ──withdraw──▶ withdrawn ──submit──▶ inReview +``` + +`declined` is final for that submission: the contributor can disconnect and start a new one. +Wonky sets `inReview` itself at a submit (the chip shows *Submitting…* until the blog accepts +the webhook; if every retry fails the status goes back, §7.2); every other transition comes +from the blog (§7.3). Withdrawing (moderator access removed) leaves `withdrawn`; submitting +again is allowed. + +## 3. Contributor flow + +1. **The blog** links to `https://wonky.work/write/new?publication=pub_7Hk2…`, optionally with + `&ref=` (≤ 64 chars, `[A-Za-z0-9_-]`, e.g. a call-for-posts id; passed back + in every webhook, never trusted for anything). +2. **Sign in or sign up** if needed: the auth guard keeps the whole route with its query in + `next` (03 §2). Sign-up still creates the welcome items (04 §1.1) but lands on `next`. +3. **`/new` with `publication`** (online only; offline it shows "Starting a story for a + publication needs a connection" with *Try again*): + - `publication.resolve(publicId)` returns the public card (§9.1) and the caller's open + submissions for it (`draft` or `changesRequested`, role ≥ editor). Unknown, disabled or + blocked: an empty state "This link doesn't work anymore" (blocked: " isn't accepting + stories from you") with *Go to Wonky Write*. + - **Consent dialog**, once per user and publication (repeated when the publication's site + host, webhook host or terms URL changes): + ``` + ┌ Write for Serverpod blog ─────────────────────────────────┐ + │ 📰 Serverpod blog · blog.serverpod.dev ✓ │ + │ You'll write in your own Wonky document. When you press │ + │ Submit, Serverpod blog receives: │ + │ • the text and images of the document │ + │ • the fields you fill in and your display name │ + │ and its moderators can read and comment on the document. │ + │ ☐ I agree to Serverpod blog's contributor terms ↗ │ + │ [Cancel] [Start writing] │ + └───────────────────────────────────────────────────────────┘ + ``` + Unverified publication (§8.2): the line shows the **webhook host** instead of the site host + and "Wonky hasn't verified that this publication belongs to blog.serverpod.dev". The terms + checkbox shows only when the publication has a terms URL and is required then. With open + submissions the dialog lists them first: *Continue "My story"* rows and *Start a new story*. + - *Start writing* calls `publication.startSubmission(publicId, ref?)`: the server creates a + Write document in the user's *My files* root (from the publication's template, or empty; + counted in the user's quota, Drive 03), the submission (`draft`) and the consent record, + and returns the document uuid; the client replaces the route with `/d/:uuid`. +4. **Writing** is a normal document: co-authors, comments, suggestions, offline editing. +5. **Submit** (§4.2) sends the current revision. The chip shows **In review**. +6. **Feedback**: moderators comment and suggest in the document as themselves; the blog's + status messages appear in the feedback thread (§5) and notify the document's editors. +7. **Resubmit / Submit update** after changes; **Withdraw** from the chip's popover. + +## 4. Write UI + +### 4.1 Title row + +Documents with a submission show, left of *Share* (Write 05 §3.2): + +| Element | Widget | Behaviour | +|---------|--------|-----------| +| Status chip | `SubmissionStatusChip` (`wonky_app`; Lucide `newspaper`) | Hidden for `draft`. *In review* (neutral), *Changes requested* (warning), *Declined* (muted), *Published* (success). Click → status popover (§4.3). Shown to every role | +| Submit | `ShadButton.secondary` (Lucide `send`) | `write.submission.submit`. Label: *Submit* (`draft`), *Resubmit* (`changesRequested`, or `inReview` with changes), *Submit update* (`published` with changes). Disabled with a tooltip: offline ("Submitting needs a connection"), no changes since the last submitted revision ("No changes since you submitted"). Hidden for role < editor, `declined`, and a disabled publication. Tooltip "Submit to Serverpod blog". Between 640 and 1200 px icon only | + +### 4.2 Submit dialog + +``` +┌ Submit to Serverpod blog ───────────────────────────────────┐ +│ 📰 Serverpod blog · blog.serverpod.dev ✓ │ +│ Title* [ How we sped up our CI ×3 ] │ +│ Summary [ A short look at … ] │ +│ Tags [ dart ×] [ ci ×] [ + ] │ +│ Cover image [ (thumbnail) Change ] │ +│ Note to the moderators [ ] │ +│ ⚠ 2 open suggestions aren't included. Review them first? │ +│ Comments in the document stay in Wonky (moderators can see │ +│ them). │ +│ [Cancel] [Submit] │ +└─────────────────────────────────────────────────────────────┘ +``` + +- Fields are the publication's configuration (§8.1). First submit prefills: title = document + title (or the first heading), summary = the first paragraph (≤ 300 chars), cover = the first + image. Later submits start from the stored values. +- Open suggestions are sent as the original text (Write 07 §4.1 `suggestions: original`); the + warning links to the first one. +- *Submit* calls `submission.submit(itemUuid, fields, expectedRevision)`; it waits up to 10 s + for the delivery (§7.2). Accepted: toast "Submitted to Serverpod blog", chip *In review*. Not + accepted in time: chip *Submitting…*, toast "Serverpod blog didn't answer yet. We'll keep + trying." (§7.2). + +### 4.3 Status popover + +Publication card (name, host, ✓), status with time and actor ("In review · submitted by Anna 2 +h ago, revision 3"), the last message (excerpt, *Open thread* scrolls the margin to the feedback +thread), *View post ↗* (when `publicUrl`), the submission history (submitted revisions with +*Compare* → version history), *Withdraw submission* (`inReview`, `changesRequested`; confirm), +*Disconnect from Serverpod blog* (not while `inReview`/`changesRequested`; §4.5). + +### 4.4 Menus and commands + +File menu (Write 05 §7.1), after *Share ▸*: *Submit to …* (`write.submission.submit`), +*Submission status* (`write.submission.showStatus`), *Withdraw submission* +(`write.submission.withdraw`) — only for documents with a submission. + +| Command | Undo | +|---------|------| +| `write.submission.submit {fields?}` | Not undoable (sent outside Wonky; *Withdraw* is the counterpart) | +| `write.submission.withdraw` | Not undoable; confirms | +| `write.submission.disconnect` | Undoable (domain `drive`, server inverse: `reconnect` clears `disconnectedAt`) | +| `write.submission.showStatus` | — (view) | +| `shell.settings.open {section: publications}` | — | + +`requiredRole: editor` except `showStatus` (viewer). Enabled flags: `online`, `hasSubmission`. + +### 4.5 Copies, trash and history + +- *Make a copy*, templates and export never take the submission along. +- Trashing a document withdraws an open submission (`submission.withdrawn`, reason `trashed`); + restoring does not resubmit. Purging deletes the submission row (history stays in the blog). +- Disconnecting sets `disconnectedAt`, removes moderator grants and sends + `submission.disconnected`; undo within the session reconnects (no webhook for the + reconnect — the next submit carries the same submission id). +- Version restore doesn't change the submission. + +## 5. Moderators and feedback + +### 5.1 Moderator access + +- Moderators are Wonky accounts the publication owner lists (§8.1; pending emails are converted + on sign-up, like invites, 06 §2). +- **First submit** grants each moderator Commenter on the document: a `DriveItemPermission` with + `viaPublicationId` set (§6), `grantedById` = the submitter, no share notification or email. A + moderator who already has a role keeps the higher one and gets no extra row. +- Withdraw, decline, disconnect, trash and removal of a moderator from the publication delete + the `viaPublicationId` rows; moderators added later get access to the publication's + `inReview`/`changesRequested` submissions. `published` submissions keep access (updates are + reviewed the same way). +- The share dialog (06 §5) shows these rows as "Moderator · Serverpod blog" with Commenter; the + owner (or an editor who may share) can remove them. A direct `share`/`updateRole` for that user + turns the row into a direct grant (`viaPublicationId` cleared). +- Moderators open documents from the blog's queue (`documentUrl` in the webhook); submissions + don't appear in their *Shared with me* until opened (06 §2.2 behaviour for state rows). + +### 5.2 Feedback thread + +- Created by the first message from the blog (§7.3): a `document` thread whose comments have + `authorKind: system` and `publicationId` set (07 §2.1). They render with the publication's name + and the `newspaper` icon. Status messages start with a status line ("**Changes requested**"). +- Editors and moderators reply as themselves. Replies by anyone except the publication itself are + sent to the blog as `comment.created` (§7.1). Other threads stay in Wonky. +- Resolving the thread is allowed; a new message from the blog reopens it. + +### 5.3 Notifications + +New `NotificationKind.submission` (07 §4) for status changes and blog messages, to every editor +of the document (and the submitter). New category `submissions` in Settings › Notifications: +default in-app + immediate email (rare and important). Payload: publication name, status, +message excerpt; link to the document with `?comment=`. + +## 6. Data model (server, `platform/publications/`) + +The models are in `wonky_server/lib/src/platform/publications/models/` (all tables +`serverOnly`; clients get the `*View`, `PublicationCard`, `PublicationSettings` and +`PublicationSecret` classes): + +| Table | What | +|-------|------| +| `publication` | Owner, `publicId` (`pub_` + 22), name, site URL (origin), webhook URL, `verifiedHost`, template item, terms URL, `fields` (`PublicationFields`, JSON column), signing secret (+ previous one during a 24 h rotation), API key hash and last 4, enabled | +| `publication_moderator` | Email (lower case) and the user once an account has it | +| `publication_consent` | Per user: a hash of what was agreed to (shown host, webhook host, terms URL) | +| `publication_block` | Users the publication refuses | +| `submission` | One per document (`itemId` unique): `uuid` (public `sub_`), `ref`, `status`, `statusBeforeSubmit` (restored when a delivery fails), `delivery` (`pending`/`failed`/null), `values` (`SubmissionValues`, JSON), `publicUrl`, `feedbackThreadId`, `disconnectedAt` | +| `submission_revision` | One per submit: `sequence`, document `revision`, named `versionId`, values, and the **`payload`** sent (served again by `GET …/content`) | +| `submission_asset` | Images a submit referenced (`fileUuid`); the API key may download only these | +| `publication_delivery` | The webhook outbox: `webhookId` (`msg_…`), type, payload, `sequence`, attempts, `nextAttemptAt`, `leaseUntil`, last status and error, delivered/failed times | + +Changes to existing models: `DriveItemPermission.viaPublicationId` (FK, cascade: deleting a +publication removes its moderator grants; 06 §2) and `PermissionView.viaPublication` (the +share dialog's "Moderator · "), `Comment.publicationId` (FK, set null) and +`CommentView.authorLabel` (07 §2.1), `NotificationKind.submission` (07 §4), +`ActivityType.submission` (05 §5; summary `{publication, action: submitted | withdrawn | +disconnected | reconnected | status, status?}`). + +## 7. Protocol + +### 7.1 Webhooks (Wonky → blog) + +`POST `, `Content-Type: application/json`, headers `webhook-id`, +`webhook-timestamp` (Unix seconds) and `webhook-signature` (`v1,..">`; during rotation two space-separated signatures). The blog must +check the signature, reject timestamps more than 5 minutes off and drop repeated ids. + +| Type | When | Extra fields | +|------|------|--------------| +| `submission.submitted` | Every submit | `sequence`, `revision`, `fields`, `markdown`, `assets`, `submittedBy`, `note` | +| `submission.withdrawn` | Withdraw or trash | `reason`: `author` \| `trashed` | +| `submission.disconnected` | Disconnect (also after `published`) | — | +| `comment.created` | Reply in the feedback thread | `comment {id, body (Markdown), author {name, wonkyUserId, isModerator}}` | +| `publication.ping` | *Send test* and saving a new webhook URL | — | + +```json +{ + "type": "submission.submitted", + "createdAt": "2026-10-20T09:14:03Z", + "publicationId": "pub_7Hk2…", + "submission": { + "id": "sub_0192…", "ref": "cfp-2026", "status": "inReview", + "documentUrl": "https://wonky.work/write/d/0192…" + }, + "sequence": 2, "revision": 418, + "fields": { "title": "How we sped up our CI ×3", "summary": "…", "tags": ["dart", "ci"], + "coverImage": "ast_0192…" }, + "note": "Fixed the code samples, thanks!", + "markdown": "# How we sped up our CI ×3\n\n…![Build graph](https://wonky.work/api/pub/v1/assets/ast_0192…)…", + "assets": [{ "id": "ast_0192…", "name": "build-graph.png", "type": "image/png", "bytes": 48213, + "url": "https://wonky.work/api/pub/v1/assets/ast_0192…" }], + "submittedBy": { "name": "Anna Berg", "wonkyUserId": "0191…" } +} +``` + +- `markdown` is the Write Markdown export (Write 07 §4) with suggestions as original, no front + matter and no comments; `wonky-file://` images become asset URLs, `https://` images stay. +- Asset URLs need the API key (§7.3). The blog should download them when it receives the + webhook; they work as long as the image exists in Wonky. +- No email addresses are sent. `wonkyUserId` is the profile uuid (for blocking, §7.3). + +### 7.2 Delivery + +- Sent by the server through the SSRF-safe client (P7: resolve, block private/link-local/ + metadata ranges, pin the address, https on port 443 only, no redirects), 10 s + timeout, response body ignored beyond 4 KB. 2xx = accepted. +- `submission.submit` writes the `PublicationDelivery` row in the same transaction as the + `SubmissionRevision`, then tries once while the client waits (≤ 10 s). Accepted → + `status = inReview`, `delivery = null`. Otherwise `delivery = pending` and the outbox retries + with the same `webhook-id`: 1 min, 5 min, 30 min, 2 h, 6 h, 12 h (`wonky.publicationSweep`, + every minute, under a lease; at most 4 concurrent deliveries per publication, oldest first). + After the last failure: `delivery = failed`, the status stays where it was (the chip drops *Submitting…*), the + submitter gets a `submission` notification ("Serverpod blog couldn't receive your + submission"), and the owner sees it under *Deliveries*. +- Deliveries are delivered at least once and may arrive out of order; `sequence` lets the blog + ignore an older submit. + +### 7.3 Publication API (blog → Wonky) + +Relic routes under `https://wonky.work/api/pub/v1/` (`wonky_server/lib/src/web/routes/`), +`Authorization: Bearer wpk_…` (the publication's API key; every call is scoped to that +publication's submissions), JSON, errors `{ "error": "", "message": "…" }`. Header-only +checks before the body (13 §1), 1 MB body cap, 120 requests/min per key (Redis counter like the +MCP limit, 13 §4). + +| Call | Purpose | +|------|---------| +| `GET submissions?status=&after=&limit=` | List for reconciliation (cursor paging) | +| `GET submissions/{id}` | Status, `documentUrl`, last `sequence`/`revision`, fields, `publicUrl` | +| `GET submissions/{id}/content?sequence=` | The `submission.submitted` payload of that submit (from its named version), for a missed webhook | +| `GET assets/{assetId}` | Image bytes; only assets listed in a `SubmissionRevision` of this publication; streamed like downloads (13 §6) | +| `POST submissions/{id}/status` `{status, message?, publicUrl?}` | `inReview`, `changesRequested`, `declined`, `published` (`publicUrl` required, https). Transitions per §2.1; `409 invalidTransition` otherwise. `message` (Markdown, ≤ 10 000 chars) goes into the feedback thread | +| `POST submissions/{id}/messages` `{body}` | A message in the feedback thread without a status change | +| `POST blocks` `{wonkyUserId}` · `DELETE blocks/{wonkyUserId}` | Stop a user from starting or submitting stories to this publication | + +A status call or message on a withdrawn or disconnected submission is `410 gone`. + +## 8. Publication setup (blog owner) + +### 8.1 Settings › Publications + +New Wonky Work settings section `publications` (04 §4.1): a list of the user's publications +(≤ 10) with an empty state "Let people write for your blog in Wonky Write" and *New +publication*. The editor: + +- **General**: name, site URL, webhook URL, enabled, terms URL, template (picker of the owner's + Write documents; its content is copied at start, comments not). +- **Submission fields**: title (always, required) plus toggles for summary, tags (optional list + of allowed tags), cover image, author bio, note to the moderators; each optional or required. +- **Moderators**: add by email (≤ 20), remove. +- **Verification** (§8.2): status and *Verify*. +- **Credentials**: publication id and contributor link (copy buttons), signing secret (shown once + at creation; *Rotate*, old one signs for 24 h), API key (*Create*, shown once; *Rotate* + revokes the old key at once). +- **Deliveries**: the last 50 with type, time, HTTP status, error; *Resend*; *Send test* + (`publication.ping`). + +Saving a new webhook URL sends a `publication.ping`; a non-2xx answer shows the error and saves +the URL anyway (the blog may deploy its receiver later). Settings changes are not undoable +(like sharing, 08 §2). + +### 8.2 Verification + +The owner serves `https:///.well-known/wonky-publications.json`: + +```json +{ "publications": ["pub_7Hk2…"] } +``` + +*Verify* fetches it through the SSRF-safe client; when it lists the publication, +`verifiedHost` = the site host. Changing the site URL clears verification. Verified publications +show the site host with ✓ in the consent and submit dialogs; unverified ones show the webhook +host and a warning (§3), so a copied name can't pretend to be another blog. + +### 8.3 Blog-side checklist (also in the developer guide, §12 PUB-7) + +1. Create the publication, verify the site, store the signing secret and API key server-side. +2. Add the *Write for us* link. +3. Webhook receiver: check the signature (any Standard Webhooks library), dedupe by + `webhook-id`, upsert the queue entry by `submission.id`, ignore an older `sequence`, download + the assets, answer 2xx fast. +4. Moderation UI: show the Markdown, link *Open in Wonky* (`documentUrl`), and call the status + API for *Request changes*, *Decline* and *Publish* (with the post's URL). + +## 9. Endpoints and MCP + +### 9.1 `PublicationEndpoint` (`publication`, signed in) + +`resolve(publicId)` → `PublicationCard {name, siteHost, verified, webhookHost, termsUrl, +fields, ownerName, consentNeeded, openSubmissions}`; `startSubmission(publicId, ref?, +consent?)` → item uuid; owner-only: `list()`, `create(...)`, `update(...)`, `verify(uuid)`, +`rotateSecret(uuid)`, `createApiKey(uuid)` → key once, `setModerators(uuid, emails)`, +`deliveries(uuid)`, `resend(deliveryId)`, `sendTest(uuid)`, `delete(uuid)` (disconnects every +submission, sends nothing). + +### 9.2 `SubmissionEndpoint` (`submission`) + +`get(itemUuid)` → `SubmissionView?` (viewer+); `submit(itemUuid, values, agreed)` (editor+, +publication enabled, not blocked, not `declined`; `agreed` confirms changed terms): names a +version, exports that version's revision and sends it; `withdraw(itemUuid)`, +`disconnect(itemUuid)`, `reconnect(itemUuid)` (editor+). Changes reach open editors as a +`DriveChange` of kind `updated` for the item; Write's `SubmissionController` reloads on it. + +### 9.3 MCP and AI + +**Not planned** (only on a feature request): headless `write.get_submission` and +`write.submit` tools. Agents can use the commands through the UI bridge +(`ui.invoke_command`, `write.submission.*`). The AI assistant can't submit, withdraw or +disconnect (like sharing, 13 §1). + +## 10. Limits and abuse + +- ≤ 10 publications per owner, ≤ 20 moderators per publication. +- Per user and publication: ≤ 10 `startSubmission` and ≤ 20 submits per day + (`limitExceeded` "You've sent a lot to Serverpod blog today. Try again tomorrow."). +- Markdown payload ≤ 5 MB (`tooLarge` in the submit dialog); fields ≤ 2 000 chars each. +- Blocks (§7.3) stop `startSubmission` and `submit` for that user. +- Account deletion: an owner's publications are deleted (submissions disconnected, moderator + grants removed); a contributor's documents follow 13 §2 and their open submissions are + withdrawn. + +## 11. Security and privacy summary + +Rows in 13 §1: forged contributor links (P1, §8.2), SSRF through the webhook URL (P7), forged or +replayed deliveries (signatures, timestamp window, ids), stolen API keys (hashed, shown once, +rotate, scoped to one publication, rate limited), moderator access beyond the submission +(Commenter only, removed on withdraw/decline/disconnect), spam and floods (§10). Privacy (13 §2): +submitted content goes to a third party the user chose, after consent; the signing secret is +stored unencrypted (it must sign) with the same caveat as user AI keys; the privacy policy (13 +§5) names submissions. + +## 12. Work packages + +| WP | Scope | Depends on | +|----|-------|------------| +| PUB-1 | Models (§6) and migration, `PublicationService`, `SubmissionService`, access rules, moderator grants (06), feedback-thread comments (07) | — | +| PUB-2 | Outbound: shared SSRF-safe client extracted from `url_fetch_proxy.dart`, Standard Webhooks signer, outbox and `wonky.publicationSweep` | PUB-1 | +| PUB-3 | Publication API routes (§7.3), API keys, rate limit, `.well-known` verification | PUB-1 | +| PUB-4 | Settings › Publications (§8.1) | PUB-1–3 | +| PUB-5 | Write: `/new?publication=`, consent dialog, Submit button and dialog, status chip and popover, commands, File menu, notifications category | PUB-1, PUB-2 | +| PUB-6 | MCP tools, activity entries, legal pages | PUB-5 | +| PUB-7 | Developer guide for blog owners with a sample receiver (Dart, Relic) | PUB-3 | +| PUB-8 | Tests: services and API (access matrix, transitions, rotation, blocks), webhook signing vectors, SSRF matrix reused, delivery retries with a fake receiver (tests allow a loopback receiver through a test-only override, never in staging/production), widget tests and goldens (light/dark), E2E journey J-P1: link → sign up → write → submit → request changes → resubmit → publish | all | + +## 13. As built (M14) + +- **Server**: `platform/publications/` (`PublicationService`, `SubmissionService`, + `PublicationWebhooks` outbox, `PublicationApi` behind `web/routes/publication_api_route.dart`, + `PublicationHttp` on the SSRF-safe `UrlFetchProxy` with https/443 only and no redirects, + `PublicationsFutureCall` with `wonky.publicationSweep` every minute, deliveries purged after 30 + days). Hooks: trash/restore (`DriveTrash`), feedback-thread replies (`CommentService.reply`), + pending moderators linked at sign-up (`UserService.ensureProfile`), direct shares turn a + moderator grant into a direct one (`SharingService`). +- **Moderator access** is synced at every submit, status change, withdraw, disconnect, trash + and restore. A moderator who signs up later, or whom an editor removes in the share dialog, + gets access back with the next submit or status change. +- **Templates**: the template's text is copied without comments and with suggestions accepted; + its images are copied into the new document (they belong to the contributor). +- **Client**: `wonky_app` (`PublicationRepository`, Settings › Publications + `PublicationsSection`, `startPublicationStory` for `/new?publication=`, `SubmissionUndoHandler` + for disconnect, notification, activity, comment and share-dialog rendering) and Write + (`features/publish/`: `SubmissionController` on `WriteDocumentController.submission`, + `SubmissionTitleActions`, the submit dialog, `write.submission.*` commands, File menu items, + which stay listed but disabled for documents without a submission). +- **Tests**: server `test/unit/publications/` (signing vector of the guide, rules) and + `test/integration/platform/publications/` (flow, API over HTTP, owner endpoints); client + `wonky_app/test/publications/` and `wonky_write/test/features/publish/`. +- **Open**: light/dark goldens of the dialogs and chip; the E2E journey J-P1; moderators who + sign up later get access only with the next submit or status change. +- **Not planned** (only on a feature request): MCP tools (§9.3); Write `?comment=` deep links, + so notifications open the publication's thread (they open the document). diff --git a/specs/README.md b/specs/README.md index 1868950b..4e8ba85e 100644 --- a/specs/README.md +++ b/specs/README.md @@ -67,10 +67,11 @@ charts). | 11 | [Quality](11-quality-testing-accessibility.md) | Testing, performance budgets, accessibility, i18n, observability | | 12 | [Offline & sync](12-offline-and-sync.md) | Local stores, Write offline, Sheets/Slides on RevLog (summary), upload queue, scale limits | | 13 | [Security & operations](13-security-and-operations.md) | Threat model, privacy, deployment, scheduled jobs, arbitrary uploads | -| 14 | [Roadmap](14-roadmap.md) | Milestones M0–M13 (v2: M8 Drive + suite changes, M9–M11 Slides; M12 Bugs & improvements; M13 RevLog), how parallel agents execute the work packages, shared workstreams, risks | +| 14 | [Roadmap](14-roadmap.md) | Milestones M0–M14 (v2: M8 Drive + suite changes, M9–M11 Slides; M12 Bugs & improvements; M13 RevLog; M14 Publications), how parallel agents execute the work packages, shared workstreams, risks | | 15 | [Writing tests](15-writing-tests.md) | How to write tests: layout, naming, helpers, server/widget/golden/property/E2E patterns, determinism, running | | 16 | [Bugs & improvements](16-bugs-and-improvements.md) | Public board for bug reports and improvement ideas: report dialog with annotated screenshots, votes, comments, AI triage and moderation, admins, tasks with contributor prompts, claims, GitHub PR rules (M12, built) | | 17 | [RevLog sync](17-revlog-sync.md) | Server-sequenced op log of Sheets and Slides: decisions, data model, change sets and apply rules, protocol, server (sequencer, hooks, pages, headless cache), client (cache, outbox, bootstrap, conflicts), performance gates, as-built notes (M13) | +| 18 | [Publications & submissions](18-publications-and-submissions.md) | Blogs register a publication; contributors write in Wonky Write and *Submit* to the blog's review queue (signed webhooks, publication API, moderators with comment access, feedback in the document) (M14, built) | ## Conventions used in all specs diff --git a/specs/wonky_write/05-screens-menus-toolbar.md b/specs/wonky_write/05-screens-menus-toolbar.md index 36787b12..b927d9fa 100644 --- a/specs/wonky_write/05-screens-menus-toolbar.md +++ b/specs/wonky_write/05-screens-menus-toolbar.md @@ -87,6 +87,7 @@ Overlays (dialogs, palette, toasts, offline banner, MCP pill) per suite 03 §3. | — spacer — | | | | Presence | `PresenceAvatarStack` | Click avatar → `write.nav.goToCollaborator`; ⋮ → Follow (`write.nav.follow`) | | Bugs & improvements (M12) | `ShadIconButton.ghost` (Lucide `messageSquarePlus`, tooltip "Bugs & improvements"; replaces *Report a bug*) | `shell.board.report` — report dialog, suite 16 §4.2; hidden below 640 px (still in Help) | +| Submission status, Submit (M14) | `SubmissionStatusChip`, `ShadButton.secondary` (Lucide `send`) | Only for documents with a submission: status popover, `write.submission.submit` — [18 §4](../18-publications-and-submissions.md) | | Share | `ShadButton` primary (lock / globe / users icon by link state) | `shell.sharing.open` | | Account | `ShadAvatar` menu | suite 04; (v2) *Write settings*, *Wonky Work settings*, *Open ▸* the four apps, *Sign out* | @@ -263,6 +264,7 @@ Write behaviour noted. | ─ | | | | | | Share ▸ Share with others *(shell)* | `shell.sharing.open` | — | — | always (role decides dialog content) | | Share ▸ Copy link *(shell)* | `shell.sharing.copyLink` | — | — | always | +| Submit to … (M14) | `write.submission.submit` (+ *Submission status*, *Withdraw submission*; [18 §4.4](../18-publications-and-submissions.md)) | — | — | has a submission, role ≥ editor, `online` | | Download ▸ Markdown (.md) | `write.file.download {format: md}` | — | — | `copyAllowed` | | Download ▸ Markdown with images (.zip) | `{format: mdZip}` | — | — | same | | Download ▸ PDF (.pdf) | `{format: pdf}` | — | — | same | diff --git a/wonky_client/lib/src/protocol/client.dart b/wonky_client/lib/src/protocol/client.dart index 7fcde455..2031470f 100644 --- a/wonky_client/lib/src/protocol/client.dart +++ b/wonky_client/lib/src/protocol/client.dart @@ -150,6 +150,24 @@ import 'package:wonky_client/src/protocol/platform/presence/presence_event.dart' as _i1lme7np; import 'package:wonky_client/src/protocol/platform/presence/presence_update.dart' as _izu9ijhe; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_card.dart' + as _igbz1wj9; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_check_result.dart' + as _i9sbxmp8; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_delivery_view.dart' + as _ipl2ldhs; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_input.dart' + as _ii8xbzwt; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_secret.dart' + as _ihfocp8h; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_settings.dart' + as _i9bruko9; +import 'package:wonky_client/src/protocol/platform/publications/models/submission_started.dart' + as _i767e3eb; +import 'package:wonky_client/src/protocol/platform/publications/models/submission_values.dart' + as _i8t9b0m8; +import 'package:wonky_client/src/protocol/platform/publications/models/submission_view.dart' + as _iy9ei8t0; import 'package:wonky_client/src/protocol/platform/revlog/messages/rev_client_message.dart' as _iedvhh7l; import 'package:wonky_client/src/protocol/platform/revlog/messages/rev_server_message.dart' @@ -2257,6 +2275,189 @@ class EndpointPresence extends _isc.EndpointRef { ); } +/// Publications (specs/18 §9.1): starting a story from a contributor link, +/// and the owner's settings. +/// {@category Endpoint} +class EndpointPublication extends _isc.EndpointRef { + EndpointPublication(_isc.EndpointCaller caller) : super(caller); + + @override + String get name => 'publication'; + + /// The publication of a contributor link. + _ida.Future<_igbz1wj9.PublicationCard> resolve(String publicId) => + caller.callServerEndpoint<_igbz1wj9.PublicationCard>( + 'publication', + 'resolve', + {'publicId': publicId}, + ); + + /// Creates the document of a new story; [agreed] confirms the consent + /// dialog. + _ida.Future<_i767e3eb.SubmissionStarted> startSubmission( + String publicId, + String? ref, + bool agreed, + ) => caller.callServerEndpoint<_i767e3eb.SubmissionStarted>( + 'publication', + 'startSubmission', + { + 'publicId': publicId, + 'ref': ref, + 'agreed': agreed, + }, + ); + + _ida.Future> list() => + caller.callServerEndpoint>( + 'publication', + 'list', + {}, + ); + + /// Creates a publication; the result holds the signing secret once. + _ida.Future<_ihfocp8h.PublicationSecret> create( + _ii8xbzwt.PublicationInput input, + ) => caller.callServerEndpoint<_ihfocp8h.PublicationSecret>( + 'publication', + 'create', + {'input': input}, + ); + + _ida.Future<_i9bruko9.PublicationSettings> update( + String publicId, + _ii8xbzwt.PublicationInput input, + ) => caller.callServerEndpoint<_i9bruko9.PublicationSettings>( + 'publication', + 'update', + { + 'publicId': publicId, + 'input': input, + }, + ); + + _ida.Future delete(String publicId) => caller.callServerEndpoint( + 'publication', + 'delete', + {'publicId': publicId}, + ); + + _ida.Future<_i9sbxmp8.PublicationCheckResult> verify(String publicId) => + caller.callServerEndpoint<_i9sbxmp8.PublicationCheckResult>( + 'publication', + 'verify', + {'publicId': publicId}, + ); + + _ida.Future<_ihfocp8h.PublicationSecret> rotateSecret(String publicId) => + caller.callServerEndpoint<_ihfocp8h.PublicationSecret>( + 'publication', + 'rotateSecret', + {'publicId': publicId}, + ); + + _ida.Future<_ihfocp8h.PublicationSecret> createApiKey(String publicId) => + caller.callServerEndpoint<_ihfocp8h.PublicationSecret>( + 'publication', + 'createApiKey', + {'publicId': publicId}, + ); + + _ida.Future<_i9bruko9.PublicationSettings> setModerators( + String publicId, + List emails, + ) => caller.callServerEndpoint<_i9bruko9.PublicationSettings>( + 'publication', + 'setModerators', + { + 'publicId': publicId, + 'emails': emails, + }, + ); + + _ida.Future> deliveries( + String publicId, + ) => caller.callServerEndpoint>( + 'publication', + 'deliveries', + {'publicId': publicId}, + ); + + _ida.Future<_ipl2ldhs.PublicationDeliveryView> resend( + String publicId, + String webhookId, + ) => caller.callServerEndpoint<_ipl2ldhs.PublicationDeliveryView>( + 'publication', + 'resend', + { + 'publicId': publicId, + 'webhookId': webhookId, + }, + ); + + _ida.Future<_i9sbxmp8.PublicationCheckResult> sendTest(String publicId) => + caller.callServerEndpoint<_i9sbxmp8.PublicationCheckResult>( + 'publication', + 'sendTest', + {'publicId': publicId}, + ); +} + +/// A document's submission to a publication (specs/18 §9.2). +/// {@category Endpoint} +class EndpointSubmission extends _isc.EndpointRef { + EndpointSubmission(_isc.EndpointCaller caller) : super(caller); + + @override + String get name => 'submission'; + + /// The document's submission, or null (viewer+). + _ida.Future<_iy9ei8t0.SubmissionView?> get(_isc.UuidValue itemUuid) => + caller.callServerEndpoint<_iy9ei8t0.SubmissionView?>( + 'submission', + 'get', + {'itemUuid': itemUuid}, + ); + + /// Submits the current revision (editor+); [agreed] confirms the + /// publication's terms when they changed. + _ida.Future<_iy9ei8t0.SubmissionView> submit( + _isc.UuidValue itemUuid, + _i8t9b0m8.SubmissionValues values, + bool agreed, + ) => caller.callServerEndpoint<_iy9ei8t0.SubmissionView>( + 'submission', + 'submit', + { + 'itemUuid': itemUuid, + 'values': values, + 'agreed': agreed, + }, + ); + + _ida.Future<_iy9ei8t0.SubmissionView> withdraw(_isc.UuidValue itemUuid) => + caller.callServerEndpoint<_iy9ei8t0.SubmissionView>( + 'submission', + 'withdraw', + {'itemUuid': itemUuid}, + ); + + _ida.Future disconnect(_isc.UuidValue itemUuid) => + caller.callServerEndpoint( + 'submission', + 'disconnect', + {'itemUuid': itemUuid}, + ); + + /// Undoes [disconnect]. + _ida.Future<_iy9ei8t0.SubmissionView?> reconnect(_isc.UuidValue itemUuid) => + caller.callServerEndpoint<_iy9ei8t0.SubmissionView?>( + 'submission', + 'reconnect', + {'itemUuid': itemUuid}, + ); +} + /// Sharing (specs/06 §4). /// {@category Endpoint} class EndpointSharing extends _isc.EndpointRef { @@ -4243,6 +4444,8 @@ class Client extends _isc.ServerpodClientShared { meta = EndpointMeta(this); notification = EndpointNotification(this); presence = EndpointPresence(this); + publication = EndpointPublication(this); + submission = EndpointSubmission(this); sharing = EndpointSharing(this); accessToken = EndpointAccessToken(this); googleIdp = EndpointGoogleIdp(this); @@ -4297,6 +4500,10 @@ class Client extends _isc.ServerpodClientShared { late final EndpointPresence presence; + late final EndpointPublication publication; + + late final EndpointSubmission submission; + late final EndpointSharing sharing; late final EndpointAccessToken accessToken; @@ -4361,6 +4568,8 @@ class Client extends _isc.ServerpodClientShared { 'meta': meta, 'notification': notification, 'presence': presence, + 'publication': publication, + 'submission': submission, 'sharing': sharing, 'accessToken': accessToken, 'googleIdp': googleIdp, diff --git a/wonky_client/lib/src/protocol/platform/activity/activity_type.dart b/wonky_client/lib/src/protocol/platform/activity/activity_type.dart index 159f614f..258938b6 100644 --- a/wonky_client/lib/src/protocol/platform/activity/activity_type.dart +++ b/wonky_client/lib/src/protocol/platform/activity/activity_type.dart @@ -26,7 +26,12 @@ enum ActivityType implements _isc.SerializableModel { exported, /// (v2) A file was uploaded (Drive 02 §3.3). - uploaded; + uploaded, + + /// (M14) Submitted to, withdrawn from or disconnected from a publication, + /// or the publication changed the status (specs/18 §6; summary + /// {publication, action, status?}). + submission; static ActivityType fromJson(String name) { switch (name) { @@ -54,6 +59,8 @@ enum ActivityType implements _isc.SerializableModel { return ActivityType.exported; case 'uploaded': return ActivityType.uploaded; + case 'submission': + return ActivityType.submission; default: throw ArgumentError( 'Value "$name" cannot be converted to "ActivityType"', diff --git a/wonky_client/lib/src/protocol/platform/comments/comment.dart b/wonky_client/lib/src/protocol/platform/comments/comment.dart index 0a916692..d4a75c69 100644 --- a/wonky_client/lib/src/protocol/platform/comments/comment.dart +++ b/wonky_client/lib/src/protocol/platform/comments/comment.dart @@ -30,6 +30,7 @@ abstract class Comment this.editedAt, this.deletedAt, this.systemEvent, + this.publicationId, }) : reactions = reactions ?? '{}'; factory Comment({ @@ -45,6 +46,7 @@ abstract class Comment DateTime? editedAt, DateTime? deletedAt, _ikzs0dm0.CommentSystemEvent? systemEvent, + int? publicationId, }) = _CommentImpl; factory Comment.fromJson(Map jsonSerialization) { @@ -77,6 +79,7 @@ abstract class Comment : _ikzs0dm0.CommentSystemEvent.fromJson( (jsonSerialization['systemEvent'] as String), ), + publicationId: jsonSerialization['publicationId'] as int?, ); } @@ -113,6 +116,9 @@ abstract class Comment _ikzs0dm0.CommentSystemEvent? systemEvent; + /// (M14) A publication's message (authorKind system), specs/18 §5.2. + int? publicationId; + /// Returns a shallow copy of this [Comment] /// with some or all fields replaced by the given arguments. @_isc.useResult @@ -129,6 +135,7 @@ abstract class Comment DateTime? editedAt = const _isc.$UndefinedDateTime(), DateTime? deletedAt = const _isc.$UndefinedDateTime(), _ikzs0dm0.CommentSystemEvent? systemEvent, + int? publicationId, }); @override Map toJson() { @@ -146,6 +153,7 @@ abstract class Comment if (editedAt != null) 'editedAt': editedAt?.toJson(), if (deletedAt != null) 'deletedAt': deletedAt?.toJson(), if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (publicationId != null) 'publicationId': publicationId, }; } @@ -165,6 +173,7 @@ abstract class Comment if (editedAt != null) 'editedAt': editedAt?.toJson(), if (deletedAt != null) 'deletedAt': deletedAt?.toJson(), if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (publicationId != null) 'publicationId': publicationId, }; } @@ -190,6 +199,7 @@ class _CommentImpl extends Comment { DateTime? editedAt, DateTime? deletedAt, _ikzs0dm0.CommentSystemEvent? systemEvent, + int? publicationId, }) : super._( id: id, threadId: threadId, @@ -203,6 +213,7 @@ class _CommentImpl extends Comment { editedAt: editedAt, deletedAt: deletedAt, systemEvent: systemEvent, + publicationId: publicationId, ); /// Returns a shallow copy of this [Comment] @@ -222,6 +233,7 @@ class _CommentImpl extends Comment { DateTime? editedAt = const _isc.$UndefinedDateTime(), DateTime? deletedAt = const _isc.$UndefinedDateTime(), Object? systemEvent = _Undefined, + Object? publicationId = _Undefined, }) { return Comment( id: id is int? ? id : this.id, @@ -240,6 +252,7 @@ class _CommentImpl extends Comment { systemEvent: systemEvent is _ikzs0dm0.CommentSystemEvent? ? systemEvent : this.systemEvent, + publicationId: publicationId is int? ? publicationId : this.publicationId, ); } } diff --git a/wonky_client/lib/src/protocol/platform/comments/comment_view.dart b/wonky_client/lib/src/protocol/platform/comments/comment_view.dart index ec16e983..209eefb0 100644 --- a/wonky_client/lib/src/protocol/platform/comments/comment_view.dart +++ b/wonky_client/lib/src/protocol/platform/comments/comment_view.dart @@ -31,6 +31,7 @@ abstract class CommentView this.editedAt, required this.deleted, this.systemEvent, + this.authorLabel, }); factory CommentView({ @@ -46,6 +47,7 @@ abstract class CommentView DateTime? editedAt, required bool deleted, _ikzs0dm0.CommentSystemEvent? systemEvent, + String? authorLabel, }) = _CommentViewImpl; factory CommentView.fromJson(Map jsonSerialization) { @@ -84,6 +86,7 @@ abstract class CommentView : _ikzs0dm0.CommentSystemEvent.fromJson( (jsonSerialization['systemEvent'] as String), ), + authorLabel: jsonSerialization['authorLabel'] as String?, ); } @@ -113,6 +116,10 @@ abstract class CommentView _ikzs0dm0.CommentSystemEvent? systemEvent; + /// (M14) Name shown instead of a user: the publication of a message + /// (specs/18 §5.2). + String? authorLabel; + /// Returns a shallow copy of this [CommentView] /// with some or all fields replaced by the given arguments. @_isc.useResult @@ -129,6 +136,7 @@ abstract class CommentView DateTime? editedAt = const _isc.$UndefinedDateTime(), bool? deleted, _ikzs0dm0.CommentSystemEvent? systemEvent, + String? authorLabel, }); @override Map toJson() { @@ -146,6 +154,7 @@ abstract class CommentView if (editedAt != null) 'editedAt': editedAt?.toJson(), 'deleted': deleted, if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (authorLabel != null) 'authorLabel': authorLabel, }; } @@ -165,6 +174,7 @@ abstract class CommentView if (editedAt != null) 'editedAt': editedAt?.toJson(), 'deleted': deleted, if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (authorLabel != null) 'authorLabel': authorLabel, }; } @@ -195,6 +205,7 @@ class _CommentViewImpl extends CommentView { DateTime? editedAt, required bool deleted, _ikzs0dm0.CommentSystemEvent? systemEvent, + String? authorLabel, }) : super._( id: id, uuid: uuid, @@ -208,6 +219,7 @@ class _CommentViewImpl extends CommentView { editedAt: editedAt, deleted: deleted, systemEvent: systemEvent, + authorLabel: authorLabel, ); /// Returns a shallow copy of this [CommentView] @@ -227,6 +239,7 @@ class _CommentViewImpl extends CommentView { DateTime? editedAt = const _isc.$UndefinedDateTime(), bool? deleted, Object? systemEvent = _Undefined, + Object? authorLabel = _Undefined, }) { return CommentView( id: id ?? this.id, @@ -255,6 +268,7 @@ class _CommentViewImpl extends CommentView { systemEvent: systemEvent is _ikzs0dm0.CommentSystemEvent? ? systemEvent : this.systemEvent, + authorLabel: authorLabel is String? ? authorLabel : this.authorLabel, ); } } diff --git a/wonky_client/lib/src/protocol/platform/notifications/notification_kind.dart b/wonky_client/lib/src/protocol/platform/notifications/notification_kind.dart index e2b12316..e02642de 100644 --- a/wonky_client/lib/src/protocol/platform/notifications/notification_kind.dart +++ b/wonky_client/lib/src/protocol/platform/notifications/notification_kind.dart @@ -35,7 +35,11 @@ enum NotificationKind implements _isc.SerializableModel { boardStatus, /// My claim: warning, expiry, released, PR closed. - boardClaim; + boardClaim, + + /// (M14) A publication changed the status of a story I can edit or sent + /// a message; a submission could not be delivered (specs/18 §5.3). + submission; static NotificationKind fromJson(String name) { switch (name) { @@ -65,6 +69,8 @@ enum NotificationKind implements _isc.SerializableModel { return NotificationKind.boardStatus; case 'boardClaim': return NotificationKind.boardClaim; + case 'submission': + return NotificationKind.submission; default: throw ArgumentError( 'Value "$name" cannot be converted to "NotificationKind"', diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_card.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_card.dart new file mode 100644 index 00000000..b4dc234f --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_card.dart @@ -0,0 +1,246 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; +import '../../../platform/publications/models/publication_open_submission.dart' + as _i2kst26h; + +/// What a contributor sees of a publication (specs/18 §3, §9.1). +abstract class PublicationCard + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationCard._({ + required this.publicId, + required this.name, + required this.shownHost, + required this.verified, + required this.siteHost, + required this.webhookHost, + this.termsUrl, + required this.fields, + required this.ownerName, + required this.enabled, + required this.consentNeeded, + required this.blocked, + required this.openSubmissions, + }); + + factory PublicationCard({ + required String publicId, + required String name, + required String shownHost, + required bool verified, + required String siteHost, + required String webhookHost, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required String ownerName, + required bool enabled, + required bool consentNeeded, + required bool blocked, + required List<_i2kst26h.PublicationOpenSubmission> openSubmissions, + }) = _PublicationCardImpl; + + factory PublicationCard.fromJson(Map jsonSerialization) { + return PublicationCard( + publicId: jsonSerialization['publicId'] as String, + name: jsonSerialization['name'] as String, + shownHost: jsonSerialization['shownHost'] as String, + verified: _isc.BoolJsonExtension.fromJson(jsonSerialization['verified']), + siteHost: jsonSerialization['siteHost'] as String, + webhookHost: jsonSerialization['webhookHost'] as String, + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _i8pkqg1o.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + ownerName: jsonSerialization['ownerName'] as String, + enabled: _isc.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + consentNeeded: _isc.BoolJsonExtension.fromJson( + jsonSerialization['consentNeeded'], + ), + blocked: _isc.BoolJsonExtension.fromJson(jsonSerialization['blocked']), + openSubmissions: _i8pkqg1o.Protocol() + .deserialize>( + jsonSerialization['openSubmissions'], + ), + ); + } + + String publicId; + + String name; + + /// The verified site host, or the webhook host when unverified. + String shownHost; + + bool verified; + + String siteHost; + + String webhookHost; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + String ownerName; + + bool enabled; + + /// The caller must agree first (never asked or what was agreed changed). + bool consentNeeded; + + /// The publication doesn't take stories from the caller. + bool blocked; + + /// The caller's drafts and stories with changes requested. + List<_i2kst26h.PublicationOpenSubmission> openSubmissions; + + /// Returns a shallow copy of this [PublicationCard] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationCard copyWith({ + String? publicId, + String? name, + String? shownHost, + bool? verified, + String? siteHost, + String? webhookHost, + String? termsUrl, + _i1a71r29.PublicationFields? fields, + String? ownerName, + bool? enabled, + bool? consentNeeded, + bool? blocked, + List<_i2kst26h.PublicationOpenSubmission>? openSubmissions, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationCard', + 'publicId': publicId, + 'name': name, + 'shownHost': shownHost, + 'verified': verified, + 'siteHost': siteHost, + 'webhookHost': webhookHost, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'ownerName': ownerName, + 'enabled': enabled, + 'consentNeeded': consentNeeded, + 'blocked': blocked, + 'openSubmissions': openSubmissions.toJson(valueToJson: (v) => v.toJson()), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationCard', + 'publicId': publicId, + 'name': name, + 'shownHost': shownHost, + 'verified': verified, + 'siteHost': siteHost, + 'webhookHost': webhookHost, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJsonForProtocol(), + 'ownerName': ownerName, + 'enabled': enabled, + 'consentNeeded': consentNeeded, + 'blocked': blocked, + 'openSubmissions': openSubmissions.toJson( + valueToJson: (v) => v.toJsonForProtocol(), + ), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationCardImpl extends PublicationCard { + _PublicationCardImpl({ + required String publicId, + required String name, + required String shownHost, + required bool verified, + required String siteHost, + required String webhookHost, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required String ownerName, + required bool enabled, + required bool consentNeeded, + required bool blocked, + required List<_i2kst26h.PublicationOpenSubmission> openSubmissions, + }) : super._( + publicId: publicId, + name: name, + shownHost: shownHost, + verified: verified, + siteHost: siteHost, + webhookHost: webhookHost, + termsUrl: termsUrl, + fields: fields, + ownerName: ownerName, + enabled: enabled, + consentNeeded: consentNeeded, + blocked: blocked, + openSubmissions: openSubmissions, + ); + + /// Returns a shallow copy of this [PublicationCard] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationCard copyWith({ + String? publicId, + String? name, + String? shownHost, + bool? verified, + String? siteHost, + String? webhookHost, + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + String? ownerName, + bool? enabled, + bool? consentNeeded, + bool? blocked, + List<_i2kst26h.PublicationOpenSubmission>? openSubmissions, + }) { + return PublicationCard( + publicId: publicId ?? this.publicId, + name: name ?? this.name, + shownHost: shownHost ?? this.shownHost, + verified: verified ?? this.verified, + siteHost: siteHost ?? this.siteHost, + webhookHost: webhookHost ?? this.webhookHost, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + ownerName: ownerName ?? this.ownerName, + enabled: enabled ?? this.enabled, + consentNeeded: consentNeeded ?? this.consentNeeded, + blocked: blocked ?? this.blocked, + openSubmissions: + openSubmissions ?? + this.openSubmissions.map((e0) => e0.copyWith()).toList(), + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_check_result.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_check_result.dart new file mode 100644 index 00000000..736e2ae4 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_check_result.dart @@ -0,0 +1,114 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_settings.dart' + as _iyzf06w5; + +/// Result of *Verify* or *Send test* (specs/18 §8.1, §8.2). +abstract class PublicationCheckResult + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationCheckResult._({ + required this.ok, + this.message, + required this.settings, + }); + + factory PublicationCheckResult({ + required bool ok, + String? message, + required _iyzf06w5.PublicationSettings settings, + }) = _PublicationCheckResultImpl; + + factory PublicationCheckResult.fromJson( + Map jsonSerialization, + ) { + return PublicationCheckResult( + ok: _isc.BoolJsonExtension.fromJson(jsonSerialization['ok']), + message: jsonSerialization['message'] as String?, + settings: _i8pkqg1o.Protocol().deserialize<_iyzf06w5.PublicationSettings>( + jsonSerialization['settings'], + ), + ); + } + + bool ok; + + /// What went wrong, for the owner. + String? message; + + _iyzf06w5.PublicationSettings settings; + + /// Returns a shallow copy of this [PublicationCheckResult] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationCheckResult copyWith({ + bool? ok, + String? message, + _iyzf06w5.PublicationSettings? settings, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationCheckResult', + 'ok': ok, + if (message != null) 'message': message, + 'settings': settings.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationCheckResult', + 'ok': ok, + if (message != null) 'message': message, + 'settings': settings.toJsonForProtocol(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationCheckResultImpl extends PublicationCheckResult { + _PublicationCheckResultImpl({ + required bool ok, + String? message, + required _iyzf06w5.PublicationSettings settings, + }) : super._( + ok: ok, + message: message, + settings: settings, + ); + + /// Returns a shallow copy of this [PublicationCheckResult] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationCheckResult copyWith({ + bool? ok, + Object? message = _Undefined, + _iyzf06w5.PublicationSettings? settings, + }) { + return PublicationCheckResult( + ok: ok ?? this.ok, + message: message is String? ? message : this.message, + settings: settings ?? this.settings.copyWith(), + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_delivery_view.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_delivery_view.dart new file mode 100644 index 00000000..7c9754b4 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_delivery_view.dart @@ -0,0 +1,196 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +/// A webhook delivery in the owner's *Deliveries* list (specs/18 §8.1). +abstract class PublicationDeliveryView + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationDeliveryView._({ + required this.webhookId, + required this.type, + required this.createdAt, + required this.attempts, + this.lastStatus, + this.lastError, + this.deliveredAt, + this.failedAt, + this.nextAttemptAt, + }); + + factory PublicationDeliveryView({ + required String webhookId, + required String type, + required DateTime createdAt, + required int attempts, + int? lastStatus, + String? lastError, + DateTime? deliveredAt, + DateTime? failedAt, + DateTime? nextAttemptAt, + }) = _PublicationDeliveryViewImpl; + + factory PublicationDeliveryView.fromJson( + Map jsonSerialization, + ) { + return PublicationDeliveryView( + webhookId: jsonSerialization['webhookId'] as String, + type: jsonSerialization['type'] as String, + createdAt: _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + attempts: jsonSerialization['attempts'] as int, + lastStatus: jsonSerialization['lastStatus'] as int?, + lastError: jsonSerialization['lastError'] as String?, + deliveredAt: jsonSerialization['deliveredAt'] == null + ? null + : _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['deliveredAt'], + ), + failedAt: jsonSerialization['failedAt'] == null + ? null + : _isc.DateTimeJsonExtension.fromJson(jsonSerialization['failedAt']), + nextAttemptAt: jsonSerialization['nextAttemptAt'] == null + ? null + : _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['nextAttemptAt'], + ), + ); + } + + String webhookId; + + String type; + + DateTime createdAt; + + int attempts; + + int? lastStatus; + + String? lastError; + + DateTime? deliveredAt; + + DateTime? failedAt; + + DateTime? nextAttemptAt; + + /// Returns a shallow copy of this [PublicationDeliveryView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationDeliveryView copyWith({ + String? webhookId, + String? type, + DateTime? createdAt, + int? attempts, + int? lastStatus, + String? lastError, + DateTime? deliveredAt = const _isc.$UndefinedDateTime(), + DateTime? failedAt = const _isc.$UndefinedDateTime(), + DateTime? nextAttemptAt = const _isc.$UndefinedDateTime(), + }); + @override + Map toJson() { + return { + '__className__': 'PublicationDeliveryView', + 'webhookId': webhookId, + 'type': type, + 'createdAt': createdAt.toJson(), + 'attempts': attempts, + if (lastStatus != null) 'lastStatus': lastStatus, + if (lastError != null) 'lastError': lastError, + if (deliveredAt != null) 'deliveredAt': deliveredAt?.toJson(), + if (failedAt != null) 'failedAt': failedAt?.toJson(), + if (nextAttemptAt != null) 'nextAttemptAt': nextAttemptAt?.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationDeliveryView', + 'webhookId': webhookId, + 'type': type, + 'createdAt': createdAt.toJson(), + 'attempts': attempts, + if (lastStatus != null) 'lastStatus': lastStatus, + if (lastError != null) 'lastError': lastError, + if (deliveredAt != null) 'deliveredAt': deliveredAt?.toJson(), + if (failedAt != null) 'failedAt': failedAt?.toJson(), + if (nextAttemptAt != null) 'nextAttemptAt': nextAttemptAt?.toJson(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationDeliveryViewImpl extends PublicationDeliveryView { + _PublicationDeliveryViewImpl({ + required String webhookId, + required String type, + required DateTime createdAt, + required int attempts, + int? lastStatus, + String? lastError, + DateTime? deliveredAt, + DateTime? failedAt, + DateTime? nextAttemptAt, + }) : super._( + webhookId: webhookId, + type: type, + createdAt: createdAt, + attempts: attempts, + lastStatus: lastStatus, + lastError: lastError, + deliveredAt: deliveredAt, + failedAt: failedAt, + nextAttemptAt: nextAttemptAt, + ); + + /// Returns a shallow copy of this [PublicationDeliveryView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationDeliveryView copyWith({ + String? webhookId, + String? type, + DateTime? createdAt, + int? attempts, + Object? lastStatus = _Undefined, + Object? lastError = _Undefined, + DateTime? deliveredAt = const _isc.$UndefinedDateTime(), + DateTime? failedAt = const _isc.$UndefinedDateTime(), + DateTime? nextAttemptAt = const _isc.$UndefinedDateTime(), + }) { + return PublicationDeliveryView( + webhookId: webhookId ?? this.webhookId, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + attempts: attempts ?? this.attempts, + lastStatus: lastStatus is int? ? lastStatus : this.lastStatus, + lastError: lastError is String? ? lastError : this.lastError, + deliveredAt: deliveredAt is _isc.UndefinedSentinel + ? this.deliveredAt + : deliveredAt, + failedAt: failedAt is _isc.UndefinedSentinel ? this.failedAt : failedAt, + nextAttemptAt: nextAttemptAt is _isc.UndefinedSentinel + ? this.nextAttemptAt + : nextAttemptAt, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_field_mode.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_field_mode.dart new file mode 100644 index 00000000..f3819526 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_field_mode.dart @@ -0,0 +1,41 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +/// Whether a submission field is shown and required (specs/18 §8.1). +enum PublicationFieldMode implements _isc.SerializableModel { + off, + optional, + required; + + static PublicationFieldMode fromJson(String name) { + switch (name) { + case 'off': + return PublicationFieldMode.off; + case 'optional': + return PublicationFieldMode.optional; + case 'required': + return PublicationFieldMode.required; + default: + throw ArgumentError( + 'Value "$name" cannot be converted to "PublicationFieldMode"', + ); + } + } + + @override + String toJson() => name; + + @override + String toString() => name; +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_fields.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_fields.dart new file mode 100644 index 00000000..d009104f --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_fields.dart @@ -0,0 +1,157 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_field_mode.dart' + as _i5yv7v4s; + +/// Which submission fields a publication asks for (specs/18 §8.1). The +/// title is always asked for and required. +abstract class PublicationFields + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationFields._({ + required this.summary, + required this.tags, + required this.allowedTags, + required this.coverImage, + required this.authorBio, + required this.note, + }); + + factory PublicationFields({ + required _i5yv7v4s.PublicationFieldMode summary, + required _i5yv7v4s.PublicationFieldMode tags, + required List allowedTags, + required _i5yv7v4s.PublicationFieldMode coverImage, + required _i5yv7v4s.PublicationFieldMode authorBio, + required _i5yv7v4s.PublicationFieldMode note, + }) = _PublicationFieldsImpl; + + factory PublicationFields.fromJson(Map jsonSerialization) { + return PublicationFields( + summary: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['summary'] as String), + ), + tags: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['tags'] as String), + ), + allowedTags: _i8pkqg1o.Protocol().deserialize>( + jsonSerialization['allowedTags'], + ), + coverImage: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['coverImage'] as String), + ), + authorBio: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['authorBio'] as String), + ), + note: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['note'] as String), + ), + ); + } + + _i5yv7v4s.PublicationFieldMode summary; + + _i5yv7v4s.PublicationFieldMode tags; + + /// When not empty, tags must come from this list. + List allowedTags; + + _i5yv7v4s.PublicationFieldMode coverImage; + + _i5yv7v4s.PublicationFieldMode authorBio; + + _i5yv7v4s.PublicationFieldMode note; + + /// Returns a shallow copy of this [PublicationFields] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationFields copyWith({ + _i5yv7v4s.PublicationFieldMode? summary, + _i5yv7v4s.PublicationFieldMode? tags, + List? allowedTags, + _i5yv7v4s.PublicationFieldMode? coverImage, + _i5yv7v4s.PublicationFieldMode? authorBio, + _i5yv7v4s.PublicationFieldMode? note, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationFields', + 'summary': summary.toJson(), + 'tags': tags.toJson(), + 'allowedTags': allowedTags.toJson(), + 'coverImage': coverImage.toJson(), + 'authorBio': authorBio.toJson(), + 'note': note.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationFields', + 'summary': summary.toJson(), + 'tags': tags.toJson(), + 'allowedTags': allowedTags.toJson(), + 'coverImage': coverImage.toJson(), + 'authorBio': authorBio.toJson(), + 'note': note.toJson(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _PublicationFieldsImpl extends PublicationFields { + _PublicationFieldsImpl({ + required _i5yv7v4s.PublicationFieldMode summary, + required _i5yv7v4s.PublicationFieldMode tags, + required List allowedTags, + required _i5yv7v4s.PublicationFieldMode coverImage, + required _i5yv7v4s.PublicationFieldMode authorBio, + required _i5yv7v4s.PublicationFieldMode note, + }) : super._( + summary: summary, + tags: tags, + allowedTags: allowedTags, + coverImage: coverImage, + authorBio: authorBio, + note: note, + ); + + /// Returns a shallow copy of this [PublicationFields] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationFields copyWith({ + _i5yv7v4s.PublicationFieldMode? summary, + _i5yv7v4s.PublicationFieldMode? tags, + List? allowedTags, + _i5yv7v4s.PublicationFieldMode? coverImage, + _i5yv7v4s.PublicationFieldMode? authorBio, + _i5yv7v4s.PublicationFieldMode? note, + }) { + return PublicationFields( + summary: summary ?? this.summary, + tags: tags ?? this.tags, + allowedTags: allowedTags ?? this.allowedTags.map((e0) => e0).toList(), + coverImage: coverImage ?? this.coverImage, + authorBio: authorBio ?? this.authorBio, + note: note ?? this.note, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_input.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_input.dart new file mode 100644 index 00000000..c2be5a54 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_input.dart @@ -0,0 +1,167 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; + +/// Create or update a publication (specs/18 §8.1). +abstract class PublicationInput + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationInput._({ + required this.name, + required this.siteUrl, + required this.webhookUrl, + this.templateItemUuid, + this.termsUrl, + required this.fields, + required this.enabled, + }); + + factory PublicationInput({ + required String name, + required String siteUrl, + required String webhookUrl, + _isc.UuidValue? templateItemUuid, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required bool enabled, + }) = _PublicationInputImpl; + + factory PublicationInput.fromJson(Map jsonSerialization) { + return PublicationInput( + name: jsonSerialization['name'] as String, + siteUrl: jsonSerialization['siteUrl'] as String, + webhookUrl: jsonSerialization['webhookUrl'] as String, + templateItemUuid: jsonSerialization['templateItemUuid'] == null + ? null + : _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['templateItemUuid'], + ), + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _i8pkqg1o.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + enabled: _isc.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + ); + } + + String name; + + String siteUrl; + + String webhookUrl; + + _isc.UuidValue? templateItemUuid; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + bool enabled; + + /// Returns a shallow copy of this [PublicationInput] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationInput copyWith({ + String? name, + String? siteUrl, + String? webhookUrl, + _isc.UuidValue? templateItemUuid = const _isc.$UndefinedUuidValue(), + String? termsUrl, + _i1a71r29.PublicationFields? fields, + bool? enabled, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationInput', + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'enabled': enabled, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationInput', + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJsonForProtocol(), + 'enabled': enabled, + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationInputImpl extends PublicationInput { + _PublicationInputImpl({ + required String name, + required String siteUrl, + required String webhookUrl, + _isc.UuidValue? templateItemUuid, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required bool enabled, + }) : super._( + name: name, + siteUrl: siteUrl, + webhookUrl: webhookUrl, + templateItemUuid: templateItemUuid, + termsUrl: termsUrl, + fields: fields, + enabled: enabled, + ); + + /// Returns a shallow copy of this [PublicationInput] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationInput copyWith({ + String? name, + String? siteUrl, + String? webhookUrl, + _isc.UuidValue? templateItemUuid = const _isc.$UndefinedUuidValue(), + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + bool? enabled, + }) { + return PublicationInput( + name: name ?? this.name, + siteUrl: siteUrl ?? this.siteUrl, + webhookUrl: webhookUrl ?? this.webhookUrl, + templateItemUuid: templateItemUuid is _isc.UndefinedSentinel + ? this.templateItemUuid + : templateItemUuid, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + enabled: enabled ?? this.enabled, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_moderator_view.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_moderator_view.dart new file mode 100644 index 00000000..dc6d852c --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_moderator_view.dart @@ -0,0 +1,96 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +abstract class PublicationModeratorView + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationModeratorView._({ + required this.email, + this.name, + }); + + factory PublicationModeratorView({ + required String email, + String? name, + }) = _PublicationModeratorViewImpl; + + factory PublicationModeratorView.fromJson( + Map jsonSerialization, + ) { + return PublicationModeratorView( + email: jsonSerialization['email'] as String, + name: jsonSerialization['name'] as String?, + ); + } + + String email; + + /// Null while no account has this email. + String? name; + + /// Returns a shallow copy of this [PublicationModeratorView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationModeratorView copyWith({ + String? email, + String? name, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationModeratorView', + 'email': email, + if (name != null) 'name': name, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationModeratorView', + 'email': email, + if (name != null) 'name': name, + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationModeratorViewImpl extends PublicationModeratorView { + _PublicationModeratorViewImpl({ + required String email, + String? name, + }) : super._( + email: email, + name: name, + ); + + /// Returns a shallow copy of this [PublicationModeratorView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationModeratorView copyWith({ + String? email, + Object? name = _Undefined, + }) { + return PublicationModeratorView( + email: email ?? this.email, + name: name is String? ? name : this.name, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_open_submission.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_open_submission.dart new file mode 100644 index 00000000..b59c30e2 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_open_submission.dart @@ -0,0 +1,126 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import '../../../platform/publications/models/submission_status.dart' + as _igclxad1; + +/// A story the caller can continue (specs/18 §3). +abstract class PublicationOpenSubmission + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationOpenSubmission._({ + required this.itemUuid, + required this.name, + required this.status, + required this.updatedAt, + }); + + factory PublicationOpenSubmission({ + required _isc.UuidValue itemUuid, + required String name, + required _igclxad1.SubmissionStatus status, + required DateTime updatedAt, + }) = _PublicationOpenSubmissionImpl; + + factory PublicationOpenSubmission.fromJson( + Map jsonSerialization, + ) { + return PublicationOpenSubmission( + itemUuid: _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['itemUuid'], + ), + name: jsonSerialization['name'] as String, + status: _igclxad1.SubmissionStatus.fromJson( + (jsonSerialization['status'] as String), + ), + updatedAt: _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['updatedAt'], + ), + ); + } + + _isc.UuidValue itemUuid; + + String name; + + _igclxad1.SubmissionStatus status; + + DateTime updatedAt; + + /// Returns a shallow copy of this [PublicationOpenSubmission] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationOpenSubmission copyWith({ + _isc.UuidValue? itemUuid, + String? name, + _igclxad1.SubmissionStatus? status, + DateTime? updatedAt, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationOpenSubmission', + 'itemUuid': itemUuid.toJson(), + 'name': name, + 'status': status.toJson(), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationOpenSubmission', + 'itemUuid': itemUuid.toJson(), + 'name': name, + 'status': status.toJson(), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _PublicationOpenSubmissionImpl extends PublicationOpenSubmission { + _PublicationOpenSubmissionImpl({ + required _isc.UuidValue itemUuid, + required String name, + required _igclxad1.SubmissionStatus status, + required DateTime updatedAt, + }) : super._( + itemUuid: itemUuid, + name: name, + status: status, + updatedAt: updatedAt, + ); + + /// Returns a shallow copy of this [PublicationOpenSubmission] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationOpenSubmission copyWith({ + _isc.UuidValue? itemUuid, + String? name, + _igclxad1.SubmissionStatus? status, + DateTime? updatedAt, + }) { + return PublicationOpenSubmission( + itemUuid: itemUuid ?? this.itemUuid, + name: name ?? this.name, + status: status ?? this.status, + updatedAt: updatedAt ?? this.updatedAt, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_secret.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_secret.dart new file mode 100644 index 00000000..854a6f46 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_secret.dart @@ -0,0 +1,98 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_settings.dart' + as _iyzf06w5; + +/// A secret shown once (specs/18 §8.1): the signing secret at creation or +/// rotation, or an API key. +abstract class PublicationSecret + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationSecret._({ + required this.settings, + required this.secret, + }); + + factory PublicationSecret({ + required _iyzf06w5.PublicationSettings settings, + required String secret, + }) = _PublicationSecretImpl; + + factory PublicationSecret.fromJson(Map jsonSerialization) { + return PublicationSecret( + settings: _i8pkqg1o.Protocol().deserialize<_iyzf06w5.PublicationSettings>( + jsonSerialization['settings'], + ), + secret: jsonSerialization['secret'] as String, + ); + } + + _iyzf06w5.PublicationSettings settings; + + String secret; + + /// Returns a shallow copy of this [PublicationSecret] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationSecret copyWith({ + _iyzf06w5.PublicationSettings? settings, + String? secret, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationSecret', + 'settings': settings.toJson(), + 'secret': secret, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationSecret', + 'settings': settings.toJsonForProtocol(), + 'secret': secret, + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _PublicationSecretImpl extends PublicationSecret { + _PublicationSecretImpl({ + required _iyzf06w5.PublicationSettings settings, + required String secret, + }) : super._( + settings: settings, + secret: secret, + ); + + /// Returns a shallow copy of this [PublicationSecret] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationSecret copyWith({ + _iyzf06w5.PublicationSettings? settings, + String? secret, + }) { + return PublicationSecret( + settings: settings ?? this.settings.copyWith(), + secret: secret ?? this.secret, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/publication_settings.dart b/wonky_client/lib/src/protocol/platform/publications/models/publication_settings.dart new file mode 100644 index 00000000..c21f893a --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/publication_settings.dart @@ -0,0 +1,328 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; +import '../../../platform/publications/models/publication_moderator_view.dart' + as _in8lpp1q; + +/// The owner's view of a publication (specs/18 §8.1). Never holds secrets. +abstract class PublicationSettings + implements _isc.SerializableModel, _isc.ProtocolSerialization { + PublicationSettings._({ + required this.publicId, + required this.name, + required this.siteUrl, + required this.webhookUrl, + this.verifiedHost, + this.verifiedAt, + this.templateItemUuid, + this.templateName, + this.termsUrl, + required this.fields, + required this.moderators, + required this.hasApiKey, + this.apiKeyLast4, + this.previousSecretUntil, + required this.enabled, + required this.contributorLink, + required this.openSubmissionCount, + required this.createdAt, + }); + + factory PublicationSettings({ + required String publicId, + required String name, + required String siteUrl, + required String webhookUrl, + String? verifiedHost, + DateTime? verifiedAt, + _isc.UuidValue? templateItemUuid, + String? templateName, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required List<_in8lpp1q.PublicationModeratorView> moderators, + required bool hasApiKey, + String? apiKeyLast4, + DateTime? previousSecretUntil, + required bool enabled, + required String contributorLink, + required int openSubmissionCount, + required DateTime createdAt, + }) = _PublicationSettingsImpl; + + factory PublicationSettings.fromJson(Map jsonSerialization) { + return PublicationSettings( + publicId: jsonSerialization['publicId'] as String, + name: jsonSerialization['name'] as String, + siteUrl: jsonSerialization['siteUrl'] as String, + webhookUrl: jsonSerialization['webhookUrl'] as String, + verifiedHost: jsonSerialization['verifiedHost'] as String?, + verifiedAt: jsonSerialization['verifiedAt'] == null + ? null + : _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['verifiedAt'], + ), + templateItemUuid: jsonSerialization['templateItemUuid'] == null + ? null + : _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['templateItemUuid'], + ), + templateName: jsonSerialization['templateName'] as String?, + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _i8pkqg1o.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + moderators: _i8pkqg1o.Protocol() + .deserialize>( + jsonSerialization['moderators'], + ), + hasApiKey: _isc.BoolJsonExtension.fromJson( + jsonSerialization['hasApiKey'], + ), + apiKeyLast4: jsonSerialization['apiKeyLast4'] as String?, + previousSecretUntil: jsonSerialization['previousSecretUntil'] == null + ? null + : _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['previousSecretUntil'], + ), + enabled: _isc.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + contributorLink: jsonSerialization['contributorLink'] as String, + openSubmissionCount: jsonSerialization['openSubmissionCount'] as int, + createdAt: _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + ); + } + + String publicId; + + String name; + + String siteUrl; + + String webhookUrl; + + String? verifiedHost; + + DateTime? verifiedAt; + + _isc.UuidValue? templateItemUuid; + + String? templateName; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + List<_in8lpp1q.PublicationModeratorView> moderators; + + bool hasApiKey; + + String? apiKeyLast4; + + /// Set while the previous signing secret still signs. + DateTime? previousSecretUntil; + + bool enabled; + + /// `https:///write/new?publication=`. + String contributorLink; + + /// Submissions in review or with changes requested. + int openSubmissionCount; + + DateTime createdAt; + + /// Returns a shallow copy of this [PublicationSettings] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + PublicationSettings copyWith({ + String? publicId, + String? name, + String? siteUrl, + String? webhookUrl, + String? verifiedHost, + DateTime? verifiedAt = const _isc.$UndefinedDateTime(), + _isc.UuidValue? templateItemUuid = const _isc.$UndefinedUuidValue(), + String? templateName, + String? termsUrl, + _i1a71r29.PublicationFields? fields, + List<_in8lpp1q.PublicationModeratorView>? moderators, + bool? hasApiKey, + String? apiKeyLast4, + DateTime? previousSecretUntil = const _isc.$UndefinedDateTime(), + bool? enabled, + String? contributorLink, + int? openSubmissionCount, + DateTime? createdAt, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationSettings', + 'publicId': publicId, + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (verifiedHost != null) 'verifiedHost': verifiedHost, + if (verifiedAt != null) 'verifiedAt': verifiedAt?.toJson(), + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (templateName != null) 'templateName': templateName, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'moderators': moderators.toJson(valueToJson: (v) => v.toJson()), + 'hasApiKey': hasApiKey, + if (apiKeyLast4 != null) 'apiKeyLast4': apiKeyLast4, + if (previousSecretUntil != null) + 'previousSecretUntil': previousSecretUntil?.toJson(), + 'enabled': enabled, + 'contributorLink': contributorLink, + 'openSubmissionCount': openSubmissionCount, + 'createdAt': createdAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationSettings', + 'publicId': publicId, + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (verifiedHost != null) 'verifiedHost': verifiedHost, + if (verifiedAt != null) 'verifiedAt': verifiedAt?.toJson(), + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (templateName != null) 'templateName': templateName, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJsonForProtocol(), + 'moderators': moderators.toJson( + valueToJson: (v) => v.toJsonForProtocol(), + ), + 'hasApiKey': hasApiKey, + if (apiKeyLast4 != null) 'apiKeyLast4': apiKeyLast4, + if (previousSecretUntil != null) + 'previousSecretUntil': previousSecretUntil?.toJson(), + 'enabled': enabled, + 'contributorLink': contributorLink, + 'openSubmissionCount': openSubmissionCount, + 'createdAt': createdAt.toJson(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationSettingsImpl extends PublicationSettings { + _PublicationSettingsImpl({ + required String publicId, + required String name, + required String siteUrl, + required String webhookUrl, + String? verifiedHost, + DateTime? verifiedAt, + _isc.UuidValue? templateItemUuid, + String? templateName, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required List<_in8lpp1q.PublicationModeratorView> moderators, + required bool hasApiKey, + String? apiKeyLast4, + DateTime? previousSecretUntil, + required bool enabled, + required String contributorLink, + required int openSubmissionCount, + required DateTime createdAt, + }) : super._( + publicId: publicId, + name: name, + siteUrl: siteUrl, + webhookUrl: webhookUrl, + verifiedHost: verifiedHost, + verifiedAt: verifiedAt, + templateItemUuid: templateItemUuid, + templateName: templateName, + termsUrl: termsUrl, + fields: fields, + moderators: moderators, + hasApiKey: hasApiKey, + apiKeyLast4: apiKeyLast4, + previousSecretUntil: previousSecretUntil, + enabled: enabled, + contributorLink: contributorLink, + openSubmissionCount: openSubmissionCount, + createdAt: createdAt, + ); + + /// Returns a shallow copy of this [PublicationSettings] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + PublicationSettings copyWith({ + String? publicId, + String? name, + String? siteUrl, + String? webhookUrl, + Object? verifiedHost = _Undefined, + DateTime? verifiedAt = const _isc.$UndefinedDateTime(), + _isc.UuidValue? templateItemUuid = const _isc.$UndefinedUuidValue(), + Object? templateName = _Undefined, + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + List<_in8lpp1q.PublicationModeratorView>? moderators, + bool? hasApiKey, + Object? apiKeyLast4 = _Undefined, + DateTime? previousSecretUntil = const _isc.$UndefinedDateTime(), + bool? enabled, + String? contributorLink, + int? openSubmissionCount, + DateTime? createdAt, + }) { + return PublicationSettings( + publicId: publicId ?? this.publicId, + name: name ?? this.name, + siteUrl: siteUrl ?? this.siteUrl, + webhookUrl: webhookUrl ?? this.webhookUrl, + verifiedHost: verifiedHost is String? ? verifiedHost : this.verifiedHost, + verifiedAt: verifiedAt is _isc.UndefinedSentinel + ? this.verifiedAt + : verifiedAt, + templateItemUuid: templateItemUuid is _isc.UndefinedSentinel + ? this.templateItemUuid + : templateItemUuid, + templateName: templateName is String? ? templateName : this.templateName, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + moderators: + moderators ?? this.moderators.map((e0) => e0.copyWith()).toList(), + hasApiKey: hasApiKey ?? this.hasApiKey, + apiKeyLast4: apiKeyLast4 is String? ? apiKeyLast4 : this.apiKeyLast4, + previousSecretUntil: previousSecretUntil is _isc.UndefinedSentinel + ? this.previousSecretUntil + : previousSecretUntil, + enabled: enabled ?? this.enabled, + contributorLink: contributorLink ?? this.contributorLink, + openSubmissionCount: openSubmissionCount ?? this.openSubmissionCount, + createdAt: createdAt ?? this.createdAt, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/submission_delivery_state.dart b/wonky_client/lib/src/protocol/platform/publications/models/submission_delivery_state.dart new file mode 100644 index 00000000..94dabbd3 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/submission_delivery_state.dart @@ -0,0 +1,41 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +/// State of the last submit's webhook delivery (specs/18 §7.2). +enum SubmissionDeliveryState implements _isc.SerializableModel { + /// Not accepted yet; the outbox retries. + pending, + + /// Every retry failed. + failed; + + static SubmissionDeliveryState fromJson(String name) { + switch (name) { + case 'pending': + return SubmissionDeliveryState.pending; + case 'failed': + return SubmissionDeliveryState.failed; + default: + throw ArgumentError( + 'Value "$name" cannot be converted to "SubmissionDeliveryState"', + ); + } + } + + @override + String toJson() => name; + + @override + String toString() => name; +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/submission_revision_view.dart b/wonky_client/lib/src/protocol/platform/publications/models/submission_revision_view.dart new file mode 100644 index 00000000..77e64363 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/submission_revision_view.dart @@ -0,0 +1,134 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +abstract class SubmissionRevisionView + implements _isc.SerializableModel, _isc.ProtocolSerialization { + SubmissionRevisionView._({ + required this.sequence, + required this.revision, + required this.submittedByName, + required this.submittedAt, + this.versionId, + }); + + factory SubmissionRevisionView({ + required int sequence, + required int revision, + required String submittedByName, + required DateTime submittedAt, + int? versionId, + }) = _SubmissionRevisionViewImpl; + + factory SubmissionRevisionView.fromJson( + Map jsonSerialization, + ) { + return SubmissionRevisionView( + sequence: jsonSerialization['sequence'] as int, + revision: jsonSerialization['revision'] as int, + submittedByName: jsonSerialization['submittedByName'] as String, + submittedAt: _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['submittedAt'], + ), + versionId: jsonSerialization['versionId'] as int?, + ); + } + + int sequence; + + int revision; + + String submittedByName; + + DateTime submittedAt; + + /// The named version of this submit, when it still exists. + int? versionId; + + /// Returns a shallow copy of this [SubmissionRevisionView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + SubmissionRevisionView copyWith({ + int? sequence, + int? revision, + String? submittedByName, + DateTime? submittedAt, + int? versionId, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionRevisionView', + 'sequence': sequence, + 'revision': revision, + 'submittedByName': submittedByName, + 'submittedAt': submittedAt.toJson(), + if (versionId != null) 'versionId': versionId, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionRevisionView', + 'sequence': sequence, + 'revision': revision, + 'submittedByName': submittedByName, + 'submittedAt': submittedAt.toJson(), + if (versionId != null) 'versionId': versionId, + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionRevisionViewImpl extends SubmissionRevisionView { + _SubmissionRevisionViewImpl({ + required int sequence, + required int revision, + required String submittedByName, + required DateTime submittedAt, + int? versionId, + }) : super._( + sequence: sequence, + revision: revision, + submittedByName: submittedByName, + submittedAt: submittedAt, + versionId: versionId, + ); + + /// Returns a shallow copy of this [SubmissionRevisionView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + SubmissionRevisionView copyWith({ + int? sequence, + int? revision, + String? submittedByName, + DateTime? submittedAt, + Object? versionId = _Undefined, + }) { + return SubmissionRevisionView( + sequence: sequence ?? this.sequence, + revision: revision ?? this.revision, + submittedByName: submittedByName ?? this.submittedByName, + submittedAt: submittedAt ?? this.submittedAt, + versionId: versionId is int? ? versionId : this.versionId, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/submission_started.dart b/wonky_client/lib/src/protocol/platform/publications/models/submission_started.dart new file mode 100644 index 00000000..ad654d81 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/submission_started.dart @@ -0,0 +1,70 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +/// Result of starting a story (specs/18 §3 step 3). +abstract class SubmissionStarted + implements _isc.SerializableModel, _isc.ProtocolSerialization { + SubmissionStarted._({required this.itemUuid}); + + factory SubmissionStarted({required _isc.UuidValue itemUuid}) = + _SubmissionStartedImpl; + + factory SubmissionStarted.fromJson(Map jsonSerialization) { + return SubmissionStarted( + itemUuid: _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['itemUuid'], + ), + ); + } + + _isc.UuidValue itemUuid; + + /// Returns a shallow copy of this [SubmissionStarted] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + SubmissionStarted copyWith({_isc.UuidValue? itemUuid}); + @override + Map toJson() { + return { + '__className__': 'SubmissionStarted', + 'itemUuid': itemUuid.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionStarted', + 'itemUuid': itemUuid.toJson(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _SubmissionStartedImpl extends SubmissionStarted { + _SubmissionStartedImpl({required _isc.UuidValue itemUuid}) + : super._(itemUuid: itemUuid); + + /// Returns a shallow copy of this [SubmissionStarted] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + SubmissionStarted copyWith({_isc.UuidValue? itemUuid}) { + return SubmissionStarted(itemUuid: itemUuid ?? this.itemUuid); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/submission_status.dart b/wonky_client/lib/src/protocol/platform/publications/models/submission_status.dart new file mode 100644 index 00000000..029857a5 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/submission_status.dart @@ -0,0 +1,53 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; + +/// Lifecycle of a submission (specs/18 §2.1). +enum SubmissionStatus implements _isc.SerializableModel { + /// Started from the link, never submitted. + draft, + inReview, + changesRequested, + + /// Final for this submission. + declined, + published, + withdrawn; + + static SubmissionStatus fromJson(String name) { + switch (name) { + case 'draft': + return SubmissionStatus.draft; + case 'inReview': + return SubmissionStatus.inReview; + case 'changesRequested': + return SubmissionStatus.changesRequested; + case 'declined': + return SubmissionStatus.declined; + case 'published': + return SubmissionStatus.published; + case 'withdrawn': + return SubmissionStatus.withdrawn; + default: + throw ArgumentError( + 'Value "$name" cannot be converted to "SubmissionStatus"', + ); + } + } + + @override + String toJson() => name; + + @override + String toString() => name; +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/submission_values.dart b/wonky_client/lib/src/protocol/platform/publications/models/submission_values.dart new file mode 100644 index 00000000..b7458b5f --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/submission_values.dart @@ -0,0 +1,152 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; + +/// The fields a contributor filled in (specs/18 §4.2). +abstract class SubmissionValues + implements _isc.SerializableModel, _isc.ProtocolSerialization { + SubmissionValues._({ + required this.title, + this.summary, + required this.tags, + this.coverImage, + this.authorBio, + this.note, + }); + + factory SubmissionValues({ + required String title, + String? summary, + required List tags, + _isc.UuidValue? coverImage, + String? authorBio, + String? note, + }) = _SubmissionValuesImpl; + + factory SubmissionValues.fromJson(Map jsonSerialization) { + return SubmissionValues( + title: jsonSerialization['title'] as String, + summary: jsonSerialization['summary'] as String?, + tags: _i8pkqg1o.Protocol().deserialize>( + jsonSerialization['tags'], + ), + coverImage: jsonSerialization['coverImage'] == null + ? null + : _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['coverImage'], + ), + authorBio: jsonSerialization['authorBio'] as String?, + note: jsonSerialization['note'] as String?, + ); + } + + String title; + + String? summary; + + List tags; + + /// A `wonky-file` uuid of an image in the document. + _isc.UuidValue? coverImage; + + String? authorBio; + + String? note; + + /// Returns a shallow copy of this [SubmissionValues] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + SubmissionValues copyWith({ + String? title, + String? summary, + List? tags, + _isc.UuidValue? coverImage = const _isc.$UndefinedUuidValue(), + String? authorBio, + String? note, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionValues', + 'title': title, + if (summary != null) 'summary': summary, + 'tags': tags.toJson(), + if (coverImage != null) 'coverImage': coverImage?.toJson(), + if (authorBio != null) 'authorBio': authorBio, + if (note != null) 'note': note, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionValues', + 'title': title, + if (summary != null) 'summary': summary, + 'tags': tags.toJson(), + if (coverImage != null) 'coverImage': coverImage?.toJson(), + if (authorBio != null) 'authorBio': authorBio, + if (note != null) 'note': note, + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionValuesImpl extends SubmissionValues { + _SubmissionValuesImpl({ + required String title, + String? summary, + required List tags, + _isc.UuidValue? coverImage, + String? authorBio, + String? note, + }) : super._( + title: title, + summary: summary, + tags: tags, + coverImage: coverImage, + authorBio: authorBio, + note: note, + ); + + /// Returns a shallow copy of this [SubmissionValues] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + SubmissionValues copyWith({ + String? title, + Object? summary = _Undefined, + List? tags, + _isc.UuidValue? coverImage = const _isc.$UndefinedUuidValue(), + Object? authorBio = _Undefined, + Object? note = _Undefined, + }) { + return SubmissionValues( + title: title ?? this.title, + summary: summary is String? ? summary : this.summary, + tags: tags ?? this.tags.map((e0) => e0).toList(), + coverImage: coverImage is _isc.UndefinedSentinel + ? this.coverImage + : coverImage, + authorBio: authorBio is String? ? authorBio : this.authorBio, + note: note is String? ? note : this.note, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/publications/models/submission_view.dart b/wonky_client/lib/src/protocol/platform/publications/models/submission_view.dart new file mode 100644 index 00000000..3249e395 --- /dev/null +++ b/wonky_client/lib/src/protocol/platform/publications/models/submission_view.dart @@ -0,0 +1,368 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod_client/serverpod_client.dart' as _isc; +import 'package:wonky_client/src/protocol/protocol.dart' as _i8pkqg1o; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; +import '../../../platform/publications/models/submission_delivery_state.dart' + as _ifp7j30v; +import '../../../platform/publications/models/submission_revision_view.dart' + as _idtrp1yl; +import '../../../platform/publications/models/submission_status.dart' + as _igclxad1; +import '../../../platform/publications/models/submission_values.dart' + as _igthguer; + +/// A document's submission as editors and moderators see it (specs/18 §4). +abstract class SubmissionView + implements _isc.SerializableModel, _isc.ProtocolSerialization { + SubmissionView._({ + required this.id, + required this.itemUuid, + required this.status, + this.delivery, + required this.publicationId, + required this.publicationName, + required this.shownHost, + required this.verified, + required this.accepting, + required this.fields, + this.termsUrl, + required this.consentNeeded, + required this.values, + this.publicUrl, + this.feedbackThreadUuid, + this.lastMessage, + this.lastMessageAt, + this.lastSubmittedRevision, + required this.revisions, + required this.updatedAt, + }); + + factory SubmissionView({ + required String id, + required _isc.UuidValue itemUuid, + required _igclxad1.SubmissionStatus status, + _ifp7j30v.SubmissionDeliveryState? delivery, + required String publicationId, + required String publicationName, + required String shownHost, + required bool verified, + required bool accepting, + required _i1a71r29.PublicationFields fields, + String? termsUrl, + required bool consentNeeded, + required _igthguer.SubmissionValues values, + String? publicUrl, + _isc.UuidValue? feedbackThreadUuid, + String? lastMessage, + DateTime? lastMessageAt, + int? lastSubmittedRevision, + required List<_idtrp1yl.SubmissionRevisionView> revisions, + required DateTime updatedAt, + }) = _SubmissionViewImpl; + + factory SubmissionView.fromJson(Map jsonSerialization) { + return SubmissionView( + id: jsonSerialization['id'] as String, + itemUuid: _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['itemUuid'], + ), + status: _igclxad1.SubmissionStatus.fromJson( + (jsonSerialization['status'] as String), + ), + delivery: jsonSerialization['delivery'] == null + ? null + : _ifp7j30v.SubmissionDeliveryState.fromJson( + (jsonSerialization['delivery'] as String), + ), + publicationId: jsonSerialization['publicationId'] as String, + publicationName: jsonSerialization['publicationName'] as String, + shownHost: jsonSerialization['shownHost'] as String, + verified: _isc.BoolJsonExtension.fromJson(jsonSerialization['verified']), + accepting: _isc.BoolJsonExtension.fromJson( + jsonSerialization['accepting'], + ), + fields: _i8pkqg1o.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + termsUrl: jsonSerialization['termsUrl'] as String?, + consentNeeded: _isc.BoolJsonExtension.fromJson( + jsonSerialization['consentNeeded'], + ), + values: _i8pkqg1o.Protocol().deserialize<_igthguer.SubmissionValues>( + jsonSerialization['values'], + ), + publicUrl: jsonSerialization['publicUrl'] as String?, + feedbackThreadUuid: jsonSerialization['feedbackThreadUuid'] == null + ? null + : _isc.UuidValueJsonExtension.fromJson( + jsonSerialization['feedbackThreadUuid'], + ), + lastMessage: jsonSerialization['lastMessage'] as String?, + lastMessageAt: jsonSerialization['lastMessageAt'] == null + ? null + : _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['lastMessageAt'], + ), + lastSubmittedRevision: jsonSerialization['lastSubmittedRevision'] as int?, + revisions: _i8pkqg1o.Protocol() + .deserialize>( + jsonSerialization['revisions'], + ), + updatedAt: _isc.DateTimeJsonExtension.fromJson( + jsonSerialization['updatedAt'], + ), + ); + } + + /// "sub_". + String id; + + _isc.UuidValue itemUuid; + + _igclxad1.SubmissionStatus status; + + _ifp7j30v.SubmissionDeliveryState? delivery; + + String publicationId; + + String publicationName; + + String shownHost; + + bool verified; + + /// The publication still takes submissions (enabled, caller not blocked). + bool accepting; + + _i1a71r29.PublicationFields fields; + + String? termsUrl; + + /// The caller still has to agree to the terms before submitting. + bool consentNeeded; + + _igthguer.SubmissionValues values; + + String? publicUrl; + + _isc.UuidValue? feedbackThreadUuid; + + /// The publication's last message (Markdown) and when it came. + String? lastMessage; + + DateTime? lastMessageAt; + + /// The document revision of the last submit (null before the first). + int? lastSubmittedRevision; + + List<_idtrp1yl.SubmissionRevisionView> revisions; + + DateTime updatedAt; + + /// Returns a shallow copy of this [SubmissionView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + SubmissionView copyWith({ + String? id, + _isc.UuidValue? itemUuid, + _igclxad1.SubmissionStatus? status, + _ifp7j30v.SubmissionDeliveryState? delivery, + String? publicationId, + String? publicationName, + String? shownHost, + bool? verified, + bool? accepting, + _i1a71r29.PublicationFields? fields, + String? termsUrl, + bool? consentNeeded, + _igthguer.SubmissionValues? values, + String? publicUrl, + _isc.UuidValue? feedbackThreadUuid = const _isc.$UndefinedUuidValue(), + String? lastMessage, + DateTime? lastMessageAt = const _isc.$UndefinedDateTime(), + int? lastSubmittedRevision, + List<_idtrp1yl.SubmissionRevisionView>? revisions, + DateTime? updatedAt, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionView', + 'id': id, + 'itemUuid': itemUuid.toJson(), + 'status': status.toJson(), + if (delivery != null) 'delivery': delivery?.toJson(), + 'publicationId': publicationId, + 'publicationName': publicationName, + 'shownHost': shownHost, + 'verified': verified, + 'accepting': accepting, + 'fields': fields.toJson(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'consentNeeded': consentNeeded, + 'values': values.toJson(), + if (publicUrl != null) 'publicUrl': publicUrl, + if (feedbackThreadUuid != null) + 'feedbackThreadUuid': feedbackThreadUuid?.toJson(), + if (lastMessage != null) 'lastMessage': lastMessage, + if (lastMessageAt != null) 'lastMessageAt': lastMessageAt?.toJson(), + if (lastSubmittedRevision != null) + 'lastSubmittedRevision': lastSubmittedRevision, + 'revisions': revisions.toJson(valueToJson: (v) => v.toJson()), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionView', + 'id': id, + 'itemUuid': itemUuid.toJson(), + 'status': status.toJson(), + if (delivery != null) 'delivery': delivery?.toJson(), + 'publicationId': publicationId, + 'publicationName': publicationName, + 'shownHost': shownHost, + 'verified': verified, + 'accepting': accepting, + 'fields': fields.toJsonForProtocol(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'consentNeeded': consentNeeded, + 'values': values.toJsonForProtocol(), + if (publicUrl != null) 'publicUrl': publicUrl, + if (feedbackThreadUuid != null) + 'feedbackThreadUuid': feedbackThreadUuid?.toJson(), + if (lastMessage != null) 'lastMessage': lastMessage, + if (lastMessageAt != null) 'lastMessageAt': lastMessageAt?.toJson(), + if (lastSubmittedRevision != null) + 'lastSubmittedRevision': lastSubmittedRevision, + 'revisions': revisions.toJson(valueToJson: (v) => v.toJsonForProtocol()), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + String toString() { + return _isc.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionViewImpl extends SubmissionView { + _SubmissionViewImpl({ + required String id, + required _isc.UuidValue itemUuid, + required _igclxad1.SubmissionStatus status, + _ifp7j30v.SubmissionDeliveryState? delivery, + required String publicationId, + required String publicationName, + required String shownHost, + required bool verified, + required bool accepting, + required _i1a71r29.PublicationFields fields, + String? termsUrl, + required bool consentNeeded, + required _igthguer.SubmissionValues values, + String? publicUrl, + _isc.UuidValue? feedbackThreadUuid, + String? lastMessage, + DateTime? lastMessageAt, + int? lastSubmittedRevision, + required List<_idtrp1yl.SubmissionRevisionView> revisions, + required DateTime updatedAt, + }) : super._( + id: id, + itemUuid: itemUuid, + status: status, + delivery: delivery, + publicationId: publicationId, + publicationName: publicationName, + shownHost: shownHost, + verified: verified, + accepting: accepting, + fields: fields, + termsUrl: termsUrl, + consentNeeded: consentNeeded, + values: values, + publicUrl: publicUrl, + feedbackThreadUuid: feedbackThreadUuid, + lastMessage: lastMessage, + lastMessageAt: lastMessageAt, + lastSubmittedRevision: lastSubmittedRevision, + revisions: revisions, + updatedAt: updatedAt, + ); + + /// Returns a shallow copy of this [SubmissionView] + /// with some or all fields replaced by the given arguments. + @_isc.useResult + @override + SubmissionView copyWith({ + String? id, + _isc.UuidValue? itemUuid, + _igclxad1.SubmissionStatus? status, + Object? delivery = _Undefined, + String? publicationId, + String? publicationName, + String? shownHost, + bool? verified, + bool? accepting, + _i1a71r29.PublicationFields? fields, + Object? termsUrl = _Undefined, + bool? consentNeeded, + _igthguer.SubmissionValues? values, + Object? publicUrl = _Undefined, + _isc.UuidValue? feedbackThreadUuid = const _isc.$UndefinedUuidValue(), + Object? lastMessage = _Undefined, + DateTime? lastMessageAt = const _isc.$UndefinedDateTime(), + Object? lastSubmittedRevision = _Undefined, + List<_idtrp1yl.SubmissionRevisionView>? revisions, + DateTime? updatedAt, + }) { + return SubmissionView( + id: id ?? this.id, + itemUuid: itemUuid ?? this.itemUuid, + status: status ?? this.status, + delivery: delivery is _ifp7j30v.SubmissionDeliveryState? + ? delivery + : this.delivery, + publicationId: publicationId ?? this.publicationId, + publicationName: publicationName ?? this.publicationName, + shownHost: shownHost ?? this.shownHost, + verified: verified ?? this.verified, + accepting: accepting ?? this.accepting, + fields: fields ?? this.fields.copyWith(), + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + consentNeeded: consentNeeded ?? this.consentNeeded, + values: values ?? this.values.copyWith(), + publicUrl: publicUrl is String? ? publicUrl : this.publicUrl, + feedbackThreadUuid: feedbackThreadUuid is _isc.UndefinedSentinel + ? this.feedbackThreadUuid + : feedbackThreadUuid, + lastMessage: lastMessage is String? ? lastMessage : this.lastMessage, + lastMessageAt: lastMessageAt is _isc.UndefinedSentinel + ? this.lastMessageAt + : lastMessageAt, + lastSubmittedRevision: lastSubmittedRevision is int? + ? lastSubmittedRevision + : this.lastSubmittedRevision, + revisions: + revisions ?? this.revisions.map((e0) => e0.copyWith()).toList(), + updatedAt: updatedAt ?? this.updatedAt, + ); + } +} diff --git a/wonky_client/lib/src/protocol/platform/sharing/drive_item_permission.dart b/wonky_client/lib/src/protocol/platform/sharing/drive_item_permission.dart index 58631b1b..c8f78458 100644 --- a/wonky_client/lib/src/protocol/platform/sharing/drive_item_permission.dart +++ b/wonky_client/lib/src/protocol/platform/sharing/drive_item_permission.dart @@ -27,6 +27,7 @@ abstract class DriveItemPermission required this.grantedById, required this.grantedAt, this.expiresAt, + this.viaPublicationId, }); factory DriveItemPermission({ @@ -39,6 +40,7 @@ abstract class DriveItemPermission required int grantedById, required DateTime grantedAt, DateTime? expiresAt, + int? viaPublicationId, }) = _DriveItemPermissionImpl; factory DriveItemPermission.fromJson(Map jsonSerialization) { @@ -58,6 +60,7 @@ abstract class DriveItemPermission expiresAt: jsonSerialization['expiresAt'] == null ? null : _isc.DateTimeJsonExtension.fromJson(jsonSerialization['expiresAt']), + viaPublicationId: jsonSerialization['viaPublicationId'] as int?, ); } @@ -84,6 +87,9 @@ abstract class DriveItemPermission DateTime? expiresAt; + /// (M14) Moderator grant of a submission (specs/18 §5.1); removed with it. + int? viaPublicationId; + /// Returns a shallow copy of this [DriveItemPermission] /// with some or all fields replaced by the given arguments. @_isc.useResult @@ -97,6 +103,7 @@ abstract class DriveItemPermission int? grantedById, DateTime? grantedAt, DateTime? expiresAt = const _isc.$UndefinedDateTime(), + int? viaPublicationId, }); @override Map toJson() { @@ -111,6 +118,7 @@ abstract class DriveItemPermission 'grantedById': grantedById, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublicationId != null) 'viaPublicationId': viaPublicationId, }; } @@ -127,6 +135,7 @@ abstract class DriveItemPermission 'grantedById': grantedById, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublicationId != null) 'viaPublicationId': viaPublicationId, }; } @@ -149,6 +158,7 @@ class _DriveItemPermissionImpl extends DriveItemPermission { required int grantedById, required DateTime grantedAt, DateTime? expiresAt, + int? viaPublicationId, }) : super._( id: id, itemId: itemId, @@ -159,6 +169,7 @@ class _DriveItemPermissionImpl extends DriveItemPermission { grantedById: grantedById, grantedAt: grantedAt, expiresAt: expiresAt, + viaPublicationId: viaPublicationId, ); /// Returns a shallow copy of this [DriveItemPermission] @@ -175,6 +186,7 @@ class _DriveItemPermissionImpl extends DriveItemPermission { int? grantedById, DateTime? grantedAt, DateTime? expiresAt = const _isc.$UndefinedDateTime(), + Object? viaPublicationId = _Undefined, }) { return DriveItemPermission( id: id is int? ? id : this.id, @@ -190,6 +202,9 @@ class _DriveItemPermissionImpl extends DriveItemPermission { expiresAt: expiresAt is _isc.UndefinedSentinel ? this.expiresAt : expiresAt, + viaPublicationId: viaPublicationId is int? + ? viaPublicationId + : this.viaPublicationId, ); } } diff --git a/wonky_client/lib/src/protocol/platform/sharing/permission_view.dart b/wonky_client/lib/src/protocol/platform/sharing/permission_view.dart index bdf37bd9..e56a2abc 100644 --- a/wonky_client/lib/src/protocol/platform/sharing/permission_view.dart +++ b/wonky_client/lib/src/protocol/platform/sharing/permission_view.dart @@ -25,6 +25,7 @@ abstract class PermissionView this.inheritedFromName, required this.grantedAt, this.expiresAt, + this.viaPublication, }); factory PermissionView({ @@ -35,6 +36,7 @@ abstract class PermissionView String? inheritedFromName, required DateTime grantedAt, DateTime? expiresAt, + String? viaPublication, }) = _PermissionViewImpl; factory PermissionView.fromJson(Map jsonSerialization) { @@ -60,6 +62,7 @@ abstract class PermissionView expiresAt: jsonSerialization['expiresAt'] == null ? null : _isc.DateTimeJsonExtension.fromJson(jsonSerialization['expiresAt']), + viaPublication: jsonSerialization['viaPublication'] as String?, ); } @@ -79,6 +82,9 @@ abstract class PermissionView DateTime? expiresAt; + /// (M14) The publication a moderator grant comes from (specs/18 §5.1). + String? viaPublication; + /// Returns a shallow copy of this [PermissionView] /// with some or all fields replaced by the given arguments. @_isc.useResult @@ -90,6 +96,7 @@ abstract class PermissionView String? inheritedFromName, DateTime? grantedAt, DateTime? expiresAt = const _isc.$UndefinedDateTime(), + String? viaPublication, }); @override Map toJson() { @@ -103,6 +110,7 @@ abstract class PermissionView if (inheritedFromName != null) 'inheritedFromName': inheritedFromName, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublication != null) 'viaPublication': viaPublication, }; } @@ -118,6 +126,7 @@ abstract class PermissionView if (inheritedFromName != null) 'inheritedFromName': inheritedFromName, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublication != null) 'viaPublication': viaPublication, }; } @@ -143,6 +152,7 @@ class _PermissionViewImpl extends PermissionView { String? inheritedFromName, required DateTime grantedAt, DateTime? expiresAt, + String? viaPublication, }) : super._( user: user, invitedEmail: invitedEmail, @@ -151,6 +161,7 @@ class _PermissionViewImpl extends PermissionView { inheritedFromName: inheritedFromName, grantedAt: grantedAt, expiresAt: expiresAt, + viaPublication: viaPublication, ); /// Returns a shallow copy of this [PermissionView] @@ -165,6 +176,7 @@ class _PermissionViewImpl extends PermissionView { Object? inheritedFromName = _Undefined, DateTime? grantedAt, DateTime? expiresAt = const _isc.$UndefinedDateTime(), + Object? viaPublication = _Undefined, }) { return PermissionView( user: user is _isc.UndefinedSentinel ? this.user?.copyWith() : user, @@ -180,6 +192,9 @@ class _PermissionViewImpl extends PermissionView { expiresAt: expiresAt is _isc.UndefinedSentinel ? this.expiresAt : expiresAt, + viaPublication: viaPublication is String? + ? viaPublication + : this.viaPublication, ); } } diff --git a/wonky_client/lib/src/protocol/protocol.dart b/wonky_client/lib/src/protocol/protocol.dart index 808f32a1..93e58340 100644 --- a/wonky_client/lib/src/protocol/protocol.dart +++ b/wonky_client/lib/src/protocol/protocol.dart @@ -38,6 +38,10 @@ import 'package:wonky_client/src/protocol/platform/drive/template_view.dart' as _i1pzk6fp; import 'package:wonky_client/src/protocol/platform/files/file_url_view.dart' as _i4i1hokq; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_delivery_view.dart' + as _ipl2ldhs; +import 'package:wonky_client/src/protocol/platform/publications/models/publication_settings.dart' + as _i9bruko9; import 'package:wonky_client/src/protocol/platform/revlog/models/rev_op_view.dart' as _iq15rk0l; import 'package:wonky_client/src/protocol/platform/users/access_token_view.dart' @@ -197,6 +201,28 @@ import 'platform/presence/participant.dart' as _iylgyc33; import 'platform/presence/presence_event.dart' as _i8r9afjv; import 'platform/presence/presence_state.dart' as _ik055xb9; import 'platform/presence/presence_update.dart' as _isz2sju0; +import 'platform/publications/models/publication_card.dart' as _i9g6l3wu; +import 'platform/publications/models/publication_check_result.dart' + as _i0a1sw0a; +import 'platform/publications/models/publication_delivery_view.dart' + as _iz1gego0; +import 'platform/publications/models/publication_field_mode.dart' as _iucp51pg; +import 'platform/publications/models/publication_fields.dart' as _i63wbtw0; +import 'platform/publications/models/publication_input.dart' as _iv6bey6s; +import 'platform/publications/models/publication_moderator_view.dart' + as _ij9tsbn9; +import 'platform/publications/models/publication_open_submission.dart' + as _ivvukfve; +import 'platform/publications/models/publication_secret.dart' as _iyqlj2kr; +import 'platform/publications/models/publication_settings.dart' as _i5i48220; +import 'platform/publications/models/submission_delivery_state.dart' + as _ip6l83ta; +import 'platform/publications/models/submission_revision_view.dart' + as _iegijpud; +import 'platform/publications/models/submission_started.dart' as _ijb8v3k4; +import 'platform/publications/models/submission_status.dart' as _i7hbulg4; +import 'platform/publications/models/submission_values.dart' as _iq9uje8l; +import 'platform/publications/models/submission_view.dart' as _iakndug7; import 'platform/revlog/messages/rev_client_message.dart' as _i6ck957q; import 'platform/revlog/messages/rev_server_message.dart' as _ie6clghy; import 'platform/revlog/models/rev_file_info.dart' as _ihwy023l; @@ -450,6 +476,22 @@ export 'platform/presence/participant.dart'; export 'platform/presence/presence_event.dart'; export 'platform/presence/presence_state.dart'; export 'platform/presence/presence_update.dart'; +export 'platform/publications/models/publication_card.dart'; +export 'platform/publications/models/publication_check_result.dart'; +export 'platform/publications/models/publication_delivery_view.dart'; +export 'platform/publications/models/publication_field_mode.dart'; +export 'platform/publications/models/publication_fields.dart'; +export 'platform/publications/models/publication_input.dart'; +export 'platform/publications/models/publication_moderator_view.dart'; +export 'platform/publications/models/publication_open_submission.dart'; +export 'platform/publications/models/publication_secret.dart'; +export 'platform/publications/models/publication_settings.dart'; +export 'platform/publications/models/submission_delivery_state.dart'; +export 'platform/publications/models/submission_revision_view.dart'; +export 'platform/publications/models/submission_started.dart'; +export 'platform/publications/models/submission_status.dart'; +export 'platform/publications/models/submission_values.dart'; +export 'platform/publications/models/submission_view.dart'; export 'platform/revlog/messages/rev_client_message.dart'; export 'platform/revlog/messages/rev_server_message.dart'; export 'platform/revlog/models/rev_file_info.dart'; @@ -730,6 +772,22 @@ class Protocol extends _isc.SerializationManager _isc.getType<_i8r9afjv.PresenceUpdated>, _isc.getType<_ik055xb9.PresenceState>, _isc.getType<_isz2sju0.PresenceUpdate>, + _isc.getType<_i9g6l3wu.PublicationCard>, + _isc.getType<_i0a1sw0a.PublicationCheckResult>, + _isc.getType<_iz1gego0.PublicationDeliveryView>, + _isc.getType<_iucp51pg.PublicationFieldMode>, + _isc.getType<_i63wbtw0.PublicationFields>, + _isc.getType<_iv6bey6s.PublicationInput>, + _isc.getType<_ij9tsbn9.PublicationModeratorView>, + _isc.getType<_ivvukfve.PublicationOpenSubmission>, + _isc.getType<_iyqlj2kr.PublicationSecret>, + _isc.getType<_i5i48220.PublicationSettings>, + _isc.getType<_ip6l83ta.SubmissionDeliveryState>, + _isc.getType<_iegijpud.SubmissionRevisionView>, + _isc.getType<_ijb8v3k4.SubmissionStarted>, + _isc.getType<_i7hbulg4.SubmissionStatus>, + _isc.getType<_iq9uje8l.SubmissionValues>, + _isc.getType<_iakndug7.SubmissionView>, _isc.getType<_ie6clghy.RevAck>, _isc.getType<_i6ck957q.RevPing>, _isc.getType<_i6ck957q.RevRequestOps>, @@ -1030,6 +1088,22 @@ class Protocol extends _isc.SerializationManager _isc.getType<_i8r9afjv.PresenceUpdated?>, _isc.getType<_ik055xb9.PresenceState?>, _isc.getType<_isz2sju0.PresenceUpdate?>, + _isc.getType<_i9g6l3wu.PublicationCard?>, + _isc.getType<_i0a1sw0a.PublicationCheckResult?>, + _isc.getType<_iz1gego0.PublicationDeliveryView?>, + _isc.getType<_iucp51pg.PublicationFieldMode?>, + _isc.getType<_i63wbtw0.PublicationFields?>, + _isc.getType<_iv6bey6s.PublicationInput?>, + _isc.getType<_ij9tsbn9.PublicationModeratorView?>, + _isc.getType<_ivvukfve.PublicationOpenSubmission?>, + _isc.getType<_iyqlj2kr.PublicationSecret?>, + _isc.getType<_i5i48220.PublicationSettings?>, + _isc.getType<_ip6l83ta.SubmissionDeliveryState?>, + _isc.getType<_iegijpud.SubmissionRevisionView?>, + _isc.getType<_ijb8v3k4.SubmissionStarted?>, + _isc.getType<_i7hbulg4.SubmissionStatus?>, + _isc.getType<_iq9uje8l.SubmissionValues?>, + _isc.getType<_iakndug7.SubmissionView?>, _isc.getType<_ie6clghy.RevAck?>, _isc.getType<_i6ck957q.RevPing?>, _isc.getType<_i6ck957q.RevRequestOps?>, @@ -1220,6 +1294,9 @@ class Protocol extends _isc.SerializationManager _isc.getType>, _isc.getType>, _isc.getType>, + _isc.getType>, + _isc.getType>, + _isc.getType>, _isc.getType>, _isc.getType?>, _isc.getType>, @@ -1257,7 +1334,9 @@ class Protocol extends _isc.SerializationManager _isc.getType>, _isc.getType>, _isc.getType>, + _isc.getType>, _isc.getType>, + _isc.getType>, _isc.getType>, _isc.getType>, _isc.getType>, @@ -1728,6 +1807,54 @@ class Protocol extends _isc.SerializationManager if (t == _isz2sju0.PresenceUpdate) { return _isz2sju0.PresenceUpdate.fromJson(data) as T; } + if (t == _i9g6l3wu.PublicationCard) { + return _i9g6l3wu.PublicationCard.fromJson(data) as T; + } + if (t == _i0a1sw0a.PublicationCheckResult) { + return _i0a1sw0a.PublicationCheckResult.fromJson(data) as T; + } + if (t == _iz1gego0.PublicationDeliveryView) { + return _iz1gego0.PublicationDeliveryView.fromJson(data) as T; + } + if (t == _iucp51pg.PublicationFieldMode) { + return _iucp51pg.PublicationFieldMode.fromJson(data) as T; + } + if (t == _i63wbtw0.PublicationFields) { + return _i63wbtw0.PublicationFields.fromJson(data) as T; + } + if (t == _iv6bey6s.PublicationInput) { + return _iv6bey6s.PublicationInput.fromJson(data) as T; + } + if (t == _ij9tsbn9.PublicationModeratorView) { + return _ij9tsbn9.PublicationModeratorView.fromJson(data) as T; + } + if (t == _ivvukfve.PublicationOpenSubmission) { + return _ivvukfve.PublicationOpenSubmission.fromJson(data) as T; + } + if (t == _iyqlj2kr.PublicationSecret) { + return _iyqlj2kr.PublicationSecret.fromJson(data) as T; + } + if (t == _i5i48220.PublicationSettings) { + return _i5i48220.PublicationSettings.fromJson(data) as T; + } + if (t == _ip6l83ta.SubmissionDeliveryState) { + return _ip6l83ta.SubmissionDeliveryState.fromJson(data) as T; + } + if (t == _iegijpud.SubmissionRevisionView) { + return _iegijpud.SubmissionRevisionView.fromJson(data) as T; + } + if (t == _ijb8v3k4.SubmissionStarted) { + return _ijb8v3k4.SubmissionStarted.fromJson(data) as T; + } + if (t == _i7hbulg4.SubmissionStatus) { + return _i7hbulg4.SubmissionStatus.fromJson(data) as T; + } + if (t == _iq9uje8l.SubmissionValues) { + return _iq9uje8l.SubmissionValues.fromJson(data) as T; + } + if (t == _iakndug7.SubmissionView) { + return _iakndug7.SubmissionView.fromJson(data) as T; + } if (t == _ie6clghy.RevAck) { return _ie6clghy.RevAck.fromJson(data) as T; } @@ -2746,6 +2873,86 @@ class Protocol extends _isc.SerializationManager return (data != null ? _isz2sju0.PresenceUpdate.fromJson(data) : null) as T; } + if (t == _isc.getType<_i9g6l3wu.PublicationCard?>()) { + return (data != null ? _i9g6l3wu.PublicationCard.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_i0a1sw0a.PublicationCheckResult?>()) { + return (data != null + ? _i0a1sw0a.PublicationCheckResult.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_iz1gego0.PublicationDeliveryView?>()) { + return (data != null + ? _iz1gego0.PublicationDeliveryView.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_iucp51pg.PublicationFieldMode?>()) { + return (data != null + ? _iucp51pg.PublicationFieldMode.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_i63wbtw0.PublicationFields?>()) { + return (data != null ? _i63wbtw0.PublicationFields.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_iv6bey6s.PublicationInput?>()) { + return (data != null ? _iv6bey6s.PublicationInput.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_ij9tsbn9.PublicationModeratorView?>()) { + return (data != null + ? _ij9tsbn9.PublicationModeratorView.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_ivvukfve.PublicationOpenSubmission?>()) { + return (data != null + ? _ivvukfve.PublicationOpenSubmission.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_iyqlj2kr.PublicationSecret?>()) { + return (data != null ? _iyqlj2kr.PublicationSecret.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_i5i48220.PublicationSettings?>()) { + return (data != null + ? _i5i48220.PublicationSettings.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_ip6l83ta.SubmissionDeliveryState?>()) { + return (data != null + ? _ip6l83ta.SubmissionDeliveryState.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_iegijpud.SubmissionRevisionView?>()) { + return (data != null + ? _iegijpud.SubmissionRevisionView.fromJson(data) + : null) + as T; + } + if (t == _isc.getType<_ijb8v3k4.SubmissionStarted?>()) { + return (data != null ? _ijb8v3k4.SubmissionStarted.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_i7hbulg4.SubmissionStatus?>()) { + return (data != null ? _i7hbulg4.SubmissionStatus.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_iq9uje8l.SubmissionValues?>()) { + return (data != null ? _iq9uje8l.SubmissionValues.fromJson(data) : null) + as T; + } + if (t == _isc.getType<_iakndug7.SubmissionView?>()) { + return (data != null ? _iakndug7.SubmissionView.fromJson(data) : null) + as T; + } if (t == _isc.getType<_ie6clghy.RevAck?>()) { return (data != null ? _ie6clghy.RevAck.fromJson(data) : null) as T; } @@ -3630,6 +3837,24 @@ class Protocol extends _isc.SerializationManager .toList() as T; } + if (t == List<_ivvukfve.PublicationOpenSubmission>) { + return (data as List) + .map((e) => deserialize<_ivvukfve.PublicationOpenSubmission>(e)) + .toList() + as T; + } + if (t == List<_ij9tsbn9.PublicationModeratorView>) { + return (data as List) + .map((e) => deserialize<_ij9tsbn9.PublicationModeratorView>(e)) + .toList() + as T; + } + if (t == List<_iegijpud.SubmissionRevisionView>) { + return (data as List) + .map((e) => deserialize<_iegijpud.SubmissionRevisionView>(e)) + .toList() + as T; + } if (t == List<_it4o2pk5.RevOpView>) { return (data as List) .map((e) => deserialize<_it4o2pk5.RevOpView>(e)) @@ -3859,9 +4084,21 @@ class Protocol extends _isc.SerializationManager .toList() as T; } + if (t == List<_i9bruko9.PublicationSettings>) { + return (data as List) + .map((e) => deserialize<_i9bruko9.PublicationSettings>(e)) + .toList() + as T; + } if (t == List) { return (data as List).map((e) => deserialize(e)).toList() as T; } + if (t == List<_ipl2ldhs.PublicationDeliveryView>) { + return (data as List) + .map((e) => deserialize<_ipl2ldhs.PublicationDeliveryView>(e)) + .toList() + as T; + } if (t == List<_ip6swqsj.AccessTokenView>) { return (data as List) .map((e) => deserialize<_ip6swqsj.AccessTokenView>(e)) @@ -4129,6 +4366,22 @@ class Protocol extends _isc.SerializationManager _i8r9afjv.PresenceUpdated => 'PresenceUpdated', _ik055xb9.PresenceState => 'PresenceState', _isz2sju0.PresenceUpdate => 'PresenceUpdate', + _i9g6l3wu.PublicationCard => 'PublicationCard', + _i0a1sw0a.PublicationCheckResult => 'PublicationCheckResult', + _iz1gego0.PublicationDeliveryView => 'PublicationDeliveryView', + _iucp51pg.PublicationFieldMode => 'PublicationFieldMode', + _i63wbtw0.PublicationFields => 'PublicationFields', + _iv6bey6s.PublicationInput => 'PublicationInput', + _ij9tsbn9.PublicationModeratorView => 'PublicationModeratorView', + _ivvukfve.PublicationOpenSubmission => 'PublicationOpenSubmission', + _iyqlj2kr.PublicationSecret => 'PublicationSecret', + _i5i48220.PublicationSettings => 'PublicationSettings', + _ip6l83ta.SubmissionDeliveryState => 'SubmissionDeliveryState', + _iegijpud.SubmissionRevisionView => 'SubmissionRevisionView', + _ijb8v3k4.SubmissionStarted => 'SubmissionStarted', + _i7hbulg4.SubmissionStatus => 'SubmissionStatus', + _iq9uje8l.SubmissionValues => 'SubmissionValues', + _iakndug7.SubmissionView => 'SubmissionView', _ie6clghy.RevAck => 'RevAck', _i6ck957q.RevPing => 'RevPing', _i6ck957q.RevRequestOps => 'RevRequestOps', @@ -4582,6 +4835,38 @@ class Protocol extends _isc.SerializationManager return 'PresenceState'; case _isz2sju0.PresenceUpdate(): return 'PresenceUpdate'; + case _i9g6l3wu.PublicationCard(): + return 'PublicationCard'; + case _i0a1sw0a.PublicationCheckResult(): + return 'PublicationCheckResult'; + case _iz1gego0.PublicationDeliveryView(): + return 'PublicationDeliveryView'; + case _iucp51pg.PublicationFieldMode(): + return 'PublicationFieldMode'; + case _i63wbtw0.PublicationFields(): + return 'PublicationFields'; + case _iv6bey6s.PublicationInput(): + return 'PublicationInput'; + case _ij9tsbn9.PublicationModeratorView(): + return 'PublicationModeratorView'; + case _ivvukfve.PublicationOpenSubmission(): + return 'PublicationOpenSubmission'; + case _iyqlj2kr.PublicationSecret(): + return 'PublicationSecret'; + case _i5i48220.PublicationSettings(): + return 'PublicationSettings'; + case _ip6l83ta.SubmissionDeliveryState(): + return 'SubmissionDeliveryState'; + case _iegijpud.SubmissionRevisionView(): + return 'SubmissionRevisionView'; + case _ijb8v3k4.SubmissionStarted(): + return 'SubmissionStarted'; + case _i7hbulg4.SubmissionStatus(): + return 'SubmissionStatus'; + case _iq9uje8l.SubmissionValues(): + return 'SubmissionValues'; + case _iakndug7.SubmissionView(): + return 'SubmissionView'; case _ie6clghy.RevAck(): return 'RevAck'; case _i6ck957q.RevPing(): @@ -5343,6 +5628,54 @@ class Protocol extends _isc.SerializationManager if (dataClassName == 'PresenceUpdate') { return deserialize<_isz2sju0.PresenceUpdate>(data['data']); } + if (dataClassName == 'PublicationCard') { + return deserialize<_i9g6l3wu.PublicationCard>(data['data']); + } + if (dataClassName == 'PublicationCheckResult') { + return deserialize<_i0a1sw0a.PublicationCheckResult>(data['data']); + } + if (dataClassName == 'PublicationDeliveryView') { + return deserialize<_iz1gego0.PublicationDeliveryView>(data['data']); + } + if (dataClassName == 'PublicationFieldMode') { + return deserialize<_iucp51pg.PublicationFieldMode>(data['data']); + } + if (dataClassName == 'PublicationFields') { + return deserialize<_i63wbtw0.PublicationFields>(data['data']); + } + if (dataClassName == 'PublicationInput') { + return deserialize<_iv6bey6s.PublicationInput>(data['data']); + } + if (dataClassName == 'PublicationModeratorView') { + return deserialize<_ij9tsbn9.PublicationModeratorView>(data['data']); + } + if (dataClassName == 'PublicationOpenSubmission') { + return deserialize<_ivvukfve.PublicationOpenSubmission>(data['data']); + } + if (dataClassName == 'PublicationSecret') { + return deserialize<_iyqlj2kr.PublicationSecret>(data['data']); + } + if (dataClassName == 'PublicationSettings') { + return deserialize<_i5i48220.PublicationSettings>(data['data']); + } + if (dataClassName == 'SubmissionDeliveryState') { + return deserialize<_ip6l83ta.SubmissionDeliveryState>(data['data']); + } + if (dataClassName == 'SubmissionRevisionView') { + return deserialize<_iegijpud.SubmissionRevisionView>(data['data']); + } + if (dataClassName == 'SubmissionStarted') { + return deserialize<_ijb8v3k4.SubmissionStarted>(data['data']); + } + if (dataClassName == 'SubmissionStatus') { + return deserialize<_i7hbulg4.SubmissionStatus>(data['data']); + } + if (dataClassName == 'SubmissionValues') { + return deserialize<_iq9uje8l.SubmissionValues>(data['data']); + } + if (dataClassName == 'SubmissionView') { + return deserialize<_iakndug7.SubmissionView>(data['data']); + } if (dataClassName == 'RevAck') { return deserialize<_ie6clghy.RevAck>(data['data']); } diff --git a/wonky_server/lib/server.dart b/wonky_server/lib/server.dart index e35c3b03..0272c879 100644 --- a/wonky_server/lib/server.dart +++ b/wonky_server/lib/server.dart @@ -30,6 +30,7 @@ import 'src/web/routes/app_config_route.dart'; import 'src/web/routes/github_webhook_route.dart'; import 'src/web/routes/improvements_redirect_route.dart'; import 'src/web/routes/invite_route.dart'; +import 'src/web/routes/publication_api_route.dart'; import 'src/web/routes/root_redirect_route.dart'; import 'src/web/web_apps.dart'; import 'src/write/themes/theme_service.dart'; @@ -177,6 +178,8 @@ void _configureWebServer(Serverpod pod) { // Webhooks of the Bugs & improvements GitHub App (specs/16 §13.3, README // in lib/src/platform/board/github/). pod.webServer.addRoute(GithubWebhookRoute(), '/api/github/webhook'); + // The API blogs call with their publication's key (specs/18 §7.3). + pod.webServer.addRoute(PublicationApiRoute(), '/api/pub/v1/**'); // Wonky Drive file bytes (Drive 02 §3.3, §8; suite 13 §6): token-bound // downloads with forced headers and the PUT upload route. FileRoutes.register(pod.webServer); @@ -293,6 +296,12 @@ final _jobs = { '*/10 * * * *', (c, id, cron) => c.callRecurring(identifier: id).cron(cron).board.sweep(), ), + // Publication webhooks due for a retry (specs/18 §7.2). + 'wonky.publicationSweep': ( + '* * * * *', + (c, id, cron) => + c.callRecurring(identifier: id).cron(cron).publications.sweep(), + ), }; /// Brings the scheduled recurring jobs in line with [_jobs] (see diff --git a/wonky_server/lib/src/generated/endpoints.dart b/wonky_server/lib/src/generated/endpoints.dart index 75916fa4..ebd3c519 100644 --- a/wonky_server/lib/src/generated/endpoints.dart +++ b/wonky_server/lib/src/generated/endpoints.dart @@ -72,6 +72,10 @@ import 'package:wonky_server/src/generated/platform/mcp/ui_bridge/ui_bridge_mess as _is78z0de; import 'package:wonky_server/src/generated/platform/presence/presence_update.dart' as _ipd65of1; +import 'package:wonky_server/src/generated/platform/publications/models/publication_input.dart' + as _iy7hmxv3; +import 'package:wonky_server/src/generated/platform/publications/models/submission_values.dart' + as _iwukrrmj; import 'package:wonky_server/src/generated/platform/revlog/messages/rev_client_message.dart' as _iv4mnr49; import 'package:wonky_server/src/generated/platform/revlog/models/rev_page_request.dart' @@ -116,6 +120,8 @@ import '../platform/mcp/ui_bridge/ui_bridge_endpoint.dart' as _ipb16bxt; import '../platform/meta/meta_endpoint.dart' as _isistrmv; import '../platform/notifications/notification_endpoint.dart' as _ia40tpv4; import '../platform/presence/presence_endpoint.dart' as _iv7snmpw; +import '../platform/publications/publication_endpoint.dart' as _igj7692v; +import '../platform/publications/submission_endpoint.dart' as _i7uk3p1b; import '../platform/sharing/sharing_endpoint.dart' as _itz30x9e; import '../platform/users/access_token_endpoint.dart' as _iusd4uiv; import '../platform/users/google_idp_endpoint.dart' as _i3henulz; @@ -229,6 +235,18 @@ class Endpoints extends _is.EndpointDispatch { 'presence', null, ), + 'publication': _igj7692v.PublicationEndpoint() + ..initialize( + server, + 'publication', + null, + ), + 'submission': _i7uk3p1b.SubmissionEndpoint() + ..initialize( + server, + 'submission', + null, + ), 'sharing': _itz30x9e.SharingEndpoint() ..initialize( server, @@ -3977,6 +3995,410 @@ class Endpoints extends _is.EndpointDispatch { ), }, ); + connectors['publication'] = _is.EndpointConnector( + name: 'publication', + endpoint: endpoints['publication']!, + methodConnectors: { + 'resolve': _is.MethodConnector( + name: 'resolve', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .resolve( + session, + params['publicId'], + ), + ), + 'startSubmission': _is.MethodConnector( + name: 'startSubmission', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + 'ref': _is.ParameterDescription( + name: 'ref', + type: _is.getType(), + nullable: true, + ), + 'agreed': _is.ParameterDescription( + name: 'agreed', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .startSubmission( + session, + params['publicId'], + params['ref'], + params['agreed'], + ), + ), + 'list': _is.MethodConnector( + name: 'list', + params: {}, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .list(session), + ), + 'create': _is.MethodConnector( + name: 'create', + params: { + 'input': _is.ParameterDescription( + name: 'input', + type: _is.getType<_iy7hmxv3.PublicationInput>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .create( + session, + params['input'], + ), + ), + 'update': _is.MethodConnector( + name: 'update', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + 'input': _is.ParameterDescription( + name: 'input', + type: _is.getType<_iy7hmxv3.PublicationInput>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .update( + session, + params['publicId'], + params['input'], + ), + ), + 'delete': _is.MethodConnector( + name: 'delete', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .delete( + session, + params['publicId'], + ), + ), + 'verify': _is.MethodConnector( + name: 'verify', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .verify( + session, + params['publicId'], + ), + ), + 'rotateSecret': _is.MethodConnector( + name: 'rotateSecret', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .rotateSecret( + session, + params['publicId'], + ), + ), + 'createApiKey': _is.MethodConnector( + name: 'createApiKey', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .createApiKey( + session, + params['publicId'], + ), + ), + 'setModerators': _is.MethodConnector( + name: 'setModerators', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + 'emails': _is.ParameterDescription( + name: 'emails', + type: _is.getType>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .setModerators( + session, + params['publicId'], + params['emails'], + ), + ), + 'deliveries': _is.MethodConnector( + name: 'deliveries', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .deliveries( + session, + params['publicId'], + ), + ), + 'resend': _is.MethodConnector( + name: 'resend', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + 'webhookId': _is.ParameterDescription( + name: 'webhookId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .resend( + session, + params['publicId'], + params['webhookId'], + ), + ), + 'sendTest': _is.MethodConnector( + name: 'sendTest', + params: { + 'publicId': _is.ParameterDescription( + name: 'publicId', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['publication'] as _igj7692v.PublicationEndpoint) + .sendTest( + session, + params['publicId'], + ), + ), + }, + ); + connectors['submission'] = _is.EndpointConnector( + name: 'submission', + endpoint: endpoints['submission']!, + methodConnectors: { + 'get': _is.MethodConnector( + name: 'get', + params: { + 'itemUuid': _is.ParameterDescription( + name: 'itemUuid', + type: _is.getType<_is.UuidValue>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['submission'] as _i7uk3p1b.SubmissionEndpoint).get( + session, + params['itemUuid'], + ), + ), + 'submit': _is.MethodConnector( + name: 'submit', + params: { + 'itemUuid': _is.ParameterDescription( + name: 'itemUuid', + type: _is.getType<_is.UuidValue>(), + nullable: false, + ), + 'values': _is.ParameterDescription( + name: 'values', + type: _is.getType<_iwukrrmj.SubmissionValues>(), + nullable: false, + ), + 'agreed': _is.ParameterDescription( + name: 'agreed', + type: _is.getType(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['submission'] as _i7uk3p1b.SubmissionEndpoint) + .submit( + session, + params['itemUuid'], + params['values'], + params['agreed'], + ), + ), + 'withdraw': _is.MethodConnector( + name: 'withdraw', + params: { + 'itemUuid': _is.ParameterDescription( + name: 'itemUuid', + type: _is.getType<_is.UuidValue>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['submission'] as _i7uk3p1b.SubmissionEndpoint) + .withdraw( + session, + params['itemUuid'], + ), + ), + 'disconnect': _is.MethodConnector( + name: 'disconnect', + params: { + 'itemUuid': _is.ParameterDescription( + name: 'itemUuid', + type: _is.getType<_is.UuidValue>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['submission'] as _i7uk3p1b.SubmissionEndpoint) + .disconnect( + session, + params['itemUuid'], + ), + ), + 'reconnect': _is.MethodConnector( + name: 'reconnect', + params: { + 'itemUuid': _is.ParameterDescription( + name: 'itemUuid', + type: _is.getType<_is.UuidValue>(), + nullable: false, + ), + }, + call: + ( + _is.Session session, + Map params, + ) async => + (endpoints['submission'] as _i7uk3p1b.SubmissionEndpoint) + .reconnect( + session, + params['itemUuid'], + ), + ), + }, + ); connectors['sharing'] = _is.EndpointConnector( name: 'sharing', endpoint: endpoints['sharing']!, diff --git a/wonky_server/lib/src/generated/future_calls.dart b/wonky_server/lib/src/generated/future_calls.dart index 09495587..ddbca080 100644 --- a/wonky_server/lib/src/generated/future_calls.dart +++ b/wonky_server/lib/src/generated/future_calls.dart @@ -20,6 +20,7 @@ import '../platform/files/file_preview_future_call.dart' as _iw6v1fyh; import '../platform/jobs/maintenance_future_call.dart' as _imgsvm9k; import '../platform/notifications/notification_email_future_call.dart' as _i1dis1nt; +import '../platform/publications/publication_future_call.dart' as _igy9pnc4; import '../platform/sharing/acl_future_call.dart' as _ivytsclb; import '../platform/storage/storage_future_call.dart' as _iel4dsm1; import '../sheets/scripts/script_scheduler_future_call.dart' as _iq0nfb3f; @@ -39,6 +40,8 @@ import 'future_calls_generated_models/file_preview_future_call_generate_model.da as _ilpvgw0t; import 'future_calls_generated_models/notification_email_future_call_send_model.dart' as _inb6x2l0; +import 'future_calls_generated_models/publications_future_call_deliver_model.dart' + as _il37cz87; import 'future_calls_generated_models/storage_future_call_refresh_item_size_model.dart' as _io4auc29; @@ -99,6 +102,8 @@ class FutureCalls extends _is.FutureCallDispatch<_FutureCallRef> { 'MaintenanceExpireGrantsFutureCall': MaintenanceExpireGrantsFutureCall(), 'MaintenanceDailyFutureCall': MaintenanceDailyFutureCall(), 'NotificationEmailSendFutureCall': NotificationEmailSendFutureCall(), + 'PublicationsDeliverFutureCall': PublicationsDeliverFutureCall(), + 'PublicationsSweepFutureCall': PublicationsSweepFutureCall(), 'AclFanOutFutureCall': AclFanOutFutureCall(), 'StorageBackfillFutureCall': StorageBackfillFutureCall(), 'StorageReconcileFutureCall': StorageReconcileFutureCall(), @@ -237,6 +242,10 @@ class _FutureCallRef { _invokeFutureCall, ); + late final publications = _PublicationsFutureCallDispatcher( + _invokeFutureCall, + ); + late final acl = _AclFutureCallDispatcher(_invokeFutureCall); late final storage = _StorageFutureCallDispatcher(_invokeFutureCall); @@ -391,6 +400,29 @@ class _NotificationEmailFutureCallDispatcher { } } +class _PublicationsFutureCallDispatcher { + _PublicationsFutureCallDispatcher(this._invokeFutureCall); + + final _InvokeFutureCall _invokeFutureCall; + + Future deliver(int deliveryId) { + var object = _il37cz87.PublicationsFutureCallDeliverModel( + deliveryId: deliveryId, + ); + return _invokeFutureCall( + 'PublicationsDeliverFutureCall', + object, + ); + } + + Future sweep() { + return _invokeFutureCall( + 'PublicationsSweepFutureCall', + null, + ); + } +} + class _AclFutureCallDispatcher { _AclFutureCallDispatcher(this._invokeFutureCall); @@ -679,6 +711,35 @@ class NotificationEmailSendFutureCall } } +class PublicationsDeliverFutureCall + extends _is.FutureCall<_il37cz87.PublicationsFutureCallDeliverModel> + implements + _is.InvokableFutureCall<_il37cz87.PublicationsFutureCallDeliverModel> { + @override + _ida.Future invoke( + _is.Session session, + _il37cz87.PublicationsFutureCallDeliverModel? object, + ) async { + if (object != null) { + await _igy9pnc4.PublicationsFutureCall().deliver( + session, + object.deliveryId, + ); + } + } +} + +class PublicationsSweepFutureCall extends _is.FutureCall + implements _is.InvokableFutureCall { + @override + _ida.Future invoke( + _is.Session session, + _is.SerializableModel? object, + ) async { + await _igy9pnc4.PublicationsFutureCall().sweep(session); + } +} + class AclFanOutFutureCall extends _is.FutureCall<_ihl3axv2.AclFutureCallFanOutModel> implements _is.InvokableFutureCall<_ihl3axv2.AclFutureCallFanOutModel> { diff --git a/wonky_server/lib/src/generated/future_calls_generated_models/publications_future_call_deliver_model.dart b/wonky_server/lib/src/generated/future_calls_generated_models/publications_future_call_deliver_model.dart new file mode 100644 index 00000000..556d1c06 --- /dev/null +++ b/wonky_server/lib/src/generated/future_calls_generated_models/publications_future_call_deliver_model.dart @@ -0,0 +1,69 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +abstract class PublicationsFutureCallDeliverModel + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationsFutureCallDeliverModel._({required this.deliveryId}); + + factory PublicationsFutureCallDeliverModel({required int deliveryId}) = + _PublicationsFutureCallDeliverModelImpl; + + factory PublicationsFutureCallDeliverModel.fromJson( + Map jsonSerialization, + ) { + return PublicationsFutureCallDeliverModel( + deliveryId: jsonSerialization['deliveryId'] as int, + ); + } + + int deliveryId; + + /// Returns a shallow copy of this [PublicationsFutureCallDeliverModel] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationsFutureCallDeliverModel copyWith({int? deliveryId}); + @override + Map toJson() { + return { + '__className__': 'PublicationsFutureCallDeliverModel', + 'deliveryId': deliveryId, + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _PublicationsFutureCallDeliverModelImpl + extends PublicationsFutureCallDeliverModel { + _PublicationsFutureCallDeliverModelImpl({required int deliveryId}) + : super._(deliveryId: deliveryId); + + /// Returns a shallow copy of this [PublicationsFutureCallDeliverModel] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationsFutureCallDeliverModel copyWith({int? deliveryId}) { + return PublicationsFutureCallDeliverModel( + deliveryId: deliveryId ?? this.deliveryId, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/activity/activity_type.dart b/wonky_server/lib/src/generated/platform/activity/activity_type.dart index c9aa3bd2..e8eb7c1c 100644 --- a/wonky_server/lib/src/generated/platform/activity/activity_type.dart +++ b/wonky_server/lib/src/generated/platform/activity/activity_type.dart @@ -26,7 +26,12 @@ enum ActivityType implements _is.SerializableModel { exported, /// (v2) A file was uploaded (Drive 02 §3.3). - uploaded; + uploaded, + + /// (M14) Submitted to, withdrawn from or disconnected from a publication, + /// or the publication changed the status (specs/18 §6; summary + /// {publication, action, status?}). + submission; static ActivityType fromJson(String name) { switch (name) { @@ -54,6 +59,8 @@ enum ActivityType implements _is.SerializableModel { return ActivityType.exported; case 'uploaded': return ActivityType.uploaded; + case 'submission': + return ActivityType.submission; default: throw ArgumentError( 'Value "$name" cannot be converted to "ActivityType"', diff --git a/wonky_server/lib/src/generated/platform/comments/comment.dart b/wonky_server/lib/src/generated/platform/comments/comment.dart index 17db84cd..6142360c 100644 --- a/wonky_server/lib/src/generated/platform/comments/comment.dart +++ b/wonky_server/lib/src/generated/platform/comments/comment.dart @@ -31,6 +31,7 @@ abstract class Comment this.editedAt, this.deletedAt, this.systemEvent, + this.publicationId, }) : reactions = reactions ?? '{}'; factory Comment({ @@ -46,6 +47,7 @@ abstract class Comment DateTime? editedAt, DateTime? deletedAt, _ikzs0dm0.CommentSystemEvent? systemEvent, + int? publicationId, }) = _CommentImpl; factory Comment.fromJson(Map jsonSerialization) { @@ -78,6 +80,7 @@ abstract class Comment : _ikzs0dm0.CommentSystemEvent.fromJson( (jsonSerialization['systemEvent'] as String), ), + publicationId: jsonSerialization['publicationId'] as int?, ); } @@ -116,6 +119,9 @@ abstract class Comment _ikzs0dm0.CommentSystemEvent? systemEvent; + /// (M14) A publication's message (authorKind system), specs/18 §5.2. + int? publicationId; + @override _is.Table get table => t; @@ -135,6 +141,7 @@ abstract class Comment DateTime? editedAt = const _is.$UndefinedDateTime(), DateTime? deletedAt = const _is.$UndefinedDateTime(), _ikzs0dm0.CommentSystemEvent? systemEvent, + int? publicationId, }); @override Map toJson() { @@ -152,6 +159,7 @@ abstract class Comment if (editedAt != null) 'editedAt': editedAt?.toJson(), if (deletedAt != null) 'deletedAt': deletedAt?.toJson(), if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (publicationId != null) 'publicationId': publicationId, }; } @@ -171,6 +179,7 @@ abstract class Comment if (editedAt != null) 'editedAt': editedAt?.toJson(), if (deletedAt != null) 'deletedAt': deletedAt?.toJson(), if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (publicationId != null) 'publicationId': publicationId, }; } @@ -218,6 +227,7 @@ class _CommentImpl extends Comment { DateTime? editedAt, DateTime? deletedAt, _ikzs0dm0.CommentSystemEvent? systemEvent, + int? publicationId, }) : super._( id: id, threadId: threadId, @@ -231,6 +241,7 @@ class _CommentImpl extends Comment { editedAt: editedAt, deletedAt: deletedAt, systemEvent: systemEvent, + publicationId: publicationId, ); /// Returns a shallow copy of this [Comment] @@ -250,6 +261,7 @@ class _CommentImpl extends Comment { DateTime? editedAt = const _is.$UndefinedDateTime(), DateTime? deletedAt = const _is.$UndefinedDateTime(), Object? systemEvent = _Undefined, + Object? publicationId = _Undefined, }) { return Comment( id: id is int? ? id : this.id, @@ -268,6 +280,7 @@ class _CommentImpl extends Comment { systemEvent: systemEvent is _ikzs0dm0.CommentSystemEvent? ? systemEvent : this.systemEvent, + publicationId: publicationId is int? ? publicationId : this.publicationId, ); } } @@ -337,6 +350,11 @@ class CommentUpdateTable extends _is.UpdateTable { table.systemEvent, value, ); + + _is.ColumnValue publicationId(int? value) => _is.ColumnValue( + table.publicationId, + value, + ); } class CommentTable extends _is.Table { @@ -389,6 +407,10 @@ class CommentTable extends _is.Table { this, _is.EnumSerialization.byName, ); + publicationId = _is.ColumnInt( + 'publicationId', + this, + ); } late final CommentUpdateTable updateTable; @@ -421,6 +443,9 @@ class CommentTable extends _is.Table { late final _is.ColumnEnum<_ikzs0dm0.CommentSystemEvent> systemEvent; + /// (M14) A publication's message (authorKind system), specs/18 §5.2. + late final _is.ColumnInt publicationId; + @override List<_is.Column> get columns => [ id, @@ -435,6 +460,7 @@ class CommentTable extends _is.Table { editedAt, deletedAt, systemEvent, + publicationId, ]; } diff --git a/wonky_server/lib/src/generated/platform/comments/comment_view.dart b/wonky_server/lib/src/generated/platform/comments/comment_view.dart index 9ef8a963..63357f12 100644 --- a/wonky_server/lib/src/generated/platform/comments/comment_view.dart +++ b/wonky_server/lib/src/generated/platform/comments/comment_view.dart @@ -31,6 +31,7 @@ abstract class CommentView this.editedAt, required this.deleted, this.systemEvent, + this.authorLabel, }); factory CommentView({ @@ -46,6 +47,7 @@ abstract class CommentView DateTime? editedAt, required bool deleted, _ikzs0dm0.CommentSystemEvent? systemEvent, + String? authorLabel, }) = _CommentViewImpl; factory CommentView.fromJson(Map jsonSerialization) { @@ -84,6 +86,7 @@ abstract class CommentView : _ikzs0dm0.CommentSystemEvent.fromJson( (jsonSerialization['systemEvent'] as String), ), + authorLabel: jsonSerialization['authorLabel'] as String?, ); } @@ -113,6 +116,10 @@ abstract class CommentView _ikzs0dm0.CommentSystemEvent? systemEvent; + /// (M14) Name shown instead of a user: the publication of a message + /// (specs/18 §5.2). + String? authorLabel; + /// Returns a shallow copy of this [CommentView] /// with some or all fields replaced by the given arguments. @_is.useResult @@ -129,6 +136,7 @@ abstract class CommentView DateTime? editedAt = const _is.$UndefinedDateTime(), bool? deleted, _ikzs0dm0.CommentSystemEvent? systemEvent, + String? authorLabel, }); @override Map toJson() { @@ -146,6 +154,7 @@ abstract class CommentView if (editedAt != null) 'editedAt': editedAt?.toJson(), 'deleted': deleted, if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (authorLabel != null) 'authorLabel': authorLabel, }; } @@ -165,6 +174,7 @@ abstract class CommentView if (editedAt != null) 'editedAt': editedAt?.toJson(), 'deleted': deleted, if (systemEvent != null) 'systemEvent': systemEvent?.toJson(), + if (authorLabel != null) 'authorLabel': authorLabel, }; } @@ -195,6 +205,7 @@ class _CommentViewImpl extends CommentView { DateTime? editedAt, required bool deleted, _ikzs0dm0.CommentSystemEvent? systemEvent, + String? authorLabel, }) : super._( id: id, uuid: uuid, @@ -208,6 +219,7 @@ class _CommentViewImpl extends CommentView { editedAt: editedAt, deleted: deleted, systemEvent: systemEvent, + authorLabel: authorLabel, ); /// Returns a shallow copy of this [CommentView] @@ -227,6 +239,7 @@ class _CommentViewImpl extends CommentView { DateTime? editedAt = const _is.$UndefinedDateTime(), bool? deleted, Object? systemEvent = _Undefined, + Object? authorLabel = _Undefined, }) { return CommentView( id: id ?? this.id, @@ -255,6 +268,7 @@ class _CommentViewImpl extends CommentView { systemEvent: systemEvent is _ikzs0dm0.CommentSystemEvent? ? systemEvent : this.systemEvent, + authorLabel: authorLabel is String? ? authorLabel : this.authorLabel, ); } } diff --git a/wonky_server/lib/src/generated/platform/notifications/notification_kind.dart b/wonky_server/lib/src/generated/platform/notifications/notification_kind.dart index 38eae5b6..9ac1bd57 100644 --- a/wonky_server/lib/src/generated/platform/notifications/notification_kind.dart +++ b/wonky_server/lib/src/generated/platform/notifications/notification_kind.dart @@ -35,7 +35,11 @@ enum NotificationKind implements _is.SerializableModel { boardStatus, /// My claim: warning, expiry, released, PR closed. - boardClaim; + boardClaim, + + /// (M14) A publication changed the status of a story I can edit or sent + /// a message; a submission could not be delivered (specs/18 §5.3). + submission; static NotificationKind fromJson(String name) { switch (name) { @@ -65,6 +69,8 @@ enum NotificationKind implements _is.SerializableModel { return NotificationKind.boardStatus; case 'boardClaim': return NotificationKind.boardClaim; + case 'submission': + return NotificationKind.submission; default: throw ArgumentError( 'Value "$name" cannot be converted to "NotificationKind"', diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication.dart b/wonky_server/lib/src/generated/platform/publications/models/publication.dart new file mode 100644 index 00000000..e7a759df --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication.dart @@ -0,0 +1,1086 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; + +/// A destination that takes stories from Wonky Write (specs/18 §2, §6), +/// owned by one user (the blog owner). Holds the signing secret, so it +/// never leaves the server; clients see [PublicationSettings] and +/// [PublicationCard]. +abstract class Publication + implements _is.TableRow, _is.ProtocolSerialization { + Publication._({ + this.id, + required this.publicId, + required this.ownerId, + required this.name, + required this.siteUrl, + required this.webhookUrl, + this.verifiedHost, + this.verifiedAt, + this.templateItemId, + this.termsUrl, + required this.fields, + required this.signingSecret, + this.previousSigningSecret, + this.previousSecretUntil, + this.apiKeyHash, + this.apiKeyLast4, + bool? enabled, + required this.createdAt, + required this.updatedAt, + }) : enabled = enabled ?? true; + + factory Publication({ + int? id, + required String publicId, + required int ownerId, + required String name, + required String siteUrl, + required String webhookUrl, + String? verifiedHost, + DateTime? verifiedAt, + int? templateItemId, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required String signingSecret, + String? previousSigningSecret, + DateTime? previousSecretUntil, + String? apiKeyHash, + String? apiKeyLast4, + bool? enabled, + required DateTime createdAt, + required DateTime updatedAt, + }) = _PublicationImpl; + + factory Publication.fromJson(Map jsonSerialization) { + return Publication( + id: jsonSerialization['id'] as int?, + publicId: jsonSerialization['publicId'] as String, + ownerId: jsonSerialization['ownerId'] as int, + name: jsonSerialization['name'] as String, + siteUrl: jsonSerialization['siteUrl'] as String, + webhookUrl: jsonSerialization['webhookUrl'] as String, + verifiedHost: jsonSerialization['verifiedHost'] as String?, + verifiedAt: jsonSerialization['verifiedAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson(jsonSerialization['verifiedAt']), + templateItemId: jsonSerialization['templateItemId'] as int?, + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _il4umwa0.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + signingSecret: jsonSerialization['signingSecret'] as String, + previousSigningSecret: + jsonSerialization['previousSigningSecret'] as String?, + previousSecretUntil: jsonSerialization['previousSecretUntil'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['previousSecretUntil'], + ), + apiKeyHash: jsonSerialization['apiKeyHash'] as String?, + apiKeyLast4: jsonSerialization['apiKeyLast4'] as String?, + enabled: jsonSerialization['enabled'] == null + ? null + : _is.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + createdAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + updatedAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['updatedAt'], + ), + ); + } + + static final t = PublicationTable(); + + static const db = PublicationRepository._(); + + @override + int? id; + + /// "pub_" + 22 url-safe characters; in contributor links, not a secret. + String publicId; + + int ownerId; + + String name; + + /// https origin of the blog (`https://blog.example.com`). + String siteUrl; + + /// https URL the webhooks go to. + String webhookUrl; + + /// The site host proven by `/.well-known/wonky-publications.json` + /// (specs/18 §8.2); null = unverified. + String? verifiedHost; + + DateTime? verifiedAt; + + /// The owner's Write document new stories start from. + int? templateItemId; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + /// "whsec_" + base64 key; must be kept in plain to sign (specs/13 §2). + String signingSecret; + + /// The previous secret signs too until [previousSecretUntil] (rotation). + String? previousSigningSecret; + + DateTime? previousSecretUntil; + + /// SHA-256 (hex) of the API key "wpk_…", shown once. + String? apiKeyHash; + + String? apiKeyLast4; + + bool enabled; + + DateTime createdAt; + + DateTime updatedAt; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [Publication] + /// with some or all fields replaced by the given arguments. + @_is.useResult + Publication copyWith({ + int? id, + String? publicId, + int? ownerId, + String? name, + String? siteUrl, + String? webhookUrl, + String? verifiedHost, + DateTime? verifiedAt = const _is.$UndefinedDateTime(), + int? templateItemId, + String? termsUrl, + _i1a71r29.PublicationFields? fields, + String? signingSecret, + String? previousSigningSecret, + DateTime? previousSecretUntil = const _is.$UndefinedDateTime(), + String? apiKeyHash, + String? apiKeyLast4, + bool? enabled, + DateTime? createdAt, + DateTime? updatedAt, + }); + @override + Map toJson() { + return { + '__className__': 'Publication', + if (id != null) 'id': id, + 'publicId': publicId, + 'ownerId': ownerId, + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (verifiedHost != null) 'verifiedHost': verifiedHost, + if (verifiedAt != null) 'verifiedAt': verifiedAt?.toJson(), + if (templateItemId != null) 'templateItemId': templateItemId, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'signingSecret': signingSecret, + if (previousSigningSecret != null) + 'previousSigningSecret': previousSigningSecret, + if (previousSecretUntil != null) + 'previousSecretUntil': previousSecretUntil?.toJson(), + if (apiKeyHash != null) 'apiKeyHash': apiKeyHash, + if (apiKeyLast4 != null) 'apiKeyLast4': apiKeyLast4, + 'enabled': enabled, + 'createdAt': createdAt.toJson(), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static PublicationInclude include() { + return PublicationInclude._(); + } + + static PublicationIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + PublicationInclude? include, + }) { + return PublicationIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationImpl extends Publication { + _PublicationImpl({ + int? id, + required String publicId, + required int ownerId, + required String name, + required String siteUrl, + required String webhookUrl, + String? verifiedHost, + DateTime? verifiedAt, + int? templateItemId, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required String signingSecret, + String? previousSigningSecret, + DateTime? previousSecretUntil, + String? apiKeyHash, + String? apiKeyLast4, + bool? enabled, + required DateTime createdAt, + required DateTime updatedAt, + }) : super._( + id: id, + publicId: publicId, + ownerId: ownerId, + name: name, + siteUrl: siteUrl, + webhookUrl: webhookUrl, + verifiedHost: verifiedHost, + verifiedAt: verifiedAt, + templateItemId: templateItemId, + termsUrl: termsUrl, + fields: fields, + signingSecret: signingSecret, + previousSigningSecret: previousSigningSecret, + previousSecretUntil: previousSecretUntil, + apiKeyHash: apiKeyHash, + apiKeyLast4: apiKeyLast4, + enabled: enabled, + createdAt: createdAt, + updatedAt: updatedAt, + ); + + /// Returns a shallow copy of this [Publication] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + Publication copyWith({ + Object? id = _Undefined, + String? publicId, + int? ownerId, + String? name, + String? siteUrl, + String? webhookUrl, + Object? verifiedHost = _Undefined, + DateTime? verifiedAt = const _is.$UndefinedDateTime(), + Object? templateItemId = _Undefined, + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + String? signingSecret, + Object? previousSigningSecret = _Undefined, + DateTime? previousSecretUntil = const _is.$UndefinedDateTime(), + Object? apiKeyHash = _Undefined, + Object? apiKeyLast4 = _Undefined, + bool? enabled, + DateTime? createdAt, + DateTime? updatedAt, + }) { + return Publication( + id: id is int? ? id : this.id, + publicId: publicId ?? this.publicId, + ownerId: ownerId ?? this.ownerId, + name: name ?? this.name, + siteUrl: siteUrl ?? this.siteUrl, + webhookUrl: webhookUrl ?? this.webhookUrl, + verifiedHost: verifiedHost is String? ? verifiedHost : this.verifiedHost, + verifiedAt: verifiedAt is _is.UndefinedSentinel + ? this.verifiedAt + : verifiedAt, + templateItemId: templateItemId is int? + ? templateItemId + : this.templateItemId, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + signingSecret: signingSecret ?? this.signingSecret, + previousSigningSecret: previousSigningSecret is String? + ? previousSigningSecret + : this.previousSigningSecret, + previousSecretUntil: previousSecretUntil is _is.UndefinedSentinel + ? this.previousSecretUntil + : previousSecretUntil, + apiKeyHash: apiKeyHash is String? ? apiKeyHash : this.apiKeyHash, + apiKeyLast4: apiKeyLast4 is String? ? apiKeyLast4 : this.apiKeyLast4, + enabled: enabled ?? this.enabled, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + ); + } +} + +class PublicationUpdateTable extends _is.UpdateTable { + PublicationUpdateTable(super.table); + + _is.ColumnValue publicId(String value) => _is.ColumnValue( + table.publicId, + value, + ); + + _is.ColumnValue ownerId(int value) => _is.ColumnValue( + table.ownerId, + value, + ); + + _is.ColumnValue name(String value) => _is.ColumnValue( + table.name, + value, + ); + + _is.ColumnValue siteUrl(String value) => _is.ColumnValue( + table.siteUrl, + value, + ); + + _is.ColumnValue webhookUrl(String value) => _is.ColumnValue( + table.webhookUrl, + value, + ); + + _is.ColumnValue verifiedHost(String? value) => + _is.ColumnValue( + table.verifiedHost, + value, + ); + + _is.ColumnValue verifiedAt(DateTime? value) => + _is.ColumnValue( + table.verifiedAt, + value, + ); + + _is.ColumnValue templateItemId(int? value) => _is.ColumnValue( + table.templateItemId, + value, + ); + + _is.ColumnValue termsUrl(String? value) => _is.ColumnValue( + table.termsUrl, + value, + ); + + _is.ColumnValue<_i1a71r29.PublicationFields, _i1a71r29.PublicationFields> + fields(_i1a71r29.PublicationFields value) => _is.ColumnValue( + table.fields, + value, + ); + + _is.ColumnValue signingSecret(String value) => + _is.ColumnValue( + table.signingSecret, + value, + ); + + _is.ColumnValue previousSigningSecret(String? value) => + _is.ColumnValue( + table.previousSigningSecret, + value, + ); + + _is.ColumnValue previousSecretUntil(DateTime? value) => + _is.ColumnValue( + table.previousSecretUntil, + value, + ); + + _is.ColumnValue apiKeyHash(String? value) => _is.ColumnValue( + table.apiKeyHash, + value, + ); + + _is.ColumnValue apiKeyLast4(String? value) => _is.ColumnValue( + table.apiKeyLast4, + value, + ); + + _is.ColumnValue enabled(bool value) => _is.ColumnValue( + table.enabled, + value, + ); + + _is.ColumnValue createdAt(DateTime value) => + _is.ColumnValue( + table.createdAt, + value, + ); + + _is.ColumnValue updatedAt(DateTime value) => + _is.ColumnValue( + table.updatedAt, + value, + ); +} + +class PublicationTable extends _is.Table { + PublicationTable({super.tableRelation}) : super(tableName: 'publication') { + updateTable = PublicationUpdateTable(this); + publicId = _is.ColumnString( + 'publicId', + this, + ); + ownerId = _is.ColumnInt( + 'ownerId', + this, + ); + name = _is.ColumnString( + 'name', + this, + ); + siteUrl = _is.ColumnString( + 'siteUrl', + this, + ); + webhookUrl = _is.ColumnString( + 'webhookUrl', + this, + ); + verifiedHost = _is.ColumnString( + 'verifiedHost', + this, + ); + verifiedAt = _is.ColumnDateTime( + 'verifiedAt', + this, + ); + templateItemId = _is.ColumnInt( + 'templateItemId', + this, + ); + termsUrl = _is.ColumnString( + 'termsUrl', + this, + ); + fields = _is.ColumnSerializable<_i1a71r29.PublicationFields>( + 'fields', + this, + ); + signingSecret = _is.ColumnString( + 'signingSecret', + this, + ); + previousSigningSecret = _is.ColumnString( + 'previousSigningSecret', + this, + ); + previousSecretUntil = _is.ColumnDateTime( + 'previousSecretUntil', + this, + ); + apiKeyHash = _is.ColumnString( + 'apiKeyHash', + this, + ); + apiKeyLast4 = _is.ColumnString( + 'apiKeyLast4', + this, + ); + enabled = _is.ColumnBool( + 'enabled', + this, + hasDefault: true, + ); + createdAt = _is.ColumnDateTime( + 'createdAt', + this, + ); + updatedAt = _is.ColumnDateTime( + 'updatedAt', + this, + ); + } + + late final PublicationUpdateTable updateTable; + + /// "pub_" + 22 url-safe characters; in contributor links, not a secret. + late final _is.ColumnString publicId; + + late final _is.ColumnInt ownerId; + + late final _is.ColumnString name; + + /// https origin of the blog (`https://blog.example.com`). + late final _is.ColumnString siteUrl; + + /// https URL the webhooks go to. + late final _is.ColumnString webhookUrl; + + /// The site host proven by `/.well-known/wonky-publications.json` + /// (specs/18 §8.2); null = unverified. + late final _is.ColumnString verifiedHost; + + late final _is.ColumnDateTime verifiedAt; + + /// The owner's Write document new stories start from. + late final _is.ColumnInt templateItemId; + + late final _is.ColumnString termsUrl; + + late final _is.ColumnSerializable<_i1a71r29.PublicationFields> fields; + + /// "whsec_" + base64 key; must be kept in plain to sign (specs/13 §2). + late final _is.ColumnString signingSecret; + + /// The previous secret signs too until [previousSecretUntil] (rotation). + late final _is.ColumnString previousSigningSecret; + + late final _is.ColumnDateTime previousSecretUntil; + + /// SHA-256 (hex) of the API key "wpk_…", shown once. + late final _is.ColumnString apiKeyHash; + + late final _is.ColumnString apiKeyLast4; + + late final _is.ColumnBool enabled; + + late final _is.ColumnDateTime createdAt; + + late final _is.ColumnDateTime updatedAt; + + @override + List<_is.Column> get columns => [ + id, + publicId, + ownerId, + name, + siteUrl, + webhookUrl, + verifiedHost, + verifiedAt, + templateItemId, + termsUrl, + fields, + signingSecret, + previousSigningSecret, + previousSecretUntil, + apiKeyHash, + apiKeyLast4, + enabled, + createdAt, + updatedAt, + ]; +} + +class PublicationInclude extends _is.IncludeObject { + PublicationInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => Publication.t; +} + +class PublicationIncludeList extends _is.IncludeList { + PublicationIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(Publication.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => Publication.t; +} + +class PublicationRepository { + const PublicationRepository._(); + + /// Returns a list of [Publication]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(Publication.t), + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [Publication]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `Publication.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(Publication.t), + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [Publication] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(Publication.t), + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [Publication] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [Publication]s in the list and returns the inserted rows. + /// + /// The returned [Publication]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [Publication] and returns the inserted row. + /// + /// The returned [Publication] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + Publication row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [Publication]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [Publication]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(Publication.t), + updateColumns: updateColumns?.call(Publication.t), + updateWhere: updateWhere?.call(Publication.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [Publication] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [Publication] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + Publication row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(Publication.t), + updateColumns: updateColumns?.call(Publication.t), + updateWhere: updateWhere?.call(Publication.t), + transaction: transaction, + ); + } + + /// Updates all [Publication]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(Publication.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [Publication]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + Publication row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(Publication.t), + transaction: transaction, + ); + } + + /// Updates a single [Publication] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(Publication.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [Publication]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(Publication.t.updateTable), + where: where(Publication.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [Publication]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [Publication]. + Future deleteRow( + _is.DatabaseSession session, + Publication row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(Publication.t), + orderBy: orderBy?.call(Publication.t), + orderByList: orderByList?.call(Publication.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(Publication.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [Publication] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(Publication.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_block.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_block.dart new file mode 100644 index 00000000..7502498f --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_block.dart @@ -0,0 +1,687 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; + +/// A user the publication doesn't take stories from (specs/18 §7.3). +abstract class PublicationBlock + implements _is.TableRow, _is.ProtocolSerialization { + PublicationBlock._({ + this.id, + required this.publicationId, + required this.userId, + required this.at, + }); + + factory PublicationBlock({ + int? id, + required int publicationId, + required int userId, + required DateTime at, + }) = _PublicationBlockImpl; + + factory PublicationBlock.fromJson(Map jsonSerialization) { + return PublicationBlock( + id: jsonSerialization['id'] as int?, + publicationId: jsonSerialization['publicationId'] as int, + userId: jsonSerialization['userId'] as int, + at: _is.DateTimeJsonExtension.fromJson(jsonSerialization['at']), + ); + } + + static final t = PublicationBlockTable(); + + static const db = PublicationBlockRepository._(); + + @override + int? id; + + int publicationId; + + int userId; + + DateTime at; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [PublicationBlock] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationBlock copyWith({ + int? id, + int? publicationId, + int? userId, + DateTime? at, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationBlock', + if (id != null) 'id': id, + 'publicationId': publicationId, + 'userId': userId, + 'at': at.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static PublicationBlockInclude include() { + return PublicationBlockInclude._(); + } + + static PublicationBlockIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + PublicationBlockInclude? include, + }) { + return PublicationBlockIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationBlockImpl extends PublicationBlock { + _PublicationBlockImpl({ + int? id, + required int publicationId, + required int userId, + required DateTime at, + }) : super._( + id: id, + publicationId: publicationId, + userId: userId, + at: at, + ); + + /// Returns a shallow copy of this [PublicationBlock] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationBlock copyWith({ + Object? id = _Undefined, + int? publicationId, + int? userId, + DateTime? at, + }) { + return PublicationBlock( + id: id is int? ? id : this.id, + publicationId: publicationId ?? this.publicationId, + userId: userId ?? this.userId, + at: at ?? this.at, + ); + } +} + +class PublicationBlockUpdateTable + extends _is.UpdateTable { + PublicationBlockUpdateTable(super.table); + + _is.ColumnValue publicationId(int value) => _is.ColumnValue( + table.publicationId, + value, + ); + + _is.ColumnValue userId(int value) => _is.ColumnValue( + table.userId, + value, + ); + + _is.ColumnValue at(DateTime value) => _is.ColumnValue( + table.at, + value, + ); +} + +class PublicationBlockTable extends _is.Table { + PublicationBlockTable({super.tableRelation}) + : super(tableName: 'publication_block') { + updateTable = PublicationBlockUpdateTable(this); + publicationId = _is.ColumnInt( + 'publicationId', + this, + ); + userId = _is.ColumnInt( + 'userId', + this, + ); + at = _is.ColumnDateTime( + 'at', + this, + ); + } + + late final PublicationBlockUpdateTable updateTable; + + late final _is.ColumnInt publicationId; + + late final _is.ColumnInt userId; + + late final _is.ColumnDateTime at; + + @override + List<_is.Column> get columns => [ + id, + publicationId, + userId, + at, + ]; +} + +class PublicationBlockInclude extends _is.IncludeObject { + PublicationBlockInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => PublicationBlock.t; +} + +class PublicationBlockIncludeList extends _is.IncludeList { + PublicationBlockIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(PublicationBlock.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => PublicationBlock.t; +} + +class PublicationBlockRepository { + const PublicationBlockRepository._(); + + /// Returns a list of [PublicationBlock]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(PublicationBlock.t), + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [PublicationBlock]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `PublicationBlock.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(PublicationBlock.t), + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [PublicationBlock] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(PublicationBlock.t), + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [PublicationBlock] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [PublicationBlock]s in the list and returns the inserted rows. + /// + /// The returned [PublicationBlock]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [PublicationBlock] and returns the inserted row. + /// + /// The returned [PublicationBlock] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + PublicationBlock row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [PublicationBlock]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [PublicationBlock]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(PublicationBlock.t), + updateColumns: updateColumns?.call(PublicationBlock.t), + updateWhere: updateWhere?.call(PublicationBlock.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [PublicationBlock] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [PublicationBlock] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + PublicationBlock row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(PublicationBlock.t), + updateColumns: updateColumns?.call(PublicationBlock.t), + updateWhere: updateWhere?.call(PublicationBlock.t), + transaction: transaction, + ); + } + + /// Updates all [PublicationBlock]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(PublicationBlock.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [PublicationBlock]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + PublicationBlock row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(PublicationBlock.t), + transaction: transaction, + ); + } + + /// Updates a single [PublicationBlock] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder + columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(PublicationBlock.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [PublicationBlock]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder + columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(PublicationBlock.t.updateTable), + where: where(PublicationBlock.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [PublicationBlock]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [PublicationBlock]. + Future deleteRow( + _is.DatabaseSession session, + PublicationBlock row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(PublicationBlock.t), + orderBy: orderBy?.call(PublicationBlock.t), + orderByList: orderByList?.call(PublicationBlock.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(PublicationBlock.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [PublicationBlock] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(PublicationBlock.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_card.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_card.dart new file mode 100644 index 00000000..a0caf114 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_card.dart @@ -0,0 +1,246 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; +import '../../../platform/publications/models/publication_open_submission.dart' + as _i2kst26h; + +/// What a contributor sees of a publication (specs/18 §3, §9.1). +abstract class PublicationCard + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationCard._({ + required this.publicId, + required this.name, + required this.shownHost, + required this.verified, + required this.siteHost, + required this.webhookHost, + this.termsUrl, + required this.fields, + required this.ownerName, + required this.enabled, + required this.consentNeeded, + required this.blocked, + required this.openSubmissions, + }); + + factory PublicationCard({ + required String publicId, + required String name, + required String shownHost, + required bool verified, + required String siteHost, + required String webhookHost, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required String ownerName, + required bool enabled, + required bool consentNeeded, + required bool blocked, + required List<_i2kst26h.PublicationOpenSubmission> openSubmissions, + }) = _PublicationCardImpl; + + factory PublicationCard.fromJson(Map jsonSerialization) { + return PublicationCard( + publicId: jsonSerialization['publicId'] as String, + name: jsonSerialization['name'] as String, + shownHost: jsonSerialization['shownHost'] as String, + verified: _is.BoolJsonExtension.fromJson(jsonSerialization['verified']), + siteHost: jsonSerialization['siteHost'] as String, + webhookHost: jsonSerialization['webhookHost'] as String, + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _il4umwa0.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + ownerName: jsonSerialization['ownerName'] as String, + enabled: _is.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + consentNeeded: _is.BoolJsonExtension.fromJson( + jsonSerialization['consentNeeded'], + ), + blocked: _is.BoolJsonExtension.fromJson(jsonSerialization['blocked']), + openSubmissions: _il4umwa0.Protocol() + .deserialize>( + jsonSerialization['openSubmissions'], + ), + ); + } + + String publicId; + + String name; + + /// The verified site host, or the webhook host when unverified. + String shownHost; + + bool verified; + + String siteHost; + + String webhookHost; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + String ownerName; + + bool enabled; + + /// The caller must agree first (never asked or what was agreed changed). + bool consentNeeded; + + /// The publication doesn't take stories from the caller. + bool blocked; + + /// The caller's drafts and stories with changes requested. + List<_i2kst26h.PublicationOpenSubmission> openSubmissions; + + /// Returns a shallow copy of this [PublicationCard] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationCard copyWith({ + String? publicId, + String? name, + String? shownHost, + bool? verified, + String? siteHost, + String? webhookHost, + String? termsUrl, + _i1a71r29.PublicationFields? fields, + String? ownerName, + bool? enabled, + bool? consentNeeded, + bool? blocked, + List<_i2kst26h.PublicationOpenSubmission>? openSubmissions, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationCard', + 'publicId': publicId, + 'name': name, + 'shownHost': shownHost, + 'verified': verified, + 'siteHost': siteHost, + 'webhookHost': webhookHost, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'ownerName': ownerName, + 'enabled': enabled, + 'consentNeeded': consentNeeded, + 'blocked': blocked, + 'openSubmissions': openSubmissions.toJson(valueToJson: (v) => v.toJson()), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationCard', + 'publicId': publicId, + 'name': name, + 'shownHost': shownHost, + 'verified': verified, + 'siteHost': siteHost, + 'webhookHost': webhookHost, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJsonForProtocol(), + 'ownerName': ownerName, + 'enabled': enabled, + 'consentNeeded': consentNeeded, + 'blocked': blocked, + 'openSubmissions': openSubmissions.toJson( + valueToJson: (v) => v.toJsonForProtocol(), + ), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationCardImpl extends PublicationCard { + _PublicationCardImpl({ + required String publicId, + required String name, + required String shownHost, + required bool verified, + required String siteHost, + required String webhookHost, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required String ownerName, + required bool enabled, + required bool consentNeeded, + required bool blocked, + required List<_i2kst26h.PublicationOpenSubmission> openSubmissions, + }) : super._( + publicId: publicId, + name: name, + shownHost: shownHost, + verified: verified, + siteHost: siteHost, + webhookHost: webhookHost, + termsUrl: termsUrl, + fields: fields, + ownerName: ownerName, + enabled: enabled, + consentNeeded: consentNeeded, + blocked: blocked, + openSubmissions: openSubmissions, + ); + + /// Returns a shallow copy of this [PublicationCard] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationCard copyWith({ + String? publicId, + String? name, + String? shownHost, + bool? verified, + String? siteHost, + String? webhookHost, + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + String? ownerName, + bool? enabled, + bool? consentNeeded, + bool? blocked, + List<_i2kst26h.PublicationOpenSubmission>? openSubmissions, + }) { + return PublicationCard( + publicId: publicId ?? this.publicId, + name: name ?? this.name, + shownHost: shownHost ?? this.shownHost, + verified: verified ?? this.verified, + siteHost: siteHost ?? this.siteHost, + webhookHost: webhookHost ?? this.webhookHost, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + ownerName: ownerName ?? this.ownerName, + enabled: enabled ?? this.enabled, + consentNeeded: consentNeeded ?? this.consentNeeded, + blocked: blocked ?? this.blocked, + openSubmissions: + openSubmissions ?? + this.openSubmissions.map((e0) => e0.copyWith()).toList(), + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_check_result.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_check_result.dart new file mode 100644 index 00000000..e1f05958 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_check_result.dart @@ -0,0 +1,114 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_settings.dart' + as _iyzf06w5; + +/// Result of *Verify* or *Send test* (specs/18 §8.1, §8.2). +abstract class PublicationCheckResult + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationCheckResult._({ + required this.ok, + this.message, + required this.settings, + }); + + factory PublicationCheckResult({ + required bool ok, + String? message, + required _iyzf06w5.PublicationSettings settings, + }) = _PublicationCheckResultImpl; + + factory PublicationCheckResult.fromJson( + Map jsonSerialization, + ) { + return PublicationCheckResult( + ok: _is.BoolJsonExtension.fromJson(jsonSerialization['ok']), + message: jsonSerialization['message'] as String?, + settings: _il4umwa0.Protocol().deserialize<_iyzf06w5.PublicationSettings>( + jsonSerialization['settings'], + ), + ); + } + + bool ok; + + /// What went wrong, for the owner. + String? message; + + _iyzf06w5.PublicationSettings settings; + + /// Returns a shallow copy of this [PublicationCheckResult] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationCheckResult copyWith({ + bool? ok, + String? message, + _iyzf06w5.PublicationSettings? settings, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationCheckResult', + 'ok': ok, + if (message != null) 'message': message, + 'settings': settings.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationCheckResult', + 'ok': ok, + if (message != null) 'message': message, + 'settings': settings.toJsonForProtocol(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationCheckResultImpl extends PublicationCheckResult { + _PublicationCheckResultImpl({ + required bool ok, + String? message, + required _iyzf06w5.PublicationSettings settings, + }) : super._( + ok: ok, + message: message, + settings: settings, + ); + + /// Returns a shallow copy of this [PublicationCheckResult] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationCheckResult copyWith({ + bool? ok, + Object? message = _Undefined, + _iyzf06w5.PublicationSettings? settings, + }) { + return PublicationCheckResult( + ok: ok ?? this.ok, + message: message is String? ? message : this.message, + settings: settings ?? this.settings.copyWith(), + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_consent.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_consent.dart new file mode 100644 index 00000000..3f4b00eb --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_consent.dart @@ -0,0 +1,713 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; + +/// A user's consent to write for a publication (specs/18 §3). Asked again +/// when the site host, webhook host or terms URL change ([consentKey]). +abstract class PublicationConsent + implements _is.TableRow, _is.ProtocolSerialization { + PublicationConsent._({ + this.id, + required this.publicationId, + required this.userId, + required this.consentKey, + required this.at, + }); + + factory PublicationConsent({ + int? id, + required int publicationId, + required int userId, + required String consentKey, + required DateTime at, + }) = _PublicationConsentImpl; + + factory PublicationConsent.fromJson(Map jsonSerialization) { + return PublicationConsent( + id: jsonSerialization['id'] as int?, + publicationId: jsonSerialization['publicationId'] as int, + userId: jsonSerialization['userId'] as int, + consentKey: jsonSerialization['consentKey'] as String, + at: _is.DateTimeJsonExtension.fromJson(jsonSerialization['at']), + ); + } + + static final t = PublicationConsentTable(); + + static const db = PublicationConsentRepository._(); + + @override + int? id; + + int publicationId; + + int userId; + + /// Hash of what was agreed to (shown host, webhook host, terms URL). + String consentKey; + + DateTime at; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [PublicationConsent] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationConsent copyWith({ + int? id, + int? publicationId, + int? userId, + String? consentKey, + DateTime? at, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationConsent', + if (id != null) 'id': id, + 'publicationId': publicationId, + 'userId': userId, + 'consentKey': consentKey, + 'at': at.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static PublicationConsentInclude include() { + return PublicationConsentInclude._(); + } + + static PublicationConsentIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + PublicationConsentInclude? include, + }) { + return PublicationConsentIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationConsentImpl extends PublicationConsent { + _PublicationConsentImpl({ + int? id, + required int publicationId, + required int userId, + required String consentKey, + required DateTime at, + }) : super._( + id: id, + publicationId: publicationId, + userId: userId, + consentKey: consentKey, + at: at, + ); + + /// Returns a shallow copy of this [PublicationConsent] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationConsent copyWith({ + Object? id = _Undefined, + int? publicationId, + int? userId, + String? consentKey, + DateTime? at, + }) { + return PublicationConsent( + id: id is int? ? id : this.id, + publicationId: publicationId ?? this.publicationId, + userId: userId ?? this.userId, + consentKey: consentKey ?? this.consentKey, + at: at ?? this.at, + ); + } +} + +class PublicationConsentUpdateTable + extends _is.UpdateTable { + PublicationConsentUpdateTable(super.table); + + _is.ColumnValue publicationId(int value) => _is.ColumnValue( + table.publicationId, + value, + ); + + _is.ColumnValue userId(int value) => _is.ColumnValue( + table.userId, + value, + ); + + _is.ColumnValue consentKey(String value) => _is.ColumnValue( + table.consentKey, + value, + ); + + _is.ColumnValue at(DateTime value) => _is.ColumnValue( + table.at, + value, + ); +} + +class PublicationConsentTable extends _is.Table { + PublicationConsentTable({super.tableRelation}) + : super(tableName: 'publication_consent') { + updateTable = PublicationConsentUpdateTable(this); + publicationId = _is.ColumnInt( + 'publicationId', + this, + ); + userId = _is.ColumnInt( + 'userId', + this, + ); + consentKey = _is.ColumnString( + 'consentKey', + this, + ); + at = _is.ColumnDateTime( + 'at', + this, + ); + } + + late final PublicationConsentUpdateTable updateTable; + + late final _is.ColumnInt publicationId; + + late final _is.ColumnInt userId; + + /// Hash of what was agreed to (shown host, webhook host, terms URL). + late final _is.ColumnString consentKey; + + late final _is.ColumnDateTime at; + + @override + List<_is.Column> get columns => [ + id, + publicationId, + userId, + consentKey, + at, + ]; +} + +class PublicationConsentInclude extends _is.IncludeObject { + PublicationConsentInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => PublicationConsent.t; +} + +class PublicationConsentIncludeList extends _is.IncludeList { + PublicationConsentIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(PublicationConsent.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => PublicationConsent.t; +} + +class PublicationConsentRepository { + const PublicationConsentRepository._(); + + /// Returns a list of [PublicationConsent]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(PublicationConsent.t), + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [PublicationConsent]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `PublicationConsent.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(PublicationConsent.t), + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [PublicationConsent] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(PublicationConsent.t), + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [PublicationConsent] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [PublicationConsent]s in the list and returns the inserted rows. + /// + /// The returned [PublicationConsent]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [PublicationConsent] and returns the inserted row. + /// + /// The returned [PublicationConsent] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + PublicationConsent row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [PublicationConsent]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [PublicationConsent]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(PublicationConsent.t), + updateColumns: updateColumns?.call(PublicationConsent.t), + updateWhere: updateWhere?.call(PublicationConsent.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [PublicationConsent] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [PublicationConsent] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + PublicationConsent row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(PublicationConsent.t), + updateColumns: updateColumns?.call(PublicationConsent.t), + updateWhere: updateWhere?.call(PublicationConsent.t), + transaction: transaction, + ); + } + + /// Updates all [PublicationConsent]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(PublicationConsent.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [PublicationConsent]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + PublicationConsent row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(PublicationConsent.t), + transaction: transaction, + ); + } + + /// Updates a single [PublicationConsent] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder + columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(PublicationConsent.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [PublicationConsent]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder + columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(PublicationConsent.t.updateTable), + where: where(PublicationConsent.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [PublicationConsent]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [PublicationConsent]. + Future deleteRow( + _is.DatabaseSession session, + PublicationConsent row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(PublicationConsent.t), + orderBy: orderBy?.call(PublicationConsent.t), + orderByList: orderByList?.call(PublicationConsent.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(PublicationConsent.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [PublicationConsent] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(PublicationConsent.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_delivery.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_delivery.dart new file mode 100644 index 00000000..d87e7af6 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_delivery.dart @@ -0,0 +1,979 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; + +/// A webhook in the outbox (specs/18 §7.2): retried with the same id until +/// the blog answers 2xx or the retries run out. +abstract class PublicationDelivery + implements _is.TableRow, _is.ProtocolSerialization { + PublicationDelivery._({ + this.id, + required this.publicationId, + this.submissionId, + required this.webhookId, + required this.type, + this.sequence, + required this.payload, + int? attempts, + this.nextAttemptAt, + this.leaseUntil, + this.lastStatus, + this.lastError, + this.deliveredAt, + this.failedAt, + required this.createdAt, + }) : attempts = attempts ?? 0; + + factory PublicationDelivery({ + int? id, + required int publicationId, + int? submissionId, + required String webhookId, + required String type, + int? sequence, + required String payload, + int? attempts, + DateTime? nextAttemptAt, + DateTime? leaseUntil, + int? lastStatus, + String? lastError, + DateTime? deliveredAt, + DateTime? failedAt, + required DateTime createdAt, + }) = _PublicationDeliveryImpl; + + factory PublicationDelivery.fromJson(Map jsonSerialization) { + return PublicationDelivery( + id: jsonSerialization['id'] as int?, + publicationId: jsonSerialization['publicationId'] as int, + submissionId: jsonSerialization['submissionId'] as int?, + webhookId: jsonSerialization['webhookId'] as String, + type: jsonSerialization['type'] as String, + sequence: jsonSerialization['sequence'] as int?, + payload: jsonSerialization['payload'] as String, + attempts: jsonSerialization['attempts'] as int?, + nextAttemptAt: jsonSerialization['nextAttemptAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['nextAttemptAt'], + ), + leaseUntil: jsonSerialization['leaseUntil'] == null + ? null + : _is.DateTimeJsonExtension.fromJson(jsonSerialization['leaseUntil']), + lastStatus: jsonSerialization['lastStatus'] as int?, + lastError: jsonSerialization['lastError'] as String?, + deliveredAt: jsonSerialization['deliveredAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['deliveredAt'], + ), + failedAt: jsonSerialization['failedAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson(jsonSerialization['failedAt']), + createdAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + ); + } + + static final t = PublicationDeliveryTable(); + + static const db = PublicationDeliveryRepository._(); + + @override + int? id; + + int publicationId; + + int? submissionId; + + /// "msg_", the `webhook-id` header; stable across retries. + String webhookId; + + String type; + + /// The submit's sequence of a `submission.submitted`. + int? sequence; + + /// The JSON body. + String payload; + + int attempts; + + /// Null once delivered or given up. + DateTime? nextAttemptAt; + + /// Lease of the instance sending it (specs/13 §4). + DateTime? leaseUntil; + + /// HTTP status of the last attempt; 0 = network error or timeout. + int? lastStatus; + + String? lastError; + + DateTime? deliveredAt; + + DateTime? failedAt; + + DateTime createdAt; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [PublicationDelivery] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationDelivery copyWith({ + int? id, + int? publicationId, + int? submissionId, + String? webhookId, + String? type, + int? sequence, + String? payload, + int? attempts, + DateTime? nextAttemptAt = const _is.$UndefinedDateTime(), + DateTime? leaseUntil = const _is.$UndefinedDateTime(), + int? lastStatus, + String? lastError, + DateTime? deliveredAt = const _is.$UndefinedDateTime(), + DateTime? failedAt = const _is.$UndefinedDateTime(), + DateTime? createdAt, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationDelivery', + if (id != null) 'id': id, + 'publicationId': publicationId, + if (submissionId != null) 'submissionId': submissionId, + 'webhookId': webhookId, + 'type': type, + if (sequence != null) 'sequence': sequence, + 'payload': payload, + 'attempts': attempts, + if (nextAttemptAt != null) 'nextAttemptAt': nextAttemptAt?.toJson(), + if (leaseUntil != null) 'leaseUntil': leaseUntil?.toJson(), + if (lastStatus != null) 'lastStatus': lastStatus, + if (lastError != null) 'lastError': lastError, + if (deliveredAt != null) 'deliveredAt': deliveredAt?.toJson(), + if (failedAt != null) 'failedAt': failedAt?.toJson(), + 'createdAt': createdAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static PublicationDeliveryInclude include() { + return PublicationDeliveryInclude._(); + } + + static PublicationDeliveryIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + PublicationDeliveryInclude? include, + }) { + return PublicationDeliveryIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationDeliveryImpl extends PublicationDelivery { + _PublicationDeliveryImpl({ + int? id, + required int publicationId, + int? submissionId, + required String webhookId, + required String type, + int? sequence, + required String payload, + int? attempts, + DateTime? nextAttemptAt, + DateTime? leaseUntil, + int? lastStatus, + String? lastError, + DateTime? deliveredAt, + DateTime? failedAt, + required DateTime createdAt, + }) : super._( + id: id, + publicationId: publicationId, + submissionId: submissionId, + webhookId: webhookId, + type: type, + sequence: sequence, + payload: payload, + attempts: attempts, + nextAttemptAt: nextAttemptAt, + leaseUntil: leaseUntil, + lastStatus: lastStatus, + lastError: lastError, + deliveredAt: deliveredAt, + failedAt: failedAt, + createdAt: createdAt, + ); + + /// Returns a shallow copy of this [PublicationDelivery] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationDelivery copyWith({ + Object? id = _Undefined, + int? publicationId, + Object? submissionId = _Undefined, + String? webhookId, + String? type, + Object? sequence = _Undefined, + String? payload, + int? attempts, + DateTime? nextAttemptAt = const _is.$UndefinedDateTime(), + DateTime? leaseUntil = const _is.$UndefinedDateTime(), + Object? lastStatus = _Undefined, + Object? lastError = _Undefined, + DateTime? deliveredAt = const _is.$UndefinedDateTime(), + DateTime? failedAt = const _is.$UndefinedDateTime(), + DateTime? createdAt, + }) { + return PublicationDelivery( + id: id is int? ? id : this.id, + publicationId: publicationId ?? this.publicationId, + submissionId: submissionId is int? ? submissionId : this.submissionId, + webhookId: webhookId ?? this.webhookId, + type: type ?? this.type, + sequence: sequence is int? ? sequence : this.sequence, + payload: payload ?? this.payload, + attempts: attempts ?? this.attempts, + nextAttemptAt: nextAttemptAt is _is.UndefinedSentinel + ? this.nextAttemptAt + : nextAttemptAt, + leaseUntil: leaseUntil is _is.UndefinedSentinel + ? this.leaseUntil + : leaseUntil, + lastStatus: lastStatus is int? ? lastStatus : this.lastStatus, + lastError: lastError is String? ? lastError : this.lastError, + deliveredAt: deliveredAt is _is.UndefinedSentinel + ? this.deliveredAt + : deliveredAt, + failedAt: failedAt is _is.UndefinedSentinel ? this.failedAt : failedAt, + createdAt: createdAt ?? this.createdAt, + ); + } +} + +class PublicationDeliveryUpdateTable + extends _is.UpdateTable { + PublicationDeliveryUpdateTable(super.table); + + _is.ColumnValue publicationId(int value) => _is.ColumnValue( + table.publicationId, + value, + ); + + _is.ColumnValue submissionId(int? value) => _is.ColumnValue( + table.submissionId, + value, + ); + + _is.ColumnValue webhookId(String value) => _is.ColumnValue( + table.webhookId, + value, + ); + + _is.ColumnValue type(String value) => _is.ColumnValue( + table.type, + value, + ); + + _is.ColumnValue sequence(int? value) => _is.ColumnValue( + table.sequence, + value, + ); + + _is.ColumnValue payload(String value) => _is.ColumnValue( + table.payload, + value, + ); + + _is.ColumnValue attempts(int value) => _is.ColumnValue( + table.attempts, + value, + ); + + _is.ColumnValue nextAttemptAt(DateTime? value) => + _is.ColumnValue( + table.nextAttemptAt, + value, + ); + + _is.ColumnValue leaseUntil(DateTime? value) => + _is.ColumnValue( + table.leaseUntil, + value, + ); + + _is.ColumnValue lastStatus(int? value) => _is.ColumnValue( + table.lastStatus, + value, + ); + + _is.ColumnValue lastError(String? value) => _is.ColumnValue( + table.lastError, + value, + ); + + _is.ColumnValue deliveredAt(DateTime? value) => + _is.ColumnValue( + table.deliveredAt, + value, + ); + + _is.ColumnValue failedAt(DateTime? value) => + _is.ColumnValue( + table.failedAt, + value, + ); + + _is.ColumnValue createdAt(DateTime value) => + _is.ColumnValue( + table.createdAt, + value, + ); +} + +class PublicationDeliveryTable extends _is.Table { + PublicationDeliveryTable({super.tableRelation}) + : super(tableName: 'publication_delivery') { + updateTable = PublicationDeliveryUpdateTable(this); + publicationId = _is.ColumnInt( + 'publicationId', + this, + ); + submissionId = _is.ColumnInt( + 'submissionId', + this, + ); + webhookId = _is.ColumnString( + 'webhookId', + this, + ); + type = _is.ColumnString( + 'type', + this, + ); + sequence = _is.ColumnInt( + 'sequence', + this, + ); + payload = _is.ColumnString( + 'payload', + this, + ); + attempts = _is.ColumnInt( + 'attempts', + this, + hasDefault: true, + ); + nextAttemptAt = _is.ColumnDateTime( + 'nextAttemptAt', + this, + ); + leaseUntil = _is.ColumnDateTime( + 'leaseUntil', + this, + ); + lastStatus = _is.ColumnInt( + 'lastStatus', + this, + ); + lastError = _is.ColumnString( + 'lastError', + this, + ); + deliveredAt = _is.ColumnDateTime( + 'deliveredAt', + this, + ); + failedAt = _is.ColumnDateTime( + 'failedAt', + this, + ); + createdAt = _is.ColumnDateTime( + 'createdAt', + this, + ); + } + + late final PublicationDeliveryUpdateTable updateTable; + + late final _is.ColumnInt publicationId; + + late final _is.ColumnInt submissionId; + + /// "msg_", the `webhook-id` header; stable across retries. + late final _is.ColumnString webhookId; + + late final _is.ColumnString type; + + /// The submit's sequence of a `submission.submitted`. + late final _is.ColumnInt sequence; + + /// The JSON body. + late final _is.ColumnString payload; + + late final _is.ColumnInt attempts; + + /// Null once delivered or given up. + late final _is.ColumnDateTime nextAttemptAt; + + /// Lease of the instance sending it (specs/13 §4). + late final _is.ColumnDateTime leaseUntil; + + /// HTTP status of the last attempt; 0 = network error or timeout. + late final _is.ColumnInt lastStatus; + + late final _is.ColumnString lastError; + + late final _is.ColumnDateTime deliveredAt; + + late final _is.ColumnDateTime failedAt; + + late final _is.ColumnDateTime createdAt; + + @override + List<_is.Column> get columns => [ + id, + publicationId, + submissionId, + webhookId, + type, + sequence, + payload, + attempts, + nextAttemptAt, + leaseUntil, + lastStatus, + lastError, + deliveredAt, + failedAt, + createdAt, + ]; +} + +class PublicationDeliveryInclude extends _is.IncludeObject { + PublicationDeliveryInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => PublicationDelivery.t; +} + +class PublicationDeliveryIncludeList extends _is.IncludeList { + PublicationDeliveryIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(PublicationDelivery.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => PublicationDelivery.t; +} + +class PublicationDeliveryRepository { + const PublicationDeliveryRepository._(); + + /// Returns a list of [PublicationDelivery]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(PublicationDelivery.t), + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [PublicationDelivery]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `PublicationDelivery.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(PublicationDelivery.t), + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [PublicationDelivery] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(PublicationDelivery.t), + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [PublicationDelivery] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [PublicationDelivery]s in the list and returns the inserted rows. + /// + /// The returned [PublicationDelivery]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [PublicationDelivery] and returns the inserted row. + /// + /// The returned [PublicationDelivery] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + PublicationDelivery row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [PublicationDelivery]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [PublicationDelivery]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(PublicationDelivery.t), + updateColumns: updateColumns?.call(PublicationDelivery.t), + updateWhere: updateWhere?.call(PublicationDelivery.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [PublicationDelivery] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [PublicationDelivery] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + PublicationDelivery row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(PublicationDelivery.t), + updateColumns: updateColumns?.call(PublicationDelivery.t), + updateWhere: updateWhere?.call(PublicationDelivery.t), + transaction: transaction, + ); + } + + /// Updates all [PublicationDelivery]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(PublicationDelivery.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [PublicationDelivery]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + PublicationDelivery row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(PublicationDelivery.t), + transaction: transaction, + ); + } + + /// Updates a single [PublicationDelivery] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder + columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(PublicationDelivery.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [PublicationDelivery]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder + columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(PublicationDelivery.t.updateTable), + where: where(PublicationDelivery.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [PublicationDelivery]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [PublicationDelivery]. + Future deleteRow( + _is.DatabaseSession session, + PublicationDelivery row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(PublicationDelivery.t), + orderBy: orderBy?.call(PublicationDelivery.t), + orderByList: orderByList?.call(PublicationDelivery.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(PublicationDelivery.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [PublicationDelivery] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(PublicationDelivery.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_delivery_view.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_delivery_view.dart new file mode 100644 index 00000000..58fef785 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_delivery_view.dart @@ -0,0 +1,196 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +/// A webhook delivery in the owner's *Deliveries* list (specs/18 §8.1). +abstract class PublicationDeliveryView + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationDeliveryView._({ + required this.webhookId, + required this.type, + required this.createdAt, + required this.attempts, + this.lastStatus, + this.lastError, + this.deliveredAt, + this.failedAt, + this.nextAttemptAt, + }); + + factory PublicationDeliveryView({ + required String webhookId, + required String type, + required DateTime createdAt, + required int attempts, + int? lastStatus, + String? lastError, + DateTime? deliveredAt, + DateTime? failedAt, + DateTime? nextAttemptAt, + }) = _PublicationDeliveryViewImpl; + + factory PublicationDeliveryView.fromJson( + Map jsonSerialization, + ) { + return PublicationDeliveryView( + webhookId: jsonSerialization['webhookId'] as String, + type: jsonSerialization['type'] as String, + createdAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + attempts: jsonSerialization['attempts'] as int, + lastStatus: jsonSerialization['lastStatus'] as int?, + lastError: jsonSerialization['lastError'] as String?, + deliveredAt: jsonSerialization['deliveredAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['deliveredAt'], + ), + failedAt: jsonSerialization['failedAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson(jsonSerialization['failedAt']), + nextAttemptAt: jsonSerialization['nextAttemptAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['nextAttemptAt'], + ), + ); + } + + String webhookId; + + String type; + + DateTime createdAt; + + int attempts; + + int? lastStatus; + + String? lastError; + + DateTime? deliveredAt; + + DateTime? failedAt; + + DateTime? nextAttemptAt; + + /// Returns a shallow copy of this [PublicationDeliveryView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationDeliveryView copyWith({ + String? webhookId, + String? type, + DateTime? createdAt, + int? attempts, + int? lastStatus, + String? lastError, + DateTime? deliveredAt = const _is.$UndefinedDateTime(), + DateTime? failedAt = const _is.$UndefinedDateTime(), + DateTime? nextAttemptAt = const _is.$UndefinedDateTime(), + }); + @override + Map toJson() { + return { + '__className__': 'PublicationDeliveryView', + 'webhookId': webhookId, + 'type': type, + 'createdAt': createdAt.toJson(), + 'attempts': attempts, + if (lastStatus != null) 'lastStatus': lastStatus, + if (lastError != null) 'lastError': lastError, + if (deliveredAt != null) 'deliveredAt': deliveredAt?.toJson(), + if (failedAt != null) 'failedAt': failedAt?.toJson(), + if (nextAttemptAt != null) 'nextAttemptAt': nextAttemptAt?.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationDeliveryView', + 'webhookId': webhookId, + 'type': type, + 'createdAt': createdAt.toJson(), + 'attempts': attempts, + if (lastStatus != null) 'lastStatus': lastStatus, + if (lastError != null) 'lastError': lastError, + if (deliveredAt != null) 'deliveredAt': deliveredAt?.toJson(), + if (failedAt != null) 'failedAt': failedAt?.toJson(), + if (nextAttemptAt != null) 'nextAttemptAt': nextAttemptAt?.toJson(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationDeliveryViewImpl extends PublicationDeliveryView { + _PublicationDeliveryViewImpl({ + required String webhookId, + required String type, + required DateTime createdAt, + required int attempts, + int? lastStatus, + String? lastError, + DateTime? deliveredAt, + DateTime? failedAt, + DateTime? nextAttemptAt, + }) : super._( + webhookId: webhookId, + type: type, + createdAt: createdAt, + attempts: attempts, + lastStatus: lastStatus, + lastError: lastError, + deliveredAt: deliveredAt, + failedAt: failedAt, + nextAttemptAt: nextAttemptAt, + ); + + /// Returns a shallow copy of this [PublicationDeliveryView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationDeliveryView copyWith({ + String? webhookId, + String? type, + DateTime? createdAt, + int? attempts, + Object? lastStatus = _Undefined, + Object? lastError = _Undefined, + DateTime? deliveredAt = const _is.$UndefinedDateTime(), + DateTime? failedAt = const _is.$UndefinedDateTime(), + DateTime? nextAttemptAt = const _is.$UndefinedDateTime(), + }) { + return PublicationDeliveryView( + webhookId: webhookId ?? this.webhookId, + type: type ?? this.type, + createdAt: createdAt ?? this.createdAt, + attempts: attempts ?? this.attempts, + lastStatus: lastStatus is int? ? lastStatus : this.lastStatus, + lastError: lastError is String? ? lastError : this.lastError, + deliveredAt: deliveredAt is _is.UndefinedSentinel + ? this.deliveredAt + : deliveredAt, + failedAt: failedAt is _is.UndefinedSentinel ? this.failedAt : failedAt, + nextAttemptAt: nextAttemptAt is _is.UndefinedSentinel + ? this.nextAttemptAt + : nextAttemptAt, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_field_mode.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_field_mode.dart new file mode 100644 index 00000000..0ae9daf2 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_field_mode.dart @@ -0,0 +1,41 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +/// Whether a submission field is shown and required (specs/18 §8.1). +enum PublicationFieldMode implements _is.SerializableModel { + off, + optional, + required; + + static PublicationFieldMode fromJson(String name) { + switch (name) { + case 'off': + return PublicationFieldMode.off; + case 'optional': + return PublicationFieldMode.optional; + case 'required': + return PublicationFieldMode.required; + default: + throw ArgumentError( + 'Value "$name" cannot be converted to "PublicationFieldMode"', + ); + } + } + + @override + String toJson() => name; + + @override + String toString() => name; +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_fields.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_fields.dart new file mode 100644 index 00000000..f442b141 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_fields.dart @@ -0,0 +1,157 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_field_mode.dart' + as _i5yv7v4s; + +/// Which submission fields a publication asks for (specs/18 §8.1). The +/// title is always asked for and required. +abstract class PublicationFields + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationFields._({ + required this.summary, + required this.tags, + required this.allowedTags, + required this.coverImage, + required this.authorBio, + required this.note, + }); + + factory PublicationFields({ + required _i5yv7v4s.PublicationFieldMode summary, + required _i5yv7v4s.PublicationFieldMode tags, + required List allowedTags, + required _i5yv7v4s.PublicationFieldMode coverImage, + required _i5yv7v4s.PublicationFieldMode authorBio, + required _i5yv7v4s.PublicationFieldMode note, + }) = _PublicationFieldsImpl; + + factory PublicationFields.fromJson(Map jsonSerialization) { + return PublicationFields( + summary: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['summary'] as String), + ), + tags: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['tags'] as String), + ), + allowedTags: _il4umwa0.Protocol().deserialize>( + jsonSerialization['allowedTags'], + ), + coverImage: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['coverImage'] as String), + ), + authorBio: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['authorBio'] as String), + ), + note: _i5yv7v4s.PublicationFieldMode.fromJson( + (jsonSerialization['note'] as String), + ), + ); + } + + _i5yv7v4s.PublicationFieldMode summary; + + _i5yv7v4s.PublicationFieldMode tags; + + /// When not empty, tags must come from this list. + List allowedTags; + + _i5yv7v4s.PublicationFieldMode coverImage; + + _i5yv7v4s.PublicationFieldMode authorBio; + + _i5yv7v4s.PublicationFieldMode note; + + /// Returns a shallow copy of this [PublicationFields] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationFields copyWith({ + _i5yv7v4s.PublicationFieldMode? summary, + _i5yv7v4s.PublicationFieldMode? tags, + List? allowedTags, + _i5yv7v4s.PublicationFieldMode? coverImage, + _i5yv7v4s.PublicationFieldMode? authorBio, + _i5yv7v4s.PublicationFieldMode? note, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationFields', + 'summary': summary.toJson(), + 'tags': tags.toJson(), + 'allowedTags': allowedTags.toJson(), + 'coverImage': coverImage.toJson(), + 'authorBio': authorBio.toJson(), + 'note': note.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationFields', + 'summary': summary.toJson(), + 'tags': tags.toJson(), + 'allowedTags': allowedTags.toJson(), + 'coverImage': coverImage.toJson(), + 'authorBio': authorBio.toJson(), + 'note': note.toJson(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _PublicationFieldsImpl extends PublicationFields { + _PublicationFieldsImpl({ + required _i5yv7v4s.PublicationFieldMode summary, + required _i5yv7v4s.PublicationFieldMode tags, + required List allowedTags, + required _i5yv7v4s.PublicationFieldMode coverImage, + required _i5yv7v4s.PublicationFieldMode authorBio, + required _i5yv7v4s.PublicationFieldMode note, + }) : super._( + summary: summary, + tags: tags, + allowedTags: allowedTags, + coverImage: coverImage, + authorBio: authorBio, + note: note, + ); + + /// Returns a shallow copy of this [PublicationFields] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationFields copyWith({ + _i5yv7v4s.PublicationFieldMode? summary, + _i5yv7v4s.PublicationFieldMode? tags, + List? allowedTags, + _i5yv7v4s.PublicationFieldMode? coverImage, + _i5yv7v4s.PublicationFieldMode? authorBio, + _i5yv7v4s.PublicationFieldMode? note, + }) { + return PublicationFields( + summary: summary ?? this.summary, + tags: tags ?? this.tags, + allowedTags: allowedTags ?? this.allowedTags.map((e0) => e0).toList(), + coverImage: coverImage ?? this.coverImage, + authorBio: authorBio ?? this.authorBio, + note: note ?? this.note, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_input.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_input.dart new file mode 100644 index 00000000..f59046ab --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_input.dart @@ -0,0 +1,167 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; + +/// Create or update a publication (specs/18 §8.1). +abstract class PublicationInput + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationInput._({ + required this.name, + required this.siteUrl, + required this.webhookUrl, + this.templateItemUuid, + this.termsUrl, + required this.fields, + required this.enabled, + }); + + factory PublicationInput({ + required String name, + required String siteUrl, + required String webhookUrl, + _is.UuidValue? templateItemUuid, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required bool enabled, + }) = _PublicationInputImpl; + + factory PublicationInput.fromJson(Map jsonSerialization) { + return PublicationInput( + name: jsonSerialization['name'] as String, + siteUrl: jsonSerialization['siteUrl'] as String, + webhookUrl: jsonSerialization['webhookUrl'] as String, + templateItemUuid: jsonSerialization['templateItemUuid'] == null + ? null + : _is.UuidValueJsonExtension.fromJson( + jsonSerialization['templateItemUuid'], + ), + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _il4umwa0.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + enabled: _is.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + ); + } + + String name; + + String siteUrl; + + String webhookUrl; + + _is.UuidValue? templateItemUuid; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + bool enabled; + + /// Returns a shallow copy of this [PublicationInput] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationInput copyWith({ + String? name, + String? siteUrl, + String? webhookUrl, + _is.UuidValue? templateItemUuid = const _is.$UndefinedUuidValue(), + String? termsUrl, + _i1a71r29.PublicationFields? fields, + bool? enabled, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationInput', + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'enabled': enabled, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationInput', + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJsonForProtocol(), + 'enabled': enabled, + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationInputImpl extends PublicationInput { + _PublicationInputImpl({ + required String name, + required String siteUrl, + required String webhookUrl, + _is.UuidValue? templateItemUuid, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required bool enabled, + }) : super._( + name: name, + siteUrl: siteUrl, + webhookUrl: webhookUrl, + templateItemUuid: templateItemUuid, + termsUrl: termsUrl, + fields: fields, + enabled: enabled, + ); + + /// Returns a shallow copy of this [PublicationInput] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationInput copyWith({ + String? name, + String? siteUrl, + String? webhookUrl, + _is.UuidValue? templateItemUuid = const _is.$UndefinedUuidValue(), + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + bool? enabled, + }) { + return PublicationInput( + name: name ?? this.name, + siteUrl: siteUrl ?? this.siteUrl, + webhookUrl: webhookUrl ?? this.webhookUrl, + templateItemUuid: templateItemUuid is _is.UndefinedSentinel + ? this.templateItemUuid + : templateItemUuid, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + enabled: enabled ?? this.enabled, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_moderator.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_moderator.dart new file mode 100644 index 00000000..b91f3226 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_moderator.dart @@ -0,0 +1,693 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; + +/// A moderator of a publication (specs/18 §5.1): gets Commenter on the +/// publication's open submissions. Pending ([userId] null) until the +/// email signs up. +abstract class PublicationModerator + implements _is.TableRow, _is.ProtocolSerialization { + PublicationModerator._({ + this.id, + required this.publicationId, + this.userId, + required this.email, + }); + + factory PublicationModerator({ + int? id, + required int publicationId, + int? userId, + required String email, + }) = _PublicationModeratorImpl; + + factory PublicationModerator.fromJson( + Map jsonSerialization, + ) { + return PublicationModerator( + id: jsonSerialization['id'] as int?, + publicationId: jsonSerialization['publicationId'] as int, + userId: jsonSerialization['userId'] as int?, + email: jsonSerialization['email'] as String, + ); + } + + static final t = PublicationModeratorTable(); + + static const db = PublicationModeratorRepository._(); + + @override + int? id; + + int publicationId; + + int? userId; + + /// Lower-case email; kept after sign-up for display. + String email; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [PublicationModerator] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationModerator copyWith({ + int? id, + int? publicationId, + int? userId, + String? email, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationModerator', + if (id != null) 'id': id, + 'publicationId': publicationId, + if (userId != null) 'userId': userId, + 'email': email, + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static PublicationModeratorInclude include() { + return PublicationModeratorInclude._(); + } + + static PublicationModeratorIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + PublicationModeratorInclude? include, + }) { + return PublicationModeratorIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationModeratorImpl extends PublicationModerator { + _PublicationModeratorImpl({ + int? id, + required int publicationId, + int? userId, + required String email, + }) : super._( + id: id, + publicationId: publicationId, + userId: userId, + email: email, + ); + + /// Returns a shallow copy of this [PublicationModerator] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationModerator copyWith({ + Object? id = _Undefined, + int? publicationId, + Object? userId = _Undefined, + String? email, + }) { + return PublicationModerator( + id: id is int? ? id : this.id, + publicationId: publicationId ?? this.publicationId, + userId: userId is int? ? userId : this.userId, + email: email ?? this.email, + ); + } +} + +class PublicationModeratorUpdateTable + extends _is.UpdateTable { + PublicationModeratorUpdateTable(super.table); + + _is.ColumnValue publicationId(int value) => _is.ColumnValue( + table.publicationId, + value, + ); + + _is.ColumnValue userId(int? value) => _is.ColumnValue( + table.userId, + value, + ); + + _is.ColumnValue email(String value) => _is.ColumnValue( + table.email, + value, + ); +} + +class PublicationModeratorTable extends _is.Table { + PublicationModeratorTable({super.tableRelation}) + : super(tableName: 'publication_moderator') { + updateTable = PublicationModeratorUpdateTable(this); + publicationId = _is.ColumnInt( + 'publicationId', + this, + ); + userId = _is.ColumnInt( + 'userId', + this, + ); + email = _is.ColumnString( + 'email', + this, + ); + } + + late final PublicationModeratorUpdateTable updateTable; + + late final _is.ColumnInt publicationId; + + late final _is.ColumnInt userId; + + /// Lower-case email; kept after sign-up for display. + late final _is.ColumnString email; + + @override + List<_is.Column> get columns => [ + id, + publicationId, + userId, + email, + ]; +} + +class PublicationModeratorInclude extends _is.IncludeObject { + PublicationModeratorInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => PublicationModerator.t; +} + +class PublicationModeratorIncludeList extends _is.IncludeList { + PublicationModeratorIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(PublicationModerator.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => PublicationModerator.t; +} + +class PublicationModeratorRepository { + const PublicationModeratorRepository._(); + + /// Returns a list of [PublicationModerator]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(PublicationModerator.t), + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [PublicationModerator]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `PublicationModerator.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(PublicationModerator.t), + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [PublicationModerator] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(PublicationModerator.t), + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [PublicationModerator] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [PublicationModerator]s in the list and returns the inserted rows. + /// + /// The returned [PublicationModerator]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [PublicationModerator] and returns the inserted row. + /// + /// The returned [PublicationModerator] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + PublicationModerator row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [PublicationModerator]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [PublicationModerator]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(PublicationModerator.t), + updateColumns: updateColumns?.call(PublicationModerator.t), + updateWhere: updateWhere?.call(PublicationModerator.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [PublicationModerator] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [PublicationModerator] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + PublicationModerator row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(PublicationModerator.t), + updateColumns: updateColumns?.call(PublicationModerator.t), + updateWhere: updateWhere?.call(PublicationModerator.t), + transaction: transaction, + ); + } + + /// Updates all [PublicationModerator]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(PublicationModerator.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [PublicationModerator]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + PublicationModerator row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(PublicationModerator.t), + transaction: transaction, + ); + } + + /// Updates a single [PublicationModerator] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder + columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(PublicationModerator.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [PublicationModerator]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder + columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(PublicationModerator.t.updateTable), + where: where(PublicationModerator.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [PublicationModerator]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [PublicationModerator]. + Future deleteRow( + _is.DatabaseSession session, + PublicationModerator row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(PublicationModerator.t), + orderBy: orderBy?.call(PublicationModerator.t), + orderByList: orderByList?.call(PublicationModerator.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(PublicationModerator.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [PublicationModerator] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(PublicationModerator.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_moderator_view.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_moderator_view.dart new file mode 100644 index 00000000..9081e769 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_moderator_view.dart @@ -0,0 +1,96 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +abstract class PublicationModeratorView + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationModeratorView._({ + required this.email, + this.name, + }); + + factory PublicationModeratorView({ + required String email, + String? name, + }) = _PublicationModeratorViewImpl; + + factory PublicationModeratorView.fromJson( + Map jsonSerialization, + ) { + return PublicationModeratorView( + email: jsonSerialization['email'] as String, + name: jsonSerialization['name'] as String?, + ); + } + + String email; + + /// Null while no account has this email. + String? name; + + /// Returns a shallow copy of this [PublicationModeratorView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationModeratorView copyWith({ + String? email, + String? name, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationModeratorView', + 'email': email, + if (name != null) 'name': name, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationModeratorView', + 'email': email, + if (name != null) 'name': name, + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationModeratorViewImpl extends PublicationModeratorView { + _PublicationModeratorViewImpl({ + required String email, + String? name, + }) : super._( + email: email, + name: name, + ); + + /// Returns a shallow copy of this [PublicationModeratorView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationModeratorView copyWith({ + String? email, + Object? name = _Undefined, + }) { + return PublicationModeratorView( + email: email ?? this.email, + name: name is String? ? name : this.name, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_open_submission.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_open_submission.dart new file mode 100644 index 00000000..cd307a9b --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_open_submission.dart @@ -0,0 +1,126 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import '../../../platform/publications/models/submission_status.dart' + as _igclxad1; + +/// A story the caller can continue (specs/18 §3). +abstract class PublicationOpenSubmission + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationOpenSubmission._({ + required this.itemUuid, + required this.name, + required this.status, + required this.updatedAt, + }); + + factory PublicationOpenSubmission({ + required _is.UuidValue itemUuid, + required String name, + required _igclxad1.SubmissionStatus status, + required DateTime updatedAt, + }) = _PublicationOpenSubmissionImpl; + + factory PublicationOpenSubmission.fromJson( + Map jsonSerialization, + ) { + return PublicationOpenSubmission( + itemUuid: _is.UuidValueJsonExtension.fromJson( + jsonSerialization['itemUuid'], + ), + name: jsonSerialization['name'] as String, + status: _igclxad1.SubmissionStatus.fromJson( + (jsonSerialization['status'] as String), + ), + updatedAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['updatedAt'], + ), + ); + } + + _is.UuidValue itemUuid; + + String name; + + _igclxad1.SubmissionStatus status; + + DateTime updatedAt; + + /// Returns a shallow copy of this [PublicationOpenSubmission] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationOpenSubmission copyWith({ + _is.UuidValue? itemUuid, + String? name, + _igclxad1.SubmissionStatus? status, + DateTime? updatedAt, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationOpenSubmission', + 'itemUuid': itemUuid.toJson(), + 'name': name, + 'status': status.toJson(), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationOpenSubmission', + 'itemUuid': itemUuid.toJson(), + 'name': name, + 'status': status.toJson(), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _PublicationOpenSubmissionImpl extends PublicationOpenSubmission { + _PublicationOpenSubmissionImpl({ + required _is.UuidValue itemUuid, + required String name, + required _igclxad1.SubmissionStatus status, + required DateTime updatedAt, + }) : super._( + itemUuid: itemUuid, + name: name, + status: status, + updatedAt: updatedAt, + ); + + /// Returns a shallow copy of this [PublicationOpenSubmission] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationOpenSubmission copyWith({ + _is.UuidValue? itemUuid, + String? name, + _igclxad1.SubmissionStatus? status, + DateTime? updatedAt, + }) { + return PublicationOpenSubmission( + itemUuid: itemUuid ?? this.itemUuid, + name: name ?? this.name, + status: status ?? this.status, + updatedAt: updatedAt ?? this.updatedAt, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_secret.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_secret.dart new file mode 100644 index 00000000..9bf0e3a0 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_secret.dart @@ -0,0 +1,98 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_settings.dart' + as _iyzf06w5; + +/// A secret shown once (specs/18 §8.1): the signing secret at creation or +/// rotation, or an API key. +abstract class PublicationSecret + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationSecret._({ + required this.settings, + required this.secret, + }); + + factory PublicationSecret({ + required _iyzf06w5.PublicationSettings settings, + required String secret, + }) = _PublicationSecretImpl; + + factory PublicationSecret.fromJson(Map jsonSerialization) { + return PublicationSecret( + settings: _il4umwa0.Protocol().deserialize<_iyzf06w5.PublicationSettings>( + jsonSerialization['settings'], + ), + secret: jsonSerialization['secret'] as String, + ); + } + + _iyzf06w5.PublicationSettings settings; + + String secret; + + /// Returns a shallow copy of this [PublicationSecret] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationSecret copyWith({ + _iyzf06w5.PublicationSettings? settings, + String? secret, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationSecret', + 'settings': settings.toJson(), + 'secret': secret, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationSecret', + 'settings': settings.toJsonForProtocol(), + 'secret': secret, + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _PublicationSecretImpl extends PublicationSecret { + _PublicationSecretImpl({ + required _iyzf06w5.PublicationSettings settings, + required String secret, + }) : super._( + settings: settings, + secret: secret, + ); + + /// Returns a shallow copy of this [PublicationSecret] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationSecret copyWith({ + _iyzf06w5.PublicationSettings? settings, + String? secret, + }) { + return PublicationSecret( + settings: settings ?? this.settings.copyWith(), + secret: secret ?? this.secret, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/publication_settings.dart b/wonky_server/lib/src/generated/platform/publications/models/publication_settings.dart new file mode 100644 index 00000000..13bb624c --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/publication_settings.dart @@ -0,0 +1,324 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; +import '../../../platform/publications/models/publication_moderator_view.dart' + as _in8lpp1q; + +/// The owner's view of a publication (specs/18 §8.1). Never holds secrets. +abstract class PublicationSettings + implements _is.SerializableModel, _is.ProtocolSerialization { + PublicationSettings._({ + required this.publicId, + required this.name, + required this.siteUrl, + required this.webhookUrl, + this.verifiedHost, + this.verifiedAt, + this.templateItemUuid, + this.templateName, + this.termsUrl, + required this.fields, + required this.moderators, + required this.hasApiKey, + this.apiKeyLast4, + this.previousSecretUntil, + required this.enabled, + required this.contributorLink, + required this.openSubmissionCount, + required this.createdAt, + }); + + factory PublicationSettings({ + required String publicId, + required String name, + required String siteUrl, + required String webhookUrl, + String? verifiedHost, + DateTime? verifiedAt, + _is.UuidValue? templateItemUuid, + String? templateName, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required List<_in8lpp1q.PublicationModeratorView> moderators, + required bool hasApiKey, + String? apiKeyLast4, + DateTime? previousSecretUntil, + required bool enabled, + required String contributorLink, + required int openSubmissionCount, + required DateTime createdAt, + }) = _PublicationSettingsImpl; + + factory PublicationSettings.fromJson(Map jsonSerialization) { + return PublicationSettings( + publicId: jsonSerialization['publicId'] as String, + name: jsonSerialization['name'] as String, + siteUrl: jsonSerialization['siteUrl'] as String, + webhookUrl: jsonSerialization['webhookUrl'] as String, + verifiedHost: jsonSerialization['verifiedHost'] as String?, + verifiedAt: jsonSerialization['verifiedAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson(jsonSerialization['verifiedAt']), + templateItemUuid: jsonSerialization['templateItemUuid'] == null + ? null + : _is.UuidValueJsonExtension.fromJson( + jsonSerialization['templateItemUuid'], + ), + templateName: jsonSerialization['templateName'] as String?, + termsUrl: jsonSerialization['termsUrl'] as String?, + fields: _il4umwa0.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + moderators: _il4umwa0.Protocol() + .deserialize>( + jsonSerialization['moderators'], + ), + hasApiKey: _is.BoolJsonExtension.fromJson(jsonSerialization['hasApiKey']), + apiKeyLast4: jsonSerialization['apiKeyLast4'] as String?, + previousSecretUntil: jsonSerialization['previousSecretUntil'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['previousSecretUntil'], + ), + enabled: _is.BoolJsonExtension.fromJson(jsonSerialization['enabled']), + contributorLink: jsonSerialization['contributorLink'] as String, + openSubmissionCount: jsonSerialization['openSubmissionCount'] as int, + createdAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + ); + } + + String publicId; + + String name; + + String siteUrl; + + String webhookUrl; + + String? verifiedHost; + + DateTime? verifiedAt; + + _is.UuidValue? templateItemUuid; + + String? templateName; + + String? termsUrl; + + _i1a71r29.PublicationFields fields; + + List<_in8lpp1q.PublicationModeratorView> moderators; + + bool hasApiKey; + + String? apiKeyLast4; + + /// Set while the previous signing secret still signs. + DateTime? previousSecretUntil; + + bool enabled; + + /// `https:///write/new?publication=`. + String contributorLink; + + /// Submissions in review or with changes requested. + int openSubmissionCount; + + DateTime createdAt; + + /// Returns a shallow copy of this [PublicationSettings] + /// with some or all fields replaced by the given arguments. + @_is.useResult + PublicationSettings copyWith({ + String? publicId, + String? name, + String? siteUrl, + String? webhookUrl, + String? verifiedHost, + DateTime? verifiedAt = const _is.$UndefinedDateTime(), + _is.UuidValue? templateItemUuid = const _is.$UndefinedUuidValue(), + String? templateName, + String? termsUrl, + _i1a71r29.PublicationFields? fields, + List<_in8lpp1q.PublicationModeratorView>? moderators, + bool? hasApiKey, + String? apiKeyLast4, + DateTime? previousSecretUntil = const _is.$UndefinedDateTime(), + bool? enabled, + String? contributorLink, + int? openSubmissionCount, + DateTime? createdAt, + }); + @override + Map toJson() { + return { + '__className__': 'PublicationSettings', + 'publicId': publicId, + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (verifiedHost != null) 'verifiedHost': verifiedHost, + if (verifiedAt != null) 'verifiedAt': verifiedAt?.toJson(), + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (templateName != null) 'templateName': templateName, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJson(), + 'moderators': moderators.toJson(valueToJson: (v) => v.toJson()), + 'hasApiKey': hasApiKey, + if (apiKeyLast4 != null) 'apiKeyLast4': apiKeyLast4, + if (previousSecretUntil != null) + 'previousSecretUntil': previousSecretUntil?.toJson(), + 'enabled': enabled, + 'contributorLink': contributorLink, + 'openSubmissionCount': openSubmissionCount, + 'createdAt': createdAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'PublicationSettings', + 'publicId': publicId, + 'name': name, + 'siteUrl': siteUrl, + 'webhookUrl': webhookUrl, + if (verifiedHost != null) 'verifiedHost': verifiedHost, + if (verifiedAt != null) 'verifiedAt': verifiedAt?.toJson(), + if (templateItemUuid != null) + 'templateItemUuid': templateItemUuid?.toJson(), + if (templateName != null) 'templateName': templateName, + if (termsUrl != null) 'termsUrl': termsUrl, + 'fields': fields.toJsonForProtocol(), + 'moderators': moderators.toJson( + valueToJson: (v) => v.toJsonForProtocol(), + ), + 'hasApiKey': hasApiKey, + if (apiKeyLast4 != null) 'apiKeyLast4': apiKeyLast4, + if (previousSecretUntil != null) + 'previousSecretUntil': previousSecretUntil?.toJson(), + 'enabled': enabled, + 'contributorLink': contributorLink, + 'openSubmissionCount': openSubmissionCount, + 'createdAt': createdAt.toJson(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _PublicationSettingsImpl extends PublicationSettings { + _PublicationSettingsImpl({ + required String publicId, + required String name, + required String siteUrl, + required String webhookUrl, + String? verifiedHost, + DateTime? verifiedAt, + _is.UuidValue? templateItemUuid, + String? templateName, + String? termsUrl, + required _i1a71r29.PublicationFields fields, + required List<_in8lpp1q.PublicationModeratorView> moderators, + required bool hasApiKey, + String? apiKeyLast4, + DateTime? previousSecretUntil, + required bool enabled, + required String contributorLink, + required int openSubmissionCount, + required DateTime createdAt, + }) : super._( + publicId: publicId, + name: name, + siteUrl: siteUrl, + webhookUrl: webhookUrl, + verifiedHost: verifiedHost, + verifiedAt: verifiedAt, + templateItemUuid: templateItemUuid, + templateName: templateName, + termsUrl: termsUrl, + fields: fields, + moderators: moderators, + hasApiKey: hasApiKey, + apiKeyLast4: apiKeyLast4, + previousSecretUntil: previousSecretUntil, + enabled: enabled, + contributorLink: contributorLink, + openSubmissionCount: openSubmissionCount, + createdAt: createdAt, + ); + + /// Returns a shallow copy of this [PublicationSettings] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + PublicationSettings copyWith({ + String? publicId, + String? name, + String? siteUrl, + String? webhookUrl, + Object? verifiedHost = _Undefined, + DateTime? verifiedAt = const _is.$UndefinedDateTime(), + _is.UuidValue? templateItemUuid = const _is.$UndefinedUuidValue(), + Object? templateName = _Undefined, + Object? termsUrl = _Undefined, + _i1a71r29.PublicationFields? fields, + List<_in8lpp1q.PublicationModeratorView>? moderators, + bool? hasApiKey, + Object? apiKeyLast4 = _Undefined, + DateTime? previousSecretUntil = const _is.$UndefinedDateTime(), + bool? enabled, + String? contributorLink, + int? openSubmissionCount, + DateTime? createdAt, + }) { + return PublicationSettings( + publicId: publicId ?? this.publicId, + name: name ?? this.name, + siteUrl: siteUrl ?? this.siteUrl, + webhookUrl: webhookUrl ?? this.webhookUrl, + verifiedHost: verifiedHost is String? ? verifiedHost : this.verifiedHost, + verifiedAt: verifiedAt is _is.UndefinedSentinel + ? this.verifiedAt + : verifiedAt, + templateItemUuid: templateItemUuid is _is.UndefinedSentinel + ? this.templateItemUuid + : templateItemUuid, + templateName: templateName is String? ? templateName : this.templateName, + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + fields: fields ?? this.fields.copyWith(), + moderators: + moderators ?? this.moderators.map((e0) => e0.copyWith()).toList(), + hasApiKey: hasApiKey ?? this.hasApiKey, + apiKeyLast4: apiKeyLast4 is String? ? apiKeyLast4 : this.apiKeyLast4, + previousSecretUntil: previousSecretUntil is _is.UndefinedSentinel + ? this.previousSecretUntil + : previousSecretUntil, + enabled: enabled ?? this.enabled, + contributorLink: contributorLink ?? this.contributorLink, + openSubmissionCount: openSubmissionCount ?? this.openSubmissionCount, + createdAt: createdAt ?? this.createdAt, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission.dart b/wonky_server/lib/src/generated/platform/publications/models/submission.dart new file mode 100644 index 00000000..09d624c6 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission.dart @@ -0,0 +1,1001 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/submission_delivery_state.dart' + as _ifp7j30v; +import '../../../platform/publications/models/submission_status.dart' + as _igclxad1; +import '../../../platform/publications/models/submission_values.dart' + as _igthguer; + +/// The link between a Write document and a publication (specs/18 §2, §6). +/// A document has at most one. +abstract class Submission + implements _is.TableRow, _is.ProtocolSerialization { + Submission._({ + this.id, + _is.UuidValue? uuid, + required this.publicationId, + required this.itemId, + this.ref, + required this.status, + this.statusBeforeSubmit, + this.delivery, + required this.values, + this.publicUrl, + this.feedbackThreadId, + required this.createdById, + required this.createdAt, + required this.updatedAt, + this.disconnectedAt, + }) : uuid = uuid ?? const _is.Uuid().v7obj(); + + factory Submission({ + int? id, + _is.UuidValue? uuid, + required int publicationId, + required int itemId, + String? ref, + required _igclxad1.SubmissionStatus status, + _igclxad1.SubmissionStatus? statusBeforeSubmit, + _ifp7j30v.SubmissionDeliveryState? delivery, + required _igthguer.SubmissionValues values, + String? publicUrl, + int? feedbackThreadId, + required int createdById, + required DateTime createdAt, + required DateTime updatedAt, + DateTime? disconnectedAt, + }) = _SubmissionImpl; + + factory Submission.fromJson(Map jsonSerialization) { + return Submission( + id: jsonSerialization['id'] as int?, + uuid: jsonSerialization['uuid'] == null + ? null + : _is.UuidValueJsonExtension.fromJson(jsonSerialization['uuid']), + publicationId: jsonSerialization['publicationId'] as int, + itemId: jsonSerialization['itemId'] as int, + ref: jsonSerialization['ref'] as String?, + status: _igclxad1.SubmissionStatus.fromJson( + (jsonSerialization['status'] as String), + ), + statusBeforeSubmit: jsonSerialization['statusBeforeSubmit'] == null + ? null + : _igclxad1.SubmissionStatus.fromJson( + (jsonSerialization['statusBeforeSubmit'] as String), + ), + delivery: jsonSerialization['delivery'] == null + ? null + : _ifp7j30v.SubmissionDeliveryState.fromJson( + (jsonSerialization['delivery'] as String), + ), + values: _il4umwa0.Protocol().deserialize<_igthguer.SubmissionValues>( + jsonSerialization['values'], + ), + publicUrl: jsonSerialization['publicUrl'] as String?, + feedbackThreadId: jsonSerialization['feedbackThreadId'] as int?, + createdById: jsonSerialization['createdById'] as int, + createdAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['createdAt'], + ), + updatedAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['updatedAt'], + ), + disconnectedAt: jsonSerialization['disconnectedAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['disconnectedAt'], + ), + ); + } + + static final t = SubmissionTable(); + + static const db = SubmissionRepository._(); + + @override + int? id; + + /// Public as "sub_". + _is.UuidValue uuid; + + int publicationId; + + int itemId; + + /// The blog's own reference from the contributor link. + String? ref; + + _igclxad1.SubmissionStatus status; + + /// The status before the last submit, restored when its delivery fails + /// (specs/18 §7.2). + _igclxad1.SubmissionStatus? statusBeforeSubmit; + + /// Null = the last delivery was accepted. + _ifp7j30v.SubmissionDeliveryState? delivery; + + _igthguer.SubmissionValues values; + + String? publicUrl; + + /// The document-level comment thread of the publication's messages. + int? feedbackThreadId; + + int createdById; + + DateTime createdAt; + + DateTime updatedAt; + + DateTime? disconnectedAt; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [Submission] + /// with some or all fields replaced by the given arguments. + @_is.useResult + Submission copyWith({ + int? id, + _is.UuidValue? uuid, + int? publicationId, + int? itemId, + String? ref, + _igclxad1.SubmissionStatus? status, + _igclxad1.SubmissionStatus? statusBeforeSubmit, + _ifp7j30v.SubmissionDeliveryState? delivery, + _igthguer.SubmissionValues? values, + String? publicUrl, + int? feedbackThreadId, + int? createdById, + DateTime? createdAt, + DateTime? updatedAt, + DateTime? disconnectedAt = const _is.$UndefinedDateTime(), + }); + @override + Map toJson() { + return { + '__className__': 'Submission', + if (id != null) 'id': id, + 'uuid': uuid.toJson(), + 'publicationId': publicationId, + 'itemId': itemId, + if (ref != null) 'ref': ref, + 'status': status.toJson(), + if (statusBeforeSubmit != null) + 'statusBeforeSubmit': statusBeforeSubmit?.toJson(), + if (delivery != null) 'delivery': delivery?.toJson(), + 'values': values.toJson(), + if (publicUrl != null) 'publicUrl': publicUrl, + if (feedbackThreadId != null) 'feedbackThreadId': feedbackThreadId, + 'createdById': createdById, + 'createdAt': createdAt.toJson(), + 'updatedAt': updatedAt.toJson(), + if (disconnectedAt != null) 'disconnectedAt': disconnectedAt?.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static SubmissionInclude include() { + return SubmissionInclude._(); + } + + static SubmissionIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + SubmissionInclude? include, + }) { + return SubmissionIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionImpl extends Submission { + _SubmissionImpl({ + int? id, + _is.UuidValue? uuid, + required int publicationId, + required int itemId, + String? ref, + required _igclxad1.SubmissionStatus status, + _igclxad1.SubmissionStatus? statusBeforeSubmit, + _ifp7j30v.SubmissionDeliveryState? delivery, + required _igthguer.SubmissionValues values, + String? publicUrl, + int? feedbackThreadId, + required int createdById, + required DateTime createdAt, + required DateTime updatedAt, + DateTime? disconnectedAt, + }) : super._( + id: id, + uuid: uuid, + publicationId: publicationId, + itemId: itemId, + ref: ref, + status: status, + statusBeforeSubmit: statusBeforeSubmit, + delivery: delivery, + values: values, + publicUrl: publicUrl, + feedbackThreadId: feedbackThreadId, + createdById: createdById, + createdAt: createdAt, + updatedAt: updatedAt, + disconnectedAt: disconnectedAt, + ); + + /// Returns a shallow copy of this [Submission] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + Submission copyWith({ + Object? id = _Undefined, + _is.UuidValue? uuid, + int? publicationId, + int? itemId, + Object? ref = _Undefined, + _igclxad1.SubmissionStatus? status, + Object? statusBeforeSubmit = _Undefined, + Object? delivery = _Undefined, + _igthguer.SubmissionValues? values, + Object? publicUrl = _Undefined, + Object? feedbackThreadId = _Undefined, + int? createdById, + DateTime? createdAt, + DateTime? updatedAt, + DateTime? disconnectedAt = const _is.$UndefinedDateTime(), + }) { + return Submission( + id: id is int? ? id : this.id, + uuid: uuid ?? this.uuid, + publicationId: publicationId ?? this.publicationId, + itemId: itemId ?? this.itemId, + ref: ref is String? ? ref : this.ref, + status: status ?? this.status, + statusBeforeSubmit: statusBeforeSubmit is _igclxad1.SubmissionStatus? + ? statusBeforeSubmit + : this.statusBeforeSubmit, + delivery: delivery is _ifp7j30v.SubmissionDeliveryState? + ? delivery + : this.delivery, + values: values ?? this.values.copyWith(), + publicUrl: publicUrl is String? ? publicUrl : this.publicUrl, + feedbackThreadId: feedbackThreadId is int? + ? feedbackThreadId + : this.feedbackThreadId, + createdById: createdById ?? this.createdById, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + disconnectedAt: disconnectedAt is _is.UndefinedSentinel + ? this.disconnectedAt + : disconnectedAt, + ); + } +} + +class SubmissionUpdateTable extends _is.UpdateTable { + SubmissionUpdateTable(super.table); + + _is.ColumnValue<_is.UuidValue, _is.UuidValue> uuid(_is.UuidValue value) => + _is.ColumnValue( + table.uuid, + value, + ); + + _is.ColumnValue publicationId(int value) => _is.ColumnValue( + table.publicationId, + value, + ); + + _is.ColumnValue itemId(int value) => _is.ColumnValue( + table.itemId, + value, + ); + + _is.ColumnValue ref(String? value) => _is.ColumnValue( + table.ref, + value, + ); + + _is.ColumnValue<_igclxad1.SubmissionStatus, _igclxad1.SubmissionStatus> + status(_igclxad1.SubmissionStatus value) => _is.ColumnValue( + table.status, + value, + ); + + _is.ColumnValue<_igclxad1.SubmissionStatus, _igclxad1.SubmissionStatus> + statusBeforeSubmit(_igclxad1.SubmissionStatus? value) => _is.ColumnValue( + table.statusBeforeSubmit, + value, + ); + + _is.ColumnValue< + _ifp7j30v.SubmissionDeliveryState, + _ifp7j30v.SubmissionDeliveryState + > + delivery(_ifp7j30v.SubmissionDeliveryState? value) => _is.ColumnValue( + table.delivery, + value, + ); + + _is.ColumnValue<_igthguer.SubmissionValues, _igthguer.SubmissionValues> + values(_igthguer.SubmissionValues value) => _is.ColumnValue( + table.values, + value, + ); + + _is.ColumnValue publicUrl(String? value) => _is.ColumnValue( + table.publicUrl, + value, + ); + + _is.ColumnValue feedbackThreadId(int? value) => _is.ColumnValue( + table.feedbackThreadId, + value, + ); + + _is.ColumnValue createdById(int value) => _is.ColumnValue( + table.createdById, + value, + ); + + _is.ColumnValue createdAt(DateTime value) => + _is.ColumnValue( + table.createdAt, + value, + ); + + _is.ColumnValue updatedAt(DateTime value) => + _is.ColumnValue( + table.updatedAt, + value, + ); + + _is.ColumnValue disconnectedAt(DateTime? value) => + _is.ColumnValue( + table.disconnectedAt, + value, + ); +} + +class SubmissionTable extends _is.Table { + SubmissionTable({super.tableRelation}) : super(tableName: 'submission') { + updateTable = SubmissionUpdateTable(this); + uuid = _is.ColumnUuid( + 'uuid', + this, + ); + publicationId = _is.ColumnInt( + 'publicationId', + this, + ); + itemId = _is.ColumnInt( + 'itemId', + this, + ); + ref = _is.ColumnString( + 'ref', + this, + ); + status = _is.ColumnEnum( + 'status', + this, + _is.EnumSerialization.byName, + ); + statusBeforeSubmit = _is.ColumnEnum( + 'statusBeforeSubmit', + this, + _is.EnumSerialization.byName, + ); + delivery = _is.ColumnEnum( + 'delivery', + this, + _is.EnumSerialization.byName, + ); + values = _is.ColumnSerializable<_igthguer.SubmissionValues>( + 'values', + this, + ); + publicUrl = _is.ColumnString( + 'publicUrl', + this, + ); + feedbackThreadId = _is.ColumnInt( + 'feedbackThreadId', + this, + ); + createdById = _is.ColumnInt( + 'createdById', + this, + ); + createdAt = _is.ColumnDateTime( + 'createdAt', + this, + ); + updatedAt = _is.ColumnDateTime( + 'updatedAt', + this, + ); + disconnectedAt = _is.ColumnDateTime( + 'disconnectedAt', + this, + ); + } + + late final SubmissionUpdateTable updateTable; + + /// Public as "sub_". + late final _is.ColumnUuid uuid; + + late final _is.ColumnInt publicationId; + + late final _is.ColumnInt itemId; + + /// The blog's own reference from the contributor link. + late final _is.ColumnString ref; + + late final _is.ColumnEnum<_igclxad1.SubmissionStatus> status; + + /// The status before the last submit, restored when its delivery fails + /// (specs/18 §7.2). + late final _is.ColumnEnum<_igclxad1.SubmissionStatus> statusBeforeSubmit; + + /// Null = the last delivery was accepted. + late final _is.ColumnEnum<_ifp7j30v.SubmissionDeliveryState> delivery; + + late final _is.ColumnSerializable<_igthguer.SubmissionValues> values; + + late final _is.ColumnString publicUrl; + + /// The document-level comment thread of the publication's messages. + late final _is.ColumnInt feedbackThreadId; + + late final _is.ColumnInt createdById; + + late final _is.ColumnDateTime createdAt; + + late final _is.ColumnDateTime updatedAt; + + late final _is.ColumnDateTime disconnectedAt; + + @override + List<_is.Column> get columns => [ + id, + uuid, + publicationId, + itemId, + ref, + status, + statusBeforeSubmit, + delivery, + values, + publicUrl, + feedbackThreadId, + createdById, + createdAt, + updatedAt, + disconnectedAt, + ]; +} + +class SubmissionInclude extends _is.IncludeObject { + SubmissionInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => Submission.t; +} + +class SubmissionIncludeList extends _is.IncludeList { + SubmissionIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(Submission.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => Submission.t; +} + +class SubmissionRepository { + const SubmissionRepository._(); + + /// Returns a list of [Submission]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(Submission.t), + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [Submission]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `Submission.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(Submission.t), + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [Submission] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(Submission.t), + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [Submission] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [Submission]s in the list and returns the inserted rows. + /// + /// The returned [Submission]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [Submission] and returns the inserted row. + /// + /// The returned [Submission] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + Submission row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [Submission]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [Submission]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(Submission.t), + updateColumns: updateColumns?.call(Submission.t), + updateWhere: updateWhere?.call(Submission.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [Submission] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [Submission] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + Submission row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(Submission.t), + updateColumns: updateColumns?.call(Submission.t), + updateWhere: updateWhere?.call(Submission.t), + transaction: transaction, + ); + } + + /// Updates all [Submission]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(Submission.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [Submission]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + Submission row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(Submission.t), + transaction: transaction, + ); + } + + /// Updates a single [Submission] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(Submission.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [Submission]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(Submission.t.updateTable), + where: where(Submission.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [Submission]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [Submission]. + Future deleteRow( + _is.DatabaseSession session, + Submission row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(Submission.t), + orderBy: orderBy?.call(Submission.t), + orderByList: orderByList?.call(Submission.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(Submission.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [Submission] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(Submission.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_asset.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_asset.dart new file mode 100644 index 00000000..6ce9a36c --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_asset.dart @@ -0,0 +1,667 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; + +/// An image a submit referenced (specs/18 §5, §7.3): the publication's API +/// key may download it while the file exists. +abstract class SubmissionAsset + implements _is.TableRow, _is.ProtocolSerialization { + SubmissionAsset._({ + this.id, + required this.submissionId, + required this.fileUuid, + }); + + factory SubmissionAsset({ + int? id, + required int submissionId, + required _is.UuidValue fileUuid, + }) = _SubmissionAssetImpl; + + factory SubmissionAsset.fromJson(Map jsonSerialization) { + return SubmissionAsset( + id: jsonSerialization['id'] as int?, + submissionId: jsonSerialization['submissionId'] as int, + fileUuid: _is.UuidValueJsonExtension.fromJson( + jsonSerialization['fileUuid'], + ), + ); + } + + static final t = SubmissionAssetTable(); + + static const db = SubmissionAssetRepository._(); + + @override + int? id; + + int submissionId; + + _is.UuidValue fileUuid; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [SubmissionAsset] + /// with some or all fields replaced by the given arguments. + @_is.useResult + SubmissionAsset copyWith({ + int? id, + int? submissionId, + _is.UuidValue? fileUuid, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionAsset', + if (id != null) 'id': id, + 'submissionId': submissionId, + 'fileUuid': fileUuid.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static SubmissionAssetInclude include() { + return SubmissionAssetInclude._(); + } + + static SubmissionAssetIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + SubmissionAssetInclude? include, + }) { + return SubmissionAssetIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionAssetImpl extends SubmissionAsset { + _SubmissionAssetImpl({ + int? id, + required int submissionId, + required _is.UuidValue fileUuid, + }) : super._( + id: id, + submissionId: submissionId, + fileUuid: fileUuid, + ); + + /// Returns a shallow copy of this [SubmissionAsset] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + SubmissionAsset copyWith({ + Object? id = _Undefined, + int? submissionId, + _is.UuidValue? fileUuid, + }) { + return SubmissionAsset( + id: id is int? ? id : this.id, + submissionId: submissionId ?? this.submissionId, + fileUuid: fileUuid ?? this.fileUuid, + ); + } +} + +class SubmissionAssetUpdateTable extends _is.UpdateTable { + SubmissionAssetUpdateTable(super.table); + + _is.ColumnValue submissionId(int value) => _is.ColumnValue( + table.submissionId, + value, + ); + + _is.ColumnValue<_is.UuidValue, _is.UuidValue> fileUuid(_is.UuidValue value) => + _is.ColumnValue( + table.fileUuid, + value, + ); +} + +class SubmissionAssetTable extends _is.Table { + SubmissionAssetTable({super.tableRelation}) + : super(tableName: 'submission_asset') { + updateTable = SubmissionAssetUpdateTable(this); + submissionId = _is.ColumnInt( + 'submissionId', + this, + ); + fileUuid = _is.ColumnUuid( + 'fileUuid', + this, + ); + } + + late final SubmissionAssetUpdateTable updateTable; + + late final _is.ColumnInt submissionId; + + late final _is.ColumnUuid fileUuid; + + @override + List<_is.Column> get columns => [ + id, + submissionId, + fileUuid, + ]; +} + +class SubmissionAssetInclude extends _is.IncludeObject { + SubmissionAssetInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => SubmissionAsset.t; +} + +class SubmissionAssetIncludeList extends _is.IncludeList { + SubmissionAssetIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(SubmissionAsset.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => SubmissionAsset.t; +} + +class SubmissionAssetRepository { + const SubmissionAssetRepository._(); + + /// Returns a list of [SubmissionAsset]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(SubmissionAsset.t), + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [SubmissionAsset]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `SubmissionAsset.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(SubmissionAsset.t), + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [SubmissionAsset] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(SubmissionAsset.t), + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [SubmissionAsset] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [SubmissionAsset]s in the list and returns the inserted rows. + /// + /// The returned [SubmissionAsset]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [SubmissionAsset] and returns the inserted row. + /// + /// The returned [SubmissionAsset] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + SubmissionAsset row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [SubmissionAsset]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [SubmissionAsset]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(SubmissionAsset.t), + updateColumns: updateColumns?.call(SubmissionAsset.t), + updateWhere: updateWhere?.call(SubmissionAsset.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [SubmissionAsset] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [SubmissionAsset] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + SubmissionAsset row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(SubmissionAsset.t), + updateColumns: updateColumns?.call(SubmissionAsset.t), + updateWhere: updateWhere?.call(SubmissionAsset.t), + transaction: transaction, + ); + } + + /// Updates all [SubmissionAsset]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(SubmissionAsset.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [SubmissionAsset]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + SubmissionAsset row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(SubmissionAsset.t), + transaction: transaction, + ); + } + + /// Updates a single [SubmissionAsset] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder + columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(SubmissionAsset.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [SubmissionAsset]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder + columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(SubmissionAsset.t.updateTable), + where: where(SubmissionAsset.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [SubmissionAsset]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [SubmissionAsset]. + Future deleteRow( + _is.DatabaseSession session, + SubmissionAsset row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(SubmissionAsset.t), + orderBy: orderBy?.call(SubmissionAsset.t), + orderByList: orderByList?.call(SubmissionAsset.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(SubmissionAsset.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [SubmissionAsset] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(SubmissionAsset.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_delivery_state.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_delivery_state.dart new file mode 100644 index 00000000..25078b48 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_delivery_state.dart @@ -0,0 +1,41 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +/// State of the last submit's webhook delivery (specs/18 §7.2). +enum SubmissionDeliveryState implements _is.SerializableModel { + /// Not accepted yet; the outbox retries. + pending, + + /// Every retry failed. + failed; + + static SubmissionDeliveryState fromJson(String name) { + switch (name) { + case 'pending': + return SubmissionDeliveryState.pending; + case 'failed': + return SubmissionDeliveryState.failed; + default: + throw ArgumentError( + 'Value "$name" cannot be converted to "SubmissionDeliveryState"', + ); + } + } + + @override + String toJson() => name; + + @override + String toString() => name; +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_revision.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_revision.dart new file mode 100644 index 00000000..f56f6d41 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_revision.dart @@ -0,0 +1,821 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'dart:async' as _ida; +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/submission_values.dart' + as _igthguer; + +/// One submit of a submission (specs/18 §2, §6). +abstract class SubmissionRevision + implements _is.TableRow, _is.ProtocolSerialization { + SubmissionRevision._({ + this.id, + required this.submissionId, + required this.sequence, + required this.revision, + this.versionId, + required this.values, + required this.payload, + required this.submittedById, + required this.submittedAt, + }); + + factory SubmissionRevision({ + int? id, + required int submissionId, + required int sequence, + required int revision, + int? versionId, + required _igthguer.SubmissionValues values, + required String payload, + required int submittedById, + required DateTime submittedAt, + }) = _SubmissionRevisionImpl; + + factory SubmissionRevision.fromJson(Map jsonSerialization) { + return SubmissionRevision( + id: jsonSerialization['id'] as int?, + submissionId: jsonSerialization['submissionId'] as int, + sequence: jsonSerialization['sequence'] as int, + revision: jsonSerialization['revision'] as int, + versionId: jsonSerialization['versionId'] as int?, + values: _il4umwa0.Protocol().deserialize<_igthguer.SubmissionValues>( + jsonSerialization['values'], + ), + payload: jsonSerialization['payload'] as String, + submittedById: jsonSerialization['submittedById'] as int, + submittedAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['submittedAt'], + ), + ); + } + + static final t = SubmissionRevisionTable(); + + static const db = SubmissionRevisionRepository._(); + + @override + int? id; + + int submissionId; + + /// 1, 2, … per submission. + int sequence; + + /// The Write document revision that was sent. + int revision; + + /// The named version of this submit (specs/18 P8). + int? versionId; + + _igthguer.SubmissionValues values; + + /// The `submission.submitted` body sent for this submit (JSON), served + /// again by `GET submissions/{id}/content` (specs/18 §7.3). + String payload; + + int submittedById; + + DateTime submittedAt; + + @override + _is.Table get table => t; + + /// Returns a shallow copy of this [SubmissionRevision] + /// with some or all fields replaced by the given arguments. + @_is.useResult + SubmissionRevision copyWith({ + int? id, + int? submissionId, + int? sequence, + int? revision, + int? versionId, + _igthguer.SubmissionValues? values, + String? payload, + int? submittedById, + DateTime? submittedAt, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionRevision', + if (id != null) 'id': id, + 'submissionId': submissionId, + 'sequence': sequence, + 'revision': revision, + if (versionId != null) 'versionId': versionId, + 'values': values.toJson(), + 'payload': payload, + 'submittedById': submittedById, + 'submittedAt': submittedAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return {}; + } + + static SubmissionRevisionInclude include() { + return SubmissionRevisionInclude._(); + } + + static SubmissionRevisionIncludeList includeList({ + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + SubmissionRevisionInclude? include, + }) { + return SubmissionRevisionIncludeList._( + where: where, + limit: limit, + offset: offset, + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + include: include, + ); + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionRevisionImpl extends SubmissionRevision { + _SubmissionRevisionImpl({ + int? id, + required int submissionId, + required int sequence, + required int revision, + int? versionId, + required _igthguer.SubmissionValues values, + required String payload, + required int submittedById, + required DateTime submittedAt, + }) : super._( + id: id, + submissionId: submissionId, + sequence: sequence, + revision: revision, + versionId: versionId, + values: values, + payload: payload, + submittedById: submittedById, + submittedAt: submittedAt, + ); + + /// Returns a shallow copy of this [SubmissionRevision] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + SubmissionRevision copyWith({ + Object? id = _Undefined, + int? submissionId, + int? sequence, + int? revision, + Object? versionId = _Undefined, + _igthguer.SubmissionValues? values, + String? payload, + int? submittedById, + DateTime? submittedAt, + }) { + return SubmissionRevision( + id: id is int? ? id : this.id, + submissionId: submissionId ?? this.submissionId, + sequence: sequence ?? this.sequence, + revision: revision ?? this.revision, + versionId: versionId is int? ? versionId : this.versionId, + values: values ?? this.values.copyWith(), + payload: payload ?? this.payload, + submittedById: submittedById ?? this.submittedById, + submittedAt: submittedAt ?? this.submittedAt, + ); + } +} + +class SubmissionRevisionUpdateTable + extends _is.UpdateTable { + SubmissionRevisionUpdateTable(super.table); + + _is.ColumnValue submissionId(int value) => _is.ColumnValue( + table.submissionId, + value, + ); + + _is.ColumnValue sequence(int value) => _is.ColumnValue( + table.sequence, + value, + ); + + _is.ColumnValue revision(int value) => _is.ColumnValue( + table.revision, + value, + ); + + _is.ColumnValue versionId(int? value) => _is.ColumnValue( + table.versionId, + value, + ); + + _is.ColumnValue<_igthguer.SubmissionValues, _igthguer.SubmissionValues> + values(_igthguer.SubmissionValues value) => _is.ColumnValue( + table.values, + value, + ); + + _is.ColumnValue payload(String value) => _is.ColumnValue( + table.payload, + value, + ); + + _is.ColumnValue submittedById(int value) => _is.ColumnValue( + table.submittedById, + value, + ); + + _is.ColumnValue submittedAt(DateTime value) => + _is.ColumnValue( + table.submittedAt, + value, + ); +} + +class SubmissionRevisionTable extends _is.Table { + SubmissionRevisionTable({super.tableRelation}) + : super(tableName: 'submission_revision') { + updateTable = SubmissionRevisionUpdateTable(this); + submissionId = _is.ColumnInt( + 'submissionId', + this, + ); + sequence = _is.ColumnInt( + 'sequence', + this, + ); + revision = _is.ColumnInt( + 'revision', + this, + ); + versionId = _is.ColumnInt( + 'versionId', + this, + ); + values = _is.ColumnSerializable<_igthguer.SubmissionValues>( + 'values', + this, + ); + payload = _is.ColumnString( + 'payload', + this, + ); + submittedById = _is.ColumnInt( + 'submittedById', + this, + ); + submittedAt = _is.ColumnDateTime( + 'submittedAt', + this, + ); + } + + late final SubmissionRevisionUpdateTable updateTable; + + late final _is.ColumnInt submissionId; + + /// 1, 2, … per submission. + late final _is.ColumnInt sequence; + + /// The Write document revision that was sent. + late final _is.ColumnInt revision; + + /// The named version of this submit (specs/18 P8). + late final _is.ColumnInt versionId; + + late final _is.ColumnSerializable<_igthguer.SubmissionValues> values; + + /// The `submission.submitted` body sent for this submit (JSON), served + /// again by `GET submissions/{id}/content` (specs/18 §7.3). + late final _is.ColumnString payload; + + late final _is.ColumnInt submittedById; + + late final _is.ColumnDateTime submittedAt; + + @override + List<_is.Column> get columns => [ + id, + submissionId, + sequence, + revision, + versionId, + values, + payload, + submittedById, + submittedAt, + ]; +} + +class SubmissionRevisionInclude extends _is.IncludeObject { + SubmissionRevisionInclude._(); + + @override + Map get includes => {}; + + @override + _is.Table get table => SubmissionRevision.t; +} + +class SubmissionRevisionIncludeList extends _is.IncludeList { + SubmissionRevisionIncludeList._({ + _is.WhereExpressionBuilder? where, + super.limit, + super.offset, + super.orderBy, + super.orderByList, + super.include, + }) { + super.where = where?.call(SubmissionRevision.t); + } + + @override + Map get includes => include?.includes ?? {}; + + @override + _is.Table get table => SubmissionRevision.t; +} + +class SubmissionRevisionRepository { + const SubmissionRevisionRepository._(); + + /// Returns a list of [SubmissionRevision]s matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// ```dart + /// var persons = await Persons.db.find( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ); + /// ``` + Future> find( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.find( + where: where?.call(SubmissionRevision.t), + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + limit: limit, + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Emits [SubmissionRevision]s matching the given query parameters every time the + /// source tables are modified. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order of the items use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// The maximum number of items can be set by [limit]. If no limit is set, + /// all items matching the query will be returned. + /// + /// [offset] defines how many items to skip, after which [limit] (or all) + /// items are read from the database. + /// + /// Use [throttle] to specify the minimum interval between queries. It can + /// also be set to `null`, in which case the stream will only be throttled + /// when its subscription is paused. + /// + /// Source tables are collected from the queried table, [where], [orderBy], + /// [orderByList], and the [include] graph. [alsoTriggerOnTables] is added + /// to that set. Pass [Table] instances such as `SubmissionRevision.t`. + /// + /// Raw [Expression] SQL is not inspected. Tables referenced only in raw + /// SQL must be passed via [alsoTriggerOnTables]. + /// + /// The stream always reads committed state and never joins an ambient + /// [Transaction]. Emissions for a write fire after that write commits. + /// + /// Currently only supported on SQLite. Calling this method on PostgreSQL + /// throws an [UnsupportedError]. + /// + /// ```dart + /// var subscription = Persons.db.watch( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.firstName, + /// limit: 100, + /// ).listen((persons) { + /// // Handle the latest matching rows. + /// }); + /// ``` + _ida.Stream> watch( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + Duration? throttle = const Duration(milliseconds: 30), + Iterable<_is.Table>? alsoTriggerOnTables, + }) { + return session.db.watch( + where: where?.call(SubmissionRevision.t), + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + limit: limit, + offset: offset, + throttle: throttle, + alsoTriggerOnTables: alsoTriggerOnTables, + ); + } + + /// Returns the first matching [SubmissionRevision] matching the given query parameters. + /// + /// Use [where] to specify which items to include in the return value. + /// If none is specified, all items will be returned. + /// + /// To specify the order use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// [offset] defines how many items to skip, after which the next one will be picked. + /// + /// ```dart + /// var youngestPerson = await Persons.db.findFirstRow( + /// session, + /// where: (t) => t.lastName.equals('Jones'), + /// orderBy: (t) => t.age, + /// ); + /// ``` + Future findFirstRow( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findFirstRow( + where: where?.call(SubmissionRevision.t), + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + offset: offset, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Finds a single [SubmissionRevision] by its [id] or null if no such row exists. + Future findById( + _is.DatabaseSession session, + int id, { + _is.Transaction? transaction, + _is.LockMode? lockMode, + _is.LockBehavior? lockBehavior, + }) async { + return session.db.findById( + id, + transaction: transaction, + lockMode: lockMode, + lockBehavior: lockBehavior, + ); + } + + /// Inserts all [SubmissionRevision]s in the list and returns the inserted rows. + /// + /// The returned [SubmissionRevision]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails to + /// insert, none of the rows will be inserted. + /// + /// If [ignoreConflicts] is set to `true`, rows that conflict with existing + /// rows are silently skipped, and only the successfully inserted rows are + /// returned. + /// + /// If [noReturn] is set to `true`, the inserted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> insert( + _is.DatabaseSession session, + List rows, { + _is.Transaction? transaction, + bool ignoreConflicts = false, + bool noReturn = false, + }) async { + return session.db.insert( + rows, + transaction: transaction, + ignoreConflicts: ignoreConflicts, + noReturn: noReturn, + ); + } + + /// Inserts a single [SubmissionRevision] and returns the inserted row. + /// + /// The returned [SubmissionRevision] will have its `id` field set. + Future insertRow( + _is.DatabaseSession session, + SubmissionRevision row, { + _is.Transaction? transaction, + }) async { + return session.db.insertRow( + row, + transaction: transaction, + ); + } + + /// Upserts all [SubmissionRevision]s in the list and returns the resulting rows. + /// + /// If a row conflicts on the given [conflictColumns], the existing row is + /// updated with the new values. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies to rows matching the + /// given expression. Conflicting rows that don't match are skipped and not + /// returned, so the resulting list may be shorter than [rows]. + /// + /// The returned [SubmissionRevision]s will have their `id` fields set. + /// + /// This is an atomic operation, meaning that if one of the rows fails, + /// none of the rows will be affected. + /// + /// If [noReturn] is set to `true`, the resulting rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> upsert( + _is.DatabaseSession session, + List rows, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.upsert( + rows, + conflictColumns: conflictColumns(SubmissionRevision.t), + updateColumns: updateColumns?.call(SubmissionRevision.t), + updateWhere: updateWhere?.call(SubmissionRevision.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Upserts a single [SubmissionRevision] and returns the resulting row. + /// + /// If the row conflicts on the given [conflictColumns], the existing row is + /// updated. Otherwise, a new row is inserted. + /// + /// If [updateColumns] is provided, only those columns will be updated on + /// conflict. If null, all non-conflict, non-id columns are updated. + /// + /// If [updateWhere] is provided, the update only applies when the existing + /// row matches the expression. Returns `null` if no row was affected — for + /// example when [updateWhere] does not match the conflicting row. + /// + /// The returned [SubmissionRevision] will have its `id` field set. + Future upsertRow( + _is.DatabaseSession session, + SubmissionRevision row, { + required _is.ColumnSelections conflictColumns, + _is.ColumnSelections? updateColumns, + _is.WhereExpressionBuilder? updateWhere, + _is.Transaction? transaction, + }) async { + return session.db.upsertRow( + row, + conflictColumns: conflictColumns(SubmissionRevision.t), + updateColumns: updateColumns?.call(SubmissionRevision.t), + updateWhere: updateWhere?.call(SubmissionRevision.t), + transaction: transaction, + ); + } + + /// Updates all [SubmissionRevision]s in the list and returns the updated rows. If + /// [columns] is provided, only those columns will be updated. Defaults to + /// all columns. + /// This is an atomic operation, meaning that if one of the rows fails to + /// update, none of the rows will be updated. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> update( + _is.DatabaseSession session, + List rows, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.update( + rows, + columns: columns?.call(SubmissionRevision.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Updates a single [SubmissionRevision]. The row needs to have its id set. + /// Optionally, a list of [columns] can be provided to only update those + /// columns. Defaults to all columns. + Future updateRow( + _is.DatabaseSession session, + SubmissionRevision row, { + _is.ColumnSelections? columns, + _is.Transaction? transaction, + }) async { + return session.db.updateRow( + row, + columns: columns?.call(SubmissionRevision.t), + transaction: transaction, + ); + } + + /// Updates a single [SubmissionRevision] by its [id] with the specified [columnValues]. + /// Returns the updated row or null if no row with the given id exists. + Future updateById( + _is.DatabaseSession session, + int id, { + required _is.ColumnValueListBuilder + columnValues, + _is.Transaction? transaction, + }) async { + return session.db.updateById( + id, + columnValues: columnValues(SubmissionRevision.t.updateTable), + transaction: transaction, + ); + } + + /// Updates all [SubmissionRevision]s matching the [where] expression with the specified [columnValues]. + /// Returns the list of updated rows. + /// + /// If [noReturn] is set to `true`, the updated rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> updateWhere( + _is.DatabaseSession session, { + required _is.ColumnValueListBuilder + columnValues, + required _is.WhereExpressionBuilder where, + int? limit, + int? offset, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.updateWhere( + columnValues: columnValues(SubmissionRevision.t.updateTable), + where: where(SubmissionRevision.t), + limit: limit, + offset: offset, + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes all [SubmissionRevision]s in the list and returns the deleted rows. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// This is an atomic operation, meaning that if one of the rows fail to + /// be deleted, none of the rows will be deleted. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> delete( + _is.DatabaseSession session, + List rows, { + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.delete( + rows, + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Deletes a single [SubmissionRevision]. + Future deleteRow( + _is.DatabaseSession session, + SubmissionRevision row, { + _is.Transaction? transaction, + }) async { + return session.db.deleteRow( + row, + transaction: transaction, + ); + } + + /// Deletes all rows matching the [where] expression. + /// + /// To specify the order of the returned rows use [orderBy] or [orderByList] + /// when sorting by multiple columns. + /// + /// If [noReturn] is set to `true`, the deleted rows are not read back from + /// the database and an empty list is returned. This avoids the overhead of + /// transferring and deserializing the rows when the result is not needed. + Future> deleteWhere( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + _is.OrderByBuilder? orderBy, + _is.OrderByListBuilder? orderByList, + _is.Transaction? transaction, + bool noReturn = false, + }) async { + return session.db.deleteWhere( + where: where(SubmissionRevision.t), + orderBy: orderBy?.call(SubmissionRevision.t), + orderByList: orderByList?.call(SubmissionRevision.t), + transaction: transaction, + noReturn: noReturn, + ); + } + + /// Counts the number of rows matching the [where] expression. If omitted, + /// will return the count of all rows in the table. + Future count( + _is.DatabaseSession session, { + _is.WhereExpressionBuilder? where, + int? limit, + _is.Transaction? transaction, + }) async { + return session.db.count( + where: where?.call(SubmissionRevision.t), + limit: limit, + transaction: transaction, + ); + } + + /// Acquires row-level locks on [SubmissionRevision] rows matching the [where] expression. + Future lockRows( + _is.DatabaseSession session, { + required _is.WhereExpressionBuilder where, + required _is.LockMode lockMode, + required _is.Transaction transaction, + _is.LockBehavior lockBehavior = _is.LockBehavior.wait, + }) async { + return session.db.lockRows( + where: where(SubmissionRevision.t), + lockMode: lockMode, + lockBehavior: lockBehavior, + transaction: transaction, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_revision_view.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_revision_view.dart new file mode 100644 index 00000000..631d77a1 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_revision_view.dart @@ -0,0 +1,134 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +abstract class SubmissionRevisionView + implements _is.SerializableModel, _is.ProtocolSerialization { + SubmissionRevisionView._({ + required this.sequence, + required this.revision, + required this.submittedByName, + required this.submittedAt, + this.versionId, + }); + + factory SubmissionRevisionView({ + required int sequence, + required int revision, + required String submittedByName, + required DateTime submittedAt, + int? versionId, + }) = _SubmissionRevisionViewImpl; + + factory SubmissionRevisionView.fromJson( + Map jsonSerialization, + ) { + return SubmissionRevisionView( + sequence: jsonSerialization['sequence'] as int, + revision: jsonSerialization['revision'] as int, + submittedByName: jsonSerialization['submittedByName'] as String, + submittedAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['submittedAt'], + ), + versionId: jsonSerialization['versionId'] as int?, + ); + } + + int sequence; + + int revision; + + String submittedByName; + + DateTime submittedAt; + + /// The named version of this submit, when it still exists. + int? versionId; + + /// Returns a shallow copy of this [SubmissionRevisionView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + SubmissionRevisionView copyWith({ + int? sequence, + int? revision, + String? submittedByName, + DateTime? submittedAt, + int? versionId, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionRevisionView', + 'sequence': sequence, + 'revision': revision, + 'submittedByName': submittedByName, + 'submittedAt': submittedAt.toJson(), + if (versionId != null) 'versionId': versionId, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionRevisionView', + 'sequence': sequence, + 'revision': revision, + 'submittedByName': submittedByName, + 'submittedAt': submittedAt.toJson(), + if (versionId != null) 'versionId': versionId, + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionRevisionViewImpl extends SubmissionRevisionView { + _SubmissionRevisionViewImpl({ + required int sequence, + required int revision, + required String submittedByName, + required DateTime submittedAt, + int? versionId, + }) : super._( + sequence: sequence, + revision: revision, + submittedByName: submittedByName, + submittedAt: submittedAt, + versionId: versionId, + ); + + /// Returns a shallow copy of this [SubmissionRevisionView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + SubmissionRevisionView copyWith({ + int? sequence, + int? revision, + String? submittedByName, + DateTime? submittedAt, + Object? versionId = _Undefined, + }) { + return SubmissionRevisionView( + sequence: sequence ?? this.sequence, + revision: revision ?? this.revision, + submittedByName: submittedByName ?? this.submittedByName, + submittedAt: submittedAt ?? this.submittedAt, + versionId: versionId is int? ? versionId : this.versionId, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_started.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_started.dart new file mode 100644 index 00000000..bc3478c8 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_started.dart @@ -0,0 +1,70 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +/// Result of starting a story (specs/18 §3 step 3). +abstract class SubmissionStarted + implements _is.SerializableModel, _is.ProtocolSerialization { + SubmissionStarted._({required this.itemUuid}); + + factory SubmissionStarted({required _is.UuidValue itemUuid}) = + _SubmissionStartedImpl; + + factory SubmissionStarted.fromJson(Map jsonSerialization) { + return SubmissionStarted( + itemUuid: _is.UuidValueJsonExtension.fromJson( + jsonSerialization['itemUuid'], + ), + ); + } + + _is.UuidValue itemUuid; + + /// Returns a shallow copy of this [SubmissionStarted] + /// with some or all fields replaced by the given arguments. + @_is.useResult + SubmissionStarted copyWith({_is.UuidValue? itemUuid}); + @override + Map toJson() { + return { + '__className__': 'SubmissionStarted', + 'itemUuid': itemUuid.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionStarted', + 'itemUuid': itemUuid.toJson(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _SubmissionStartedImpl extends SubmissionStarted { + _SubmissionStartedImpl({required _is.UuidValue itemUuid}) + : super._(itemUuid: itemUuid); + + /// Returns a shallow copy of this [SubmissionStarted] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + SubmissionStarted copyWith({_is.UuidValue? itemUuid}) { + return SubmissionStarted(itemUuid: itemUuid ?? this.itemUuid); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_status.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_status.dart new file mode 100644 index 00000000..58911190 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_status.dart @@ -0,0 +1,53 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; + +/// Lifecycle of a submission (specs/18 §2.1). +enum SubmissionStatus implements _is.SerializableModel { + /// Started from the link, never submitted. + draft, + inReview, + changesRequested, + + /// Final for this submission. + declined, + published, + withdrawn; + + static SubmissionStatus fromJson(String name) { + switch (name) { + case 'draft': + return SubmissionStatus.draft; + case 'inReview': + return SubmissionStatus.inReview; + case 'changesRequested': + return SubmissionStatus.changesRequested; + case 'declined': + return SubmissionStatus.declined; + case 'published': + return SubmissionStatus.published; + case 'withdrawn': + return SubmissionStatus.withdrawn; + default: + throw ArgumentError( + 'Value "$name" cannot be converted to "SubmissionStatus"', + ); + } + } + + @override + String toJson() => name; + + @override + String toString() => name; +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_values.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_values.dart new file mode 100644 index 00000000..9854d2e9 --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_values.dart @@ -0,0 +1,152 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; + +/// The fields a contributor filled in (specs/18 §4.2). +abstract class SubmissionValues + implements _is.SerializableModel, _is.ProtocolSerialization { + SubmissionValues._({ + required this.title, + this.summary, + required this.tags, + this.coverImage, + this.authorBio, + this.note, + }); + + factory SubmissionValues({ + required String title, + String? summary, + required List tags, + _is.UuidValue? coverImage, + String? authorBio, + String? note, + }) = _SubmissionValuesImpl; + + factory SubmissionValues.fromJson(Map jsonSerialization) { + return SubmissionValues( + title: jsonSerialization['title'] as String, + summary: jsonSerialization['summary'] as String?, + tags: _il4umwa0.Protocol().deserialize>( + jsonSerialization['tags'], + ), + coverImage: jsonSerialization['coverImage'] == null + ? null + : _is.UuidValueJsonExtension.fromJson( + jsonSerialization['coverImage'], + ), + authorBio: jsonSerialization['authorBio'] as String?, + note: jsonSerialization['note'] as String?, + ); + } + + String title; + + String? summary; + + List tags; + + /// A `wonky-file` uuid of an image in the document. + _is.UuidValue? coverImage; + + String? authorBio; + + String? note; + + /// Returns a shallow copy of this [SubmissionValues] + /// with some or all fields replaced by the given arguments. + @_is.useResult + SubmissionValues copyWith({ + String? title, + String? summary, + List? tags, + _is.UuidValue? coverImage = const _is.$UndefinedUuidValue(), + String? authorBio, + String? note, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionValues', + 'title': title, + if (summary != null) 'summary': summary, + 'tags': tags.toJson(), + if (coverImage != null) 'coverImage': coverImage?.toJson(), + if (authorBio != null) 'authorBio': authorBio, + if (note != null) 'note': note, + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionValues', + 'title': title, + if (summary != null) 'summary': summary, + 'tags': tags.toJson(), + if (coverImage != null) 'coverImage': coverImage?.toJson(), + if (authorBio != null) 'authorBio': authorBio, + if (note != null) 'note': note, + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionValuesImpl extends SubmissionValues { + _SubmissionValuesImpl({ + required String title, + String? summary, + required List tags, + _is.UuidValue? coverImage, + String? authorBio, + String? note, + }) : super._( + title: title, + summary: summary, + tags: tags, + coverImage: coverImage, + authorBio: authorBio, + note: note, + ); + + /// Returns a shallow copy of this [SubmissionValues] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + SubmissionValues copyWith({ + String? title, + Object? summary = _Undefined, + List? tags, + _is.UuidValue? coverImage = const _is.$UndefinedUuidValue(), + Object? authorBio = _Undefined, + Object? note = _Undefined, + }) { + return SubmissionValues( + title: title ?? this.title, + summary: summary is String? ? summary : this.summary, + tags: tags ?? this.tags.map((e0) => e0).toList(), + coverImage: coverImage is _is.UndefinedSentinel + ? this.coverImage + : coverImage, + authorBio: authorBio is String? ? authorBio : this.authorBio, + note: note is String? ? note : this.note, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/publications/models/submission_view.dart b/wonky_server/lib/src/generated/platform/publications/models/submission_view.dart new file mode 100644 index 00000000..b2e75ccd --- /dev/null +++ b/wonky_server/lib/src/generated/platform/publications/models/submission_view.dart @@ -0,0 +1,366 @@ +/* AUTOMATICALLY GENERATED CODE DO NOT MODIFY */ +/* To generate run: "serverpod generate" */ + +// ignore_for_file: implementation_imports +// ignore_for_file: library_private_types_in_public_api +// ignore_for_file: non_constant_identifier_names +// ignore_for_file: public_member_api_docs +// ignore_for_file: type_literal_in_constant_pattern +// ignore_for_file: use_super_parameters +// ignore_for_file: invalid_use_of_internal_member + +// ignore_for_file: no_leading_underscores_for_library_prefixes +import 'package:serverpod/serverpod.dart' as _is; +import 'package:wonky_server/src/generated/protocol.dart' as _il4umwa0; +import '../../../platform/publications/models/publication_fields.dart' + as _i1a71r29; +import '../../../platform/publications/models/submission_delivery_state.dart' + as _ifp7j30v; +import '../../../platform/publications/models/submission_revision_view.dart' + as _idtrp1yl; +import '../../../platform/publications/models/submission_status.dart' + as _igclxad1; +import '../../../platform/publications/models/submission_values.dart' + as _igthguer; + +/// A document's submission as editors and moderators see it (specs/18 §4). +abstract class SubmissionView + implements _is.SerializableModel, _is.ProtocolSerialization { + SubmissionView._({ + required this.id, + required this.itemUuid, + required this.status, + this.delivery, + required this.publicationId, + required this.publicationName, + required this.shownHost, + required this.verified, + required this.accepting, + required this.fields, + this.termsUrl, + required this.consentNeeded, + required this.values, + this.publicUrl, + this.feedbackThreadUuid, + this.lastMessage, + this.lastMessageAt, + this.lastSubmittedRevision, + required this.revisions, + required this.updatedAt, + }); + + factory SubmissionView({ + required String id, + required _is.UuidValue itemUuid, + required _igclxad1.SubmissionStatus status, + _ifp7j30v.SubmissionDeliveryState? delivery, + required String publicationId, + required String publicationName, + required String shownHost, + required bool verified, + required bool accepting, + required _i1a71r29.PublicationFields fields, + String? termsUrl, + required bool consentNeeded, + required _igthguer.SubmissionValues values, + String? publicUrl, + _is.UuidValue? feedbackThreadUuid, + String? lastMessage, + DateTime? lastMessageAt, + int? lastSubmittedRevision, + required List<_idtrp1yl.SubmissionRevisionView> revisions, + required DateTime updatedAt, + }) = _SubmissionViewImpl; + + factory SubmissionView.fromJson(Map jsonSerialization) { + return SubmissionView( + id: jsonSerialization['id'] as String, + itemUuid: _is.UuidValueJsonExtension.fromJson( + jsonSerialization['itemUuid'], + ), + status: _igclxad1.SubmissionStatus.fromJson( + (jsonSerialization['status'] as String), + ), + delivery: jsonSerialization['delivery'] == null + ? null + : _ifp7j30v.SubmissionDeliveryState.fromJson( + (jsonSerialization['delivery'] as String), + ), + publicationId: jsonSerialization['publicationId'] as String, + publicationName: jsonSerialization['publicationName'] as String, + shownHost: jsonSerialization['shownHost'] as String, + verified: _is.BoolJsonExtension.fromJson(jsonSerialization['verified']), + accepting: _is.BoolJsonExtension.fromJson(jsonSerialization['accepting']), + fields: _il4umwa0.Protocol().deserialize<_i1a71r29.PublicationFields>( + jsonSerialization['fields'], + ), + termsUrl: jsonSerialization['termsUrl'] as String?, + consentNeeded: _is.BoolJsonExtension.fromJson( + jsonSerialization['consentNeeded'], + ), + values: _il4umwa0.Protocol().deserialize<_igthguer.SubmissionValues>( + jsonSerialization['values'], + ), + publicUrl: jsonSerialization['publicUrl'] as String?, + feedbackThreadUuid: jsonSerialization['feedbackThreadUuid'] == null + ? null + : _is.UuidValueJsonExtension.fromJson( + jsonSerialization['feedbackThreadUuid'], + ), + lastMessage: jsonSerialization['lastMessage'] as String?, + lastMessageAt: jsonSerialization['lastMessageAt'] == null + ? null + : _is.DateTimeJsonExtension.fromJson( + jsonSerialization['lastMessageAt'], + ), + lastSubmittedRevision: jsonSerialization['lastSubmittedRevision'] as int?, + revisions: _il4umwa0.Protocol() + .deserialize>( + jsonSerialization['revisions'], + ), + updatedAt: _is.DateTimeJsonExtension.fromJson( + jsonSerialization['updatedAt'], + ), + ); + } + + /// "sub_". + String id; + + _is.UuidValue itemUuid; + + _igclxad1.SubmissionStatus status; + + _ifp7j30v.SubmissionDeliveryState? delivery; + + String publicationId; + + String publicationName; + + String shownHost; + + bool verified; + + /// The publication still takes submissions (enabled, caller not blocked). + bool accepting; + + _i1a71r29.PublicationFields fields; + + String? termsUrl; + + /// The caller still has to agree to the terms before submitting. + bool consentNeeded; + + _igthguer.SubmissionValues values; + + String? publicUrl; + + _is.UuidValue? feedbackThreadUuid; + + /// The publication's last message (Markdown) and when it came. + String? lastMessage; + + DateTime? lastMessageAt; + + /// The document revision of the last submit (null before the first). + int? lastSubmittedRevision; + + List<_idtrp1yl.SubmissionRevisionView> revisions; + + DateTime updatedAt; + + /// Returns a shallow copy of this [SubmissionView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + SubmissionView copyWith({ + String? id, + _is.UuidValue? itemUuid, + _igclxad1.SubmissionStatus? status, + _ifp7j30v.SubmissionDeliveryState? delivery, + String? publicationId, + String? publicationName, + String? shownHost, + bool? verified, + bool? accepting, + _i1a71r29.PublicationFields? fields, + String? termsUrl, + bool? consentNeeded, + _igthguer.SubmissionValues? values, + String? publicUrl, + _is.UuidValue? feedbackThreadUuid = const _is.$UndefinedUuidValue(), + String? lastMessage, + DateTime? lastMessageAt = const _is.$UndefinedDateTime(), + int? lastSubmittedRevision, + List<_idtrp1yl.SubmissionRevisionView>? revisions, + DateTime? updatedAt, + }); + @override + Map toJson() { + return { + '__className__': 'SubmissionView', + 'id': id, + 'itemUuid': itemUuid.toJson(), + 'status': status.toJson(), + if (delivery != null) 'delivery': delivery?.toJson(), + 'publicationId': publicationId, + 'publicationName': publicationName, + 'shownHost': shownHost, + 'verified': verified, + 'accepting': accepting, + 'fields': fields.toJson(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'consentNeeded': consentNeeded, + 'values': values.toJson(), + if (publicUrl != null) 'publicUrl': publicUrl, + if (feedbackThreadUuid != null) + 'feedbackThreadUuid': feedbackThreadUuid?.toJson(), + if (lastMessage != null) 'lastMessage': lastMessage, + if (lastMessageAt != null) 'lastMessageAt': lastMessageAt?.toJson(), + if (lastSubmittedRevision != null) + 'lastSubmittedRevision': lastSubmittedRevision, + 'revisions': revisions.toJson(valueToJson: (v) => v.toJson()), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + Map toJsonForProtocol() { + return { + '__className__': 'SubmissionView', + 'id': id, + 'itemUuid': itemUuid.toJson(), + 'status': status.toJson(), + if (delivery != null) 'delivery': delivery?.toJson(), + 'publicationId': publicationId, + 'publicationName': publicationName, + 'shownHost': shownHost, + 'verified': verified, + 'accepting': accepting, + 'fields': fields.toJsonForProtocol(), + if (termsUrl != null) 'termsUrl': termsUrl, + 'consentNeeded': consentNeeded, + 'values': values.toJsonForProtocol(), + if (publicUrl != null) 'publicUrl': publicUrl, + if (feedbackThreadUuid != null) + 'feedbackThreadUuid': feedbackThreadUuid?.toJson(), + if (lastMessage != null) 'lastMessage': lastMessage, + if (lastMessageAt != null) 'lastMessageAt': lastMessageAt?.toJson(), + if (lastSubmittedRevision != null) + 'lastSubmittedRevision': lastSubmittedRevision, + 'revisions': revisions.toJson(valueToJson: (v) => v.toJsonForProtocol()), + 'updatedAt': updatedAt.toJson(), + }; + } + + @override + String toString() { + return _is.SerializationManager.encode(this); + } +} + +class _Undefined {} + +class _SubmissionViewImpl extends SubmissionView { + _SubmissionViewImpl({ + required String id, + required _is.UuidValue itemUuid, + required _igclxad1.SubmissionStatus status, + _ifp7j30v.SubmissionDeliveryState? delivery, + required String publicationId, + required String publicationName, + required String shownHost, + required bool verified, + required bool accepting, + required _i1a71r29.PublicationFields fields, + String? termsUrl, + required bool consentNeeded, + required _igthguer.SubmissionValues values, + String? publicUrl, + _is.UuidValue? feedbackThreadUuid, + String? lastMessage, + DateTime? lastMessageAt, + int? lastSubmittedRevision, + required List<_idtrp1yl.SubmissionRevisionView> revisions, + required DateTime updatedAt, + }) : super._( + id: id, + itemUuid: itemUuid, + status: status, + delivery: delivery, + publicationId: publicationId, + publicationName: publicationName, + shownHost: shownHost, + verified: verified, + accepting: accepting, + fields: fields, + termsUrl: termsUrl, + consentNeeded: consentNeeded, + values: values, + publicUrl: publicUrl, + feedbackThreadUuid: feedbackThreadUuid, + lastMessage: lastMessage, + lastMessageAt: lastMessageAt, + lastSubmittedRevision: lastSubmittedRevision, + revisions: revisions, + updatedAt: updatedAt, + ); + + /// Returns a shallow copy of this [SubmissionView] + /// with some or all fields replaced by the given arguments. + @_is.useResult + @override + SubmissionView copyWith({ + String? id, + _is.UuidValue? itemUuid, + _igclxad1.SubmissionStatus? status, + Object? delivery = _Undefined, + String? publicationId, + String? publicationName, + String? shownHost, + bool? verified, + bool? accepting, + _i1a71r29.PublicationFields? fields, + Object? termsUrl = _Undefined, + bool? consentNeeded, + _igthguer.SubmissionValues? values, + Object? publicUrl = _Undefined, + _is.UuidValue? feedbackThreadUuid = const _is.$UndefinedUuidValue(), + Object? lastMessage = _Undefined, + DateTime? lastMessageAt = const _is.$UndefinedDateTime(), + Object? lastSubmittedRevision = _Undefined, + List<_idtrp1yl.SubmissionRevisionView>? revisions, + DateTime? updatedAt, + }) { + return SubmissionView( + id: id ?? this.id, + itemUuid: itemUuid ?? this.itemUuid, + status: status ?? this.status, + delivery: delivery is _ifp7j30v.SubmissionDeliveryState? + ? delivery + : this.delivery, + publicationId: publicationId ?? this.publicationId, + publicationName: publicationName ?? this.publicationName, + shownHost: shownHost ?? this.shownHost, + verified: verified ?? this.verified, + accepting: accepting ?? this.accepting, + fields: fields ?? this.fields.copyWith(), + termsUrl: termsUrl is String? ? termsUrl : this.termsUrl, + consentNeeded: consentNeeded ?? this.consentNeeded, + values: values ?? this.values.copyWith(), + publicUrl: publicUrl is String? ? publicUrl : this.publicUrl, + feedbackThreadUuid: feedbackThreadUuid is _is.UndefinedSentinel + ? this.feedbackThreadUuid + : feedbackThreadUuid, + lastMessage: lastMessage is String? ? lastMessage : this.lastMessage, + lastMessageAt: lastMessageAt is _is.UndefinedSentinel + ? this.lastMessageAt + : lastMessageAt, + lastSubmittedRevision: lastSubmittedRevision is int? + ? lastSubmittedRevision + : this.lastSubmittedRevision, + revisions: + revisions ?? this.revisions.map((e0) => e0.copyWith()).toList(), + updatedAt: updatedAt ?? this.updatedAt, + ); + } +} diff --git a/wonky_server/lib/src/generated/platform/sharing/drive_item_permission.dart b/wonky_server/lib/src/generated/platform/sharing/drive_item_permission.dart index 37674214..0875dce7 100644 --- a/wonky_server/lib/src/generated/platform/sharing/drive_item_permission.dart +++ b/wonky_server/lib/src/generated/platform/sharing/drive_item_permission.dart @@ -28,6 +28,7 @@ abstract class DriveItemPermission required this.grantedById, required this.grantedAt, this.expiresAt, + this.viaPublicationId, }); factory DriveItemPermission({ @@ -40,6 +41,7 @@ abstract class DriveItemPermission required int grantedById, required DateTime grantedAt, DateTime? expiresAt, + int? viaPublicationId, }) = _DriveItemPermissionImpl; factory DriveItemPermission.fromJson(Map jsonSerialization) { @@ -59,6 +61,7 @@ abstract class DriveItemPermission expiresAt: jsonSerialization['expiresAt'] == null ? null : _is.DateTimeJsonExtension.fromJson(jsonSerialization['expiresAt']), + viaPublicationId: jsonSerialization['viaPublicationId'] as int?, ); } @@ -87,6 +90,9 @@ abstract class DriveItemPermission DateTime? expiresAt; + /// (M14) Moderator grant of a submission (specs/18 §5.1); removed with it. + int? viaPublicationId; + @override _is.Table get table => t; @@ -103,6 +109,7 @@ abstract class DriveItemPermission int? grantedById, DateTime? grantedAt, DateTime? expiresAt = const _is.$UndefinedDateTime(), + int? viaPublicationId, }); @override Map toJson() { @@ -117,6 +124,7 @@ abstract class DriveItemPermission 'grantedById': grantedById, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublicationId != null) 'viaPublicationId': viaPublicationId, }; } @@ -133,6 +141,7 @@ abstract class DriveItemPermission 'grantedById': grantedById, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublicationId != null) 'viaPublicationId': viaPublicationId, }; } @@ -177,6 +186,7 @@ class _DriveItemPermissionImpl extends DriveItemPermission { required int grantedById, required DateTime grantedAt, DateTime? expiresAt, + int? viaPublicationId, }) : super._( id: id, itemId: itemId, @@ -187,6 +197,7 @@ class _DriveItemPermissionImpl extends DriveItemPermission { grantedById: grantedById, grantedAt: grantedAt, expiresAt: expiresAt, + viaPublicationId: viaPublicationId, ); /// Returns a shallow copy of this [DriveItemPermission] @@ -203,6 +214,7 @@ class _DriveItemPermissionImpl extends DriveItemPermission { int? grantedById, DateTime? grantedAt, DateTime? expiresAt = const _is.$UndefinedDateTime(), + Object? viaPublicationId = _Undefined, }) { return DriveItemPermission( id: id is int? ? id : this.id, @@ -218,6 +230,9 @@ class _DriveItemPermissionImpl extends DriveItemPermission { expiresAt: expiresAt is _is.UndefinedSentinel ? this.expiresAt : expiresAt, + viaPublicationId: viaPublicationId is int? + ? viaPublicationId + : this.viaPublicationId, ); } } @@ -270,6 +285,11 @@ class DriveItemPermissionUpdateTable table.expiresAt, value, ); + + _is.ColumnValue viaPublicationId(int? value) => _is.ColumnValue( + table.viaPublicationId, + value, + ); } class DriveItemPermissionTable extends _is.Table { @@ -309,6 +329,10 @@ class DriveItemPermissionTable extends _is.Table { 'expiresAt', this, ); + viaPublicationId = _is.ColumnInt( + 'viaPublicationId', + this, + ); } late final DriveItemPermissionUpdateTable updateTable; @@ -331,6 +355,9 @@ class DriveItemPermissionTable extends _is.Table { late final _is.ColumnDateTime expiresAt; + /// (M14) Moderator grant of a submission (specs/18 §5.1); removed with it. + late final _is.ColumnInt viaPublicationId; + @override List<_is.Column> get columns => [ id, @@ -342,6 +369,7 @@ class DriveItemPermissionTable extends _is.Table { grantedById, grantedAt, expiresAt, + viaPublicationId, ]; } diff --git a/wonky_server/lib/src/generated/platform/sharing/permission_view.dart b/wonky_server/lib/src/generated/platform/sharing/permission_view.dart index 596dc78f..1e636528 100644 --- a/wonky_server/lib/src/generated/platform/sharing/permission_view.dart +++ b/wonky_server/lib/src/generated/platform/sharing/permission_view.dart @@ -25,6 +25,7 @@ abstract class PermissionView this.inheritedFromName, required this.grantedAt, this.expiresAt, + this.viaPublication, }); factory PermissionView({ @@ -35,6 +36,7 @@ abstract class PermissionView String? inheritedFromName, required DateTime grantedAt, DateTime? expiresAt, + String? viaPublication, }) = _PermissionViewImpl; factory PermissionView.fromJson(Map jsonSerialization) { @@ -60,6 +62,7 @@ abstract class PermissionView expiresAt: jsonSerialization['expiresAt'] == null ? null : _is.DateTimeJsonExtension.fromJson(jsonSerialization['expiresAt']), + viaPublication: jsonSerialization['viaPublication'] as String?, ); } @@ -79,6 +82,9 @@ abstract class PermissionView DateTime? expiresAt; + /// (M14) The publication a moderator grant comes from (specs/18 §5.1). + String? viaPublication; + /// Returns a shallow copy of this [PermissionView] /// with some or all fields replaced by the given arguments. @_is.useResult @@ -90,6 +96,7 @@ abstract class PermissionView String? inheritedFromName, DateTime? grantedAt, DateTime? expiresAt = const _is.$UndefinedDateTime(), + String? viaPublication, }); @override Map toJson() { @@ -103,6 +110,7 @@ abstract class PermissionView if (inheritedFromName != null) 'inheritedFromName': inheritedFromName, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublication != null) 'viaPublication': viaPublication, }; } @@ -118,6 +126,7 @@ abstract class PermissionView if (inheritedFromName != null) 'inheritedFromName': inheritedFromName, 'grantedAt': grantedAt.toJson(), if (expiresAt != null) 'expiresAt': expiresAt?.toJson(), + if (viaPublication != null) 'viaPublication': viaPublication, }; } @@ -143,6 +152,7 @@ class _PermissionViewImpl extends PermissionView { String? inheritedFromName, required DateTime grantedAt, DateTime? expiresAt, + String? viaPublication, }) : super._( user: user, invitedEmail: invitedEmail, @@ -151,6 +161,7 @@ class _PermissionViewImpl extends PermissionView { inheritedFromName: inheritedFromName, grantedAt: grantedAt, expiresAt: expiresAt, + viaPublication: viaPublication, ); /// Returns a shallow copy of this [PermissionView] @@ -165,6 +176,7 @@ class _PermissionViewImpl extends PermissionView { Object? inheritedFromName = _Undefined, DateTime? grantedAt, DateTime? expiresAt = const _is.$UndefinedDateTime(), + Object? viaPublication = _Undefined, }) { return PermissionView( user: user is _is.UndefinedSentinel ? this.user?.copyWith() : user, @@ -180,6 +192,9 @@ class _PermissionViewImpl extends PermissionView { expiresAt: expiresAt is _is.UndefinedSentinel ? this.expiresAt : expiresAt, + viaPublication: viaPublication is String? + ? viaPublication + : this.viaPublication, ); } } diff --git a/wonky_server/lib/src/generated/protocol.dart b/wonky_server/lib/src/generated/protocol.dart index 193e0e9d..bc725709 100644 --- a/wonky_server/lib/src/generated/protocol.dart +++ b/wonky_server/lib/src/generated/protocol.dart @@ -39,6 +39,10 @@ import 'package:wonky_server/src/generated/platform/drive/template_view.dart' as _ibinmr4r; import 'package:wonky_server/src/generated/platform/files/file_url_view.dart' as _i28n3m1r; +import 'package:wonky_server/src/generated/platform/publications/models/publication_delivery_view.dart' + as _idovycpn; +import 'package:wonky_server/src/generated/platform/publications/models/publication_settings.dart' + as _i9ilkmgj; import 'package:wonky_server/src/generated/platform/revlog/models/rev_op_view.dart' as _iu7aww0d; import 'package:wonky_server/src/generated/platform/users/access_token_view.dart' @@ -87,6 +91,8 @@ import 'future_calls_generated_models/file_preview_future_call_generate_model.da as _ilpvgw0t; import 'future_calls_generated_models/notification_email_future_call_send_model.dart' as _inb6x2l0; +import 'future_calls_generated_models/publications_future_call_deliver_model.dart' + as _il37cz87; import 'future_calls_generated_models/storage_future_call_refresh_item_size_model.dart' as _io4auc29; import 'platform/activity/activity_dashboard.dart' as _izr1y672; @@ -231,6 +237,36 @@ import 'platform/presence/presence_bus_message.dart' as _i7dp90q0; import 'platform/presence/presence_event.dart' as _i8r9afjv; import 'platform/presence/presence_state.dart' as _ik055xb9; import 'platform/presence/presence_update.dart' as _isz2sju0; +import 'platform/publications/models/publication.dart' as _ikkxb56h; +import 'platform/publications/models/publication_block.dart' as _i5vk42yw; +import 'platform/publications/models/publication_card.dart' as _i9g6l3wu; +import 'platform/publications/models/publication_check_result.dart' + as _i0a1sw0a; +import 'platform/publications/models/publication_consent.dart' as _iqa48qn0; +import 'platform/publications/models/publication_delivery.dart' as _ihiygfti; +import 'platform/publications/models/publication_delivery_view.dart' + as _iz1gego0; +import 'platform/publications/models/publication_field_mode.dart' as _iucp51pg; +import 'platform/publications/models/publication_fields.dart' as _i63wbtw0; +import 'platform/publications/models/publication_input.dart' as _iv6bey6s; +import 'platform/publications/models/publication_moderator.dart' as _i1u9dlta; +import 'platform/publications/models/publication_moderator_view.dart' + as _ij9tsbn9; +import 'platform/publications/models/publication_open_submission.dart' + as _ivvukfve; +import 'platform/publications/models/publication_secret.dart' as _iyqlj2kr; +import 'platform/publications/models/publication_settings.dart' as _i5i48220; +import 'platform/publications/models/submission.dart' as _ipbg6o7y; +import 'platform/publications/models/submission_asset.dart' as _i49gtkgr; +import 'platform/publications/models/submission_delivery_state.dart' + as _ip6l83ta; +import 'platform/publications/models/submission_revision.dart' as _i71zy0hy; +import 'platform/publications/models/submission_revision_view.dart' + as _iegijpud; +import 'platform/publications/models/submission_started.dart' as _ijb8v3k4; +import 'platform/publications/models/submission_status.dart' as _i7hbulg4; +import 'platform/publications/models/submission_values.dart' as _iq9uje8l; +import 'platform/publications/models/submission_view.dart' as _iakndug7; import 'platform/revlog/messages/rev_client_message.dart' as _i6ck957q; import 'platform/revlog/messages/rev_server_message.dart' as _ie6clghy; import 'platform/revlog/models/rev_bus_message.dart' as _iyewfisw; @@ -557,6 +593,30 @@ export 'platform/presence/presence_bus_message.dart'; export 'platform/presence/presence_event.dart'; export 'platform/presence/presence_state.dart'; export 'platform/presence/presence_update.dart'; +export 'platform/publications/models/publication.dart'; +export 'platform/publications/models/publication_block.dart'; +export 'platform/publications/models/publication_card.dart'; +export 'platform/publications/models/publication_check_result.dart'; +export 'platform/publications/models/publication_consent.dart'; +export 'platform/publications/models/publication_delivery.dart'; +export 'platform/publications/models/publication_delivery_view.dart'; +export 'platform/publications/models/publication_field_mode.dart'; +export 'platform/publications/models/publication_fields.dart'; +export 'platform/publications/models/publication_input.dart'; +export 'platform/publications/models/publication_moderator.dart'; +export 'platform/publications/models/publication_moderator_view.dart'; +export 'platform/publications/models/publication_open_submission.dart'; +export 'platform/publications/models/publication_secret.dart'; +export 'platform/publications/models/publication_settings.dart'; +export 'platform/publications/models/submission.dart'; +export 'platform/publications/models/submission_asset.dart'; +export 'platform/publications/models/submission_delivery_state.dart'; +export 'platform/publications/models/submission_revision.dart'; +export 'platform/publications/models/submission_revision_view.dart'; +export 'platform/publications/models/submission_started.dart'; +export 'platform/publications/models/submission_status.dart'; +export 'platform/publications/models/submission_values.dart'; +export 'platform/publications/models/submission_view.dart'; export 'platform/revlog/messages/rev_client_message.dart'; export 'platform/revlog/messages/rev_server_message.dart'; export 'platform/revlog/models/rev_bus_message.dart'; @@ -763,6 +823,7 @@ class Protocol extends _is.DatabaseSerializationManager _is.getType<_i5z3lvv6.BoardGithubFutureCallReviewModel>, _is.getType<_ilpvgw0t.FilePreviewFutureCallGenerateModel>, _is.getType<_inb6x2l0.NotificationEmailFutureCallSendModel>, + _is.getType<_il37cz87.PublicationsFutureCallDeliverModel>, _is.getType<_io4auc29.StorageFutureCallRefreshItemSizeModel>, _is.getType<_izr1y672.ActivityDashboard>, _is.getType<_iatdjl5p.ActivityEvent>, @@ -918,6 +979,30 @@ class Protocol extends _is.DatabaseSerializationManager _is.getType<_i8r9afjv.PresenceUpdated>, _is.getType<_ik055xb9.PresenceState>, _is.getType<_isz2sju0.PresenceUpdate>, + _is.getType<_ikkxb56h.Publication>, + _is.getType<_i5vk42yw.PublicationBlock>, + _is.getType<_i9g6l3wu.PublicationCard>, + _is.getType<_i0a1sw0a.PublicationCheckResult>, + _is.getType<_iqa48qn0.PublicationConsent>, + _is.getType<_ihiygfti.PublicationDelivery>, + _is.getType<_iz1gego0.PublicationDeliveryView>, + _is.getType<_iucp51pg.PublicationFieldMode>, + _is.getType<_i63wbtw0.PublicationFields>, + _is.getType<_iv6bey6s.PublicationInput>, + _is.getType<_i1u9dlta.PublicationModerator>, + _is.getType<_ij9tsbn9.PublicationModeratorView>, + _is.getType<_ivvukfve.PublicationOpenSubmission>, + _is.getType<_iyqlj2kr.PublicationSecret>, + _is.getType<_i5i48220.PublicationSettings>, + _is.getType<_ipbg6o7y.Submission>, + _is.getType<_i49gtkgr.SubmissionAsset>, + _is.getType<_ip6l83ta.SubmissionDeliveryState>, + _is.getType<_i71zy0hy.SubmissionRevision>, + _is.getType<_iegijpud.SubmissionRevisionView>, + _is.getType<_ijb8v3k4.SubmissionStarted>, + _is.getType<_i7hbulg4.SubmissionStatus>, + _is.getType<_iq9uje8l.SubmissionValues>, + _is.getType<_iakndug7.SubmissionView>, _is.getType<_ie6clghy.RevAck>, _is.getType<_i6ck957q.RevPing>, _is.getType<_i6ck957q.RevRequestOps>, @@ -1145,6 +1230,7 @@ class Protocol extends _is.DatabaseSerializationManager _is.getType<_i5z3lvv6.BoardGithubFutureCallReviewModel?>, _is.getType<_ilpvgw0t.FilePreviewFutureCallGenerateModel?>, _is.getType<_inb6x2l0.NotificationEmailFutureCallSendModel?>, + _is.getType<_il37cz87.PublicationsFutureCallDeliverModel?>, _is.getType<_io4auc29.StorageFutureCallRefreshItemSizeModel?>, _is.getType<_izr1y672.ActivityDashboard?>, _is.getType<_iatdjl5p.ActivityEvent?>, @@ -1300,6 +1386,30 @@ class Protocol extends _is.DatabaseSerializationManager _is.getType<_i8r9afjv.PresenceUpdated?>, _is.getType<_ik055xb9.PresenceState?>, _is.getType<_isz2sju0.PresenceUpdate?>, + _is.getType<_ikkxb56h.Publication?>, + _is.getType<_i5vk42yw.PublicationBlock?>, + _is.getType<_i9g6l3wu.PublicationCard?>, + _is.getType<_i0a1sw0a.PublicationCheckResult?>, + _is.getType<_iqa48qn0.PublicationConsent?>, + _is.getType<_ihiygfti.PublicationDelivery?>, + _is.getType<_iz1gego0.PublicationDeliveryView?>, + _is.getType<_iucp51pg.PublicationFieldMode?>, + _is.getType<_i63wbtw0.PublicationFields?>, + _is.getType<_iv6bey6s.PublicationInput?>, + _is.getType<_i1u9dlta.PublicationModerator?>, + _is.getType<_ij9tsbn9.PublicationModeratorView?>, + _is.getType<_ivvukfve.PublicationOpenSubmission?>, + _is.getType<_iyqlj2kr.PublicationSecret?>, + _is.getType<_i5i48220.PublicationSettings?>, + _is.getType<_ipbg6o7y.Submission?>, + _is.getType<_i49gtkgr.SubmissionAsset?>, + _is.getType<_ip6l83ta.SubmissionDeliveryState?>, + _is.getType<_i71zy0hy.SubmissionRevision?>, + _is.getType<_iegijpud.SubmissionRevisionView?>, + _is.getType<_ijb8v3k4.SubmissionStarted?>, + _is.getType<_i7hbulg4.SubmissionStatus?>, + _is.getType<_iq9uje8l.SubmissionValues?>, + _is.getType<_iakndug7.SubmissionView?>, _is.getType<_ie6clghy.RevAck?>, _is.getType<_i6ck957q.RevPing?>, _is.getType<_i6ck957q.RevRequestOps?>, @@ -1551,6 +1661,9 @@ class Protocol extends _is.DatabaseSerializationManager _is.getType>, _is.getType>, _is.getType>, + _is.getType>, + _is.getType>, + _is.getType>, _is.getType>, _is.getType?>, _is.getType>, @@ -1585,7 +1698,9 @@ class Protocol extends _is.DatabaseSerializationManager _is.getType>, _is.getType>, _is.getType>, + _is.getType>, _is.getType>, + _is.getType>, _is.getType>, _is.getType>, _is.getType>, @@ -4811,6 +4926,12 @@ class Protocol extends _is.DatabaseSerializationManager isNullable: true, dartType: 'protocol:CommentSystemEvent?', ), + _isp.ColumnDefinition( + name: 'publicationId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), ], foreignKeys: [ _isp.ForeignKeyDefinition( @@ -4823,6 +4944,16 @@ class Protocol extends _is.DatabaseSerializationManager onDelete: _isp.ForeignKeyAction.cascade, matchType: null, ), + _isp.ForeignKeyDefinition( + constraintName: 'comment_fk_1', + columns: ['publicationId'], + referenceTable: 'publication', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.setNull, + matchType: null, + ), ], indexes: [ _isp.IndexDefinition( @@ -6593,6 +6724,12 @@ class Protocol extends _is.DatabaseSerializationManager isNullable: true, dartType: 'DateTime?', ), + _isp.ColumnDefinition( + name: 'viaPublicationId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), ], foreignKeys: [ _isp.ForeignKeyDefinition( @@ -6615,6 +6752,16 @@ class Protocol extends _is.DatabaseSerializationManager onDelete: _isp.ForeignKeyAction.cascade, matchType: null, ), + _isp.ForeignKeyDefinition( + constraintName: 'drive_item_permission_fk_2', + columns: ['viaPublicationId'], + referenceTable: 'publication', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), ], indexes: [ _isp.IndexDefinition( @@ -8462,8 +8609,8 @@ class Protocol extends _is.DatabaseSerializationManager managed: true, ), _isp.TableDefinition( - name: 'rev_file', - dartName: 'RevFile', + name: 'publication', + dartName: 'Publication', schema: 'public', module: 'wonky', columns: [ @@ -8475,70 +8622,101 @@ class Protocol extends _is.DatabaseSerializationManager columnDefault: 'serial', ), _isp.ColumnDefinition( - name: 'fileUuid', - columnType: _isp.ColumnType.uuid, - isNullable: false, - dartType: 'UuidValue', - ), - _isp.ColumnDefinition( - name: 'kind', + name: 'publicId', columnType: _isp.ColumnType.text, isNullable: false, - dartType: 'protocol:RevFileKind', + dartType: 'String', ), _isp.ColumnDefinition( - name: 'itemId', + name: 'ownerId', columnType: _isp.ColumnType.bigint, isNullable: false, dartType: 'int', ), _isp.ColumnDefinition( - name: 'headRevision', - columnType: _isp.ColumnType.bigint, + name: 'name', + columnType: _isp.ColumnType.text, isNullable: false, - dartType: 'int', - columnDefault: '0', + dartType: 'String', ), _isp.ColumnDefinition( - name: 'prunedBelow', - columnType: _isp.ColumnType.bigint, + name: 'siteUrl', + columnType: _isp.ColumnType.text, isNullable: false, - dartType: 'int', - columnDefault: '0', + dartType: 'String', ), _isp.ColumnDefinition( - name: 'initPending', - columnType: _isp.ColumnType.boolean, + name: 'webhookUrl', + columnType: _isp.ColumnType.text, isNullable: false, - dartType: 'bool', - columnDefault: 'false', + dartType: 'String', ), _isp.ColumnDefinition( - name: 'purging', - columnType: _isp.ColumnType.boolean, - isNullable: false, - dartType: 'bool', - columnDefault: 'false', + name: 'verifiedHost', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', ), _isp.ColumnDefinition( - name: 'schemaHash', + name: 'verifiedAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'templateItemId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'termsUrl', columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'fields', + columnType: _isp.ColumnType.json, isNullable: false, - dartType: 'String', + dartType: 'protocol:PublicationFields', ), _isp.ColumnDefinition( - name: 'stats', + name: 'signingSecret', columnType: _isp.ColumnType.text, isNullable: false, dartType: 'String', - columnDefault: '\'{}\'', ), _isp.ColumnDefinition( - name: 'contentCount', - columnType: _isp.ColumnType.bigint, + name: 'previousSigningSecret', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'previousSecretUntil', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'apiKeyHash', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'apiKeyLast4', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'enabled', + columnType: _isp.ColumnType.boolean, isNullable: false, - dartType: 'int', - columnDefault: '0', + dartType: 'bool', + columnDefault: 'true', ), _isp.ColumnDefinition( name: 'createdAt', @@ -8555,24 +8733,34 @@ class Protocol extends _is.DatabaseSerializationManager ], foreignKeys: [ _isp.ForeignKeyDefinition( - constraintName: 'rev_file_fk_0', - columns: ['itemId'], + constraintName: 'publication_fk_0', + columns: ['ownerId'], + referenceTable: 'user_profile', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + _isp.ForeignKeyDefinition( + constraintName: 'publication_fk_1', + columns: ['templateItemId'], referenceTable: 'drive_item', referenceTableSchema: 'public', referenceColumns: ['id'], onUpdate: _isp.ForeignKeyAction.noAction, - onDelete: _isp.ForeignKeyAction.restrict, + onDelete: _isp.ForeignKeyAction.setNull, matchType: null, ), ], indexes: [ _isp.IndexDefinition( - indexName: 'rev_file_uuid_idx', + indexName: 'publication_public_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'fileUuid', + definition: 'publicId', ), ], type: 'btree', @@ -8580,24 +8768,37 @@ class Protocol extends _is.DatabaseSerializationManager isPrimary: false, ), _isp.IndexDefinition( - indexName: 'rev_file_item_idx', + indexName: 'publication_owner_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'itemId', + definition: 'ownerId', ), ], type: 'btree', - isUnique: true, + isUnique: false, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'publication_api_key_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'apiKeyHash', + ), + ], + type: 'btree', + isUnique: false, isPrimary: false, ), ], managed: true, ), _isp.TableDefinition( - name: 'rev_hook_state', - dartName: 'RevHookState', + name: 'publication_block', + dartName: 'PublicationBlock', schema: 'public', module: 'wonky', columns: [ @@ -8609,50 +8810,19 @@ class Protocol extends _is.DatabaseSerializationManager columnDefault: 'serial', ), _isp.ColumnDefinition( - name: 'fileId', + name: 'publicationId', columnType: _isp.ColumnType.bigint, isNullable: false, dartType: 'int', ), _isp.ColumnDefinition( - name: 'cursorsJson', - columnType: _isp.ColumnType.text, - isNullable: false, - dartType: 'String', - ), - _isp.ColumnDefinition( - name: 'leaseOwner', - columnType: _isp.ColumnType.text, - isNullable: true, - dartType: 'String?', - ), - _isp.ColumnDefinition( - name: 'leaseUntil', - columnType: _isp.ColumnType.timestampWithoutTimeZone, - isNullable: true, - dartType: 'DateTime?', - ), - _isp.ColumnDefinition( - name: 'attempts', + name: 'userId', columnType: _isp.ColumnType.bigint, isNullable: false, dartType: 'int', - columnDefault: '0', - ), - _isp.ColumnDefinition( - name: 'lastError', - columnType: _isp.ColumnType.text, - isNullable: true, - dartType: 'String?', - ), - _isp.ColumnDefinition( - name: 'nextAttemptAt', - columnType: _isp.ColumnType.timestampWithoutTimeZone, - isNullable: true, - dartType: 'DateTime?', ), _isp.ColumnDefinition( - name: 'updatedAt', + name: 'at', columnType: _isp.ColumnType.timestampWithoutTimeZone, isNullable: false, dartType: 'DateTime', @@ -8660,9 +8830,19 @@ class Protocol extends _is.DatabaseSerializationManager ], foreignKeys: [ _isp.ForeignKeyDefinition( - constraintName: 'rev_hook_state_fk_0', - columns: ['fileId'], - referenceTable: 'rev_file', + constraintName: 'publication_block_fk_0', + columns: ['publicationId'], + referenceTable: 'publication', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + _isp.ForeignKeyDefinition( + constraintName: 'publication_block_fk_1', + columns: ['userId'], + referenceTable: 'user_profile', referenceTableSchema: 'public', referenceColumns: ['id'], onUpdate: _isp.ForeignKeyAction.noAction, @@ -8672,37 +8852,28 @@ class Protocol extends _is.DatabaseSerializationManager ], indexes: [ _isp.IndexDefinition( - indexName: 'rev_hook_state_file_idx', + indexName: 'publication_block_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'fileId', + definition: 'publicationId', ), - ], - type: 'btree', - isUnique: true, - isPrimary: false, - ), - _isp.IndexDefinition( - indexName: 'rev_hook_state_due_idx', - tableSpace: null, - elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'nextAttemptAt', + definition: 'userId', ), ], type: 'btree', - isUnique: false, + isUnique: true, isPrimary: false, ), ], managed: true, ), _isp.TableDefinition( - name: 'rev_op', - dartName: 'RevOp', + name: 'publication_consent', + dartName: 'PublicationConsent', schema: 'public', module: 'wonky', columns: [ @@ -8714,48 +8885,624 @@ class Protocol extends _is.DatabaseSerializationManager columnDefault: 'serial', ), _isp.ColumnDefinition( - name: 'fileId', + name: 'publicationId', columnType: _isp.ColumnType.bigint, isNullable: false, dartType: 'int', ), _isp.ColumnDefinition( - name: 'revision', + name: 'userId', columnType: _isp.ColumnType.bigint, isNullable: false, dartType: 'int', ), _isp.ColumnDefinition( - name: 'clientOpId', - columnType: _isp.ColumnType.uuid, + name: 'consentKey', + columnType: _isp.ColumnType.text, isNullable: false, - dartType: 'UuidValue', + dartType: 'String', ), _isp.ColumnDefinition( - name: 'baseRevision', - columnType: _isp.ColumnType.bigint, + name: 'at', + columnType: _isp.ColumnType.timestampWithoutTimeZone, isNullable: false, - dartType: 'int', - ), - _isp.ColumnDefinition( - name: 'authorId', - columnType: _isp.ColumnType.bigint, - isNullable: true, - dartType: 'int?', + dartType: 'DateTime', ), - _isp.ColumnDefinition( - name: 'authorUuid', - columnType: _isp.ColumnType.uuid, - isNullable: true, - dartType: 'UuidValue?', + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'publication_consent_fk_0', + columns: ['publicationId'], + referenceTable: 'publication', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, ), - _isp.ColumnDefinition( - name: 'sessionId', - columnType: _isp.ColumnType.text, - isNullable: true, - dartType: 'String?', + _isp.ForeignKeyDefinition( + constraintName: 'publication_consent_fk_1', + columns: ['userId'], + referenceTable: 'user_profile', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, ), - _isp.ColumnDefinition( + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'publication_consent_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'publicationId', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'userId', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'publication_delivery', + dartName: 'PublicationDelivery', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'publicationId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'submissionId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'webhookId', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'type', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'sequence', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'payload', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'attempts', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + columnDefault: '0', + ), + _isp.ColumnDefinition( + name: 'nextAttemptAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'leaseUntil', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'lastStatus', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'lastError', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'deliveredAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'failedAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'createdAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'publication_delivery_fk_0', + columns: ['publicationId'], + referenceTable: 'publication', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + _isp.ForeignKeyDefinition( + constraintName: 'publication_delivery_fk_1', + columns: ['submissionId'], + referenceTable: 'submission', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.setNull, + matchType: null, + ), + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'publication_delivery_webhook_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'webhookId', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'publication_delivery_due_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'nextAttemptAt', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'publication_delivery_publication_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'publicationId', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'createdAt', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'publication_moderator', + dartName: 'PublicationModerator', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'publicationId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'userId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'email', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'publication_moderator_fk_0', + columns: ['publicationId'], + referenceTable: 'publication', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + _isp.ForeignKeyDefinition( + constraintName: 'publication_moderator_fk_1', + columns: ['userId'], + referenceTable: 'user_profile', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'publication_moderator_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'publicationId', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'email', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'publication_moderator_user_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'userId', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'rev_file', + dartName: 'RevFile', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'fileUuid', + columnType: _isp.ColumnType.uuid, + isNullable: false, + dartType: 'UuidValue', + ), + _isp.ColumnDefinition( + name: 'kind', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'protocol:RevFileKind', + ), + _isp.ColumnDefinition( + name: 'itemId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'headRevision', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + columnDefault: '0', + ), + _isp.ColumnDefinition( + name: 'prunedBelow', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + columnDefault: '0', + ), + _isp.ColumnDefinition( + name: 'initPending', + columnType: _isp.ColumnType.boolean, + isNullable: false, + dartType: 'bool', + columnDefault: 'false', + ), + _isp.ColumnDefinition( + name: 'purging', + columnType: _isp.ColumnType.boolean, + isNullable: false, + dartType: 'bool', + columnDefault: 'false', + ), + _isp.ColumnDefinition( + name: 'schemaHash', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'stats', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + columnDefault: '\'{}\'', + ), + _isp.ColumnDefinition( + name: 'contentCount', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + columnDefault: '0', + ), + _isp.ColumnDefinition( + name: 'createdAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + _isp.ColumnDefinition( + name: 'updatedAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'rev_file_fk_0', + columns: ['itemId'], + referenceTable: 'drive_item', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.restrict, + matchType: null, + ), + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'rev_file_uuid_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'fileUuid', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'rev_file_item_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'itemId', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'rev_hook_state', + dartName: 'RevHookState', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'fileId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'cursorsJson', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'leaseOwner', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'leaseUntil', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'attempts', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + columnDefault: '0', + ), + _isp.ColumnDefinition( + name: 'lastError', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( + name: 'nextAttemptAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), + _isp.ColumnDefinition( + name: 'updatedAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'rev_hook_state_fk_0', + columns: ['fileId'], + referenceTable: 'rev_file', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'rev_hook_state_file_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'fileId', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'rev_hook_state_due_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'nextAttemptAt', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'rev_op', + dartName: 'RevOp', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'fileId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'revision', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'clientOpId', + columnType: _isp.ColumnType.uuid, + isNullable: false, + dartType: 'UuidValue', + ), + _isp.ColumnDefinition( + name: 'baseRevision', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'authorId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'authorUuid', + columnType: _isp.ColumnType.uuid, + isNullable: true, + dartType: 'UuidValue?', + ), + _isp.ColumnDefinition( + name: 'sessionId', + columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'String?', + ), + _isp.ColumnDefinition( name: 'onBehalfOfSessionId', columnType: _isp.ColumnType.text, isNullable: true, @@ -12724,7 +13471,122 @@ class Protocol extends _is.DatabaseSerializationManager ), _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'id', + definition: 'id', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'storage_reservation', + dartName: 'StorageReservation', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'userId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'fileUuid', + columnType: _isp.ColumnType.uuid, + isNullable: false, + dartType: 'UuidValue', + ), + _isp.ColumnDefinition( + name: 'itemId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'bytes', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'createdAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + _isp.ColumnDefinition( + name: 'expiresAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'storage_reservation_fk_0', + columns: ['userId'], + referenceTable: 'user_profile', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + _isp.ForeignKeyDefinition( + constraintName: 'storage_reservation_fk_1', + columns: ['itemId'], + referenceTable: 'drive_item', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'storage_reservation_file_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'fileUuid', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'storage_reservation_user_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'userId', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'storage_reservation_expiry_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'expiresAt', ), ], type: 'btree', @@ -12735,8 +13597,8 @@ class Protocol extends _is.DatabaseSerializationManager managed: true, ), _isp.TableDefinition( - name: 'storage_reservation', - dartName: 'StorageReservation', + name: 'stored_file', + dartName: 'StoredFile', schema: 'public', module: 'wonky', columns: [ @@ -12747,18 +13609,18 @@ class Protocol extends _is.DatabaseSerializationManager dartType: 'int?', columnDefault: 'serial', ), - _isp.ColumnDefinition( - name: 'userId', - columnType: _isp.ColumnType.bigint, - isNullable: false, - dartType: 'int', - ), _isp.ColumnDefinition( name: 'fileUuid', columnType: _isp.ColumnType.uuid, isNullable: false, dartType: 'UuidValue', ), + _isp.ColumnDefinition( + name: 'ownerId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), _isp.ColumnDefinition( name: 'itemId', columnType: _isp.ColumnType.bigint, @@ -12766,37 +13628,79 @@ class Protocol extends _is.DatabaseSerializationManager dartType: 'int?', ), _isp.ColumnDefinition( - name: 'bytes', + name: 'kind', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'protocol:StoredFileKind', + ), + _isp.ColumnDefinition( + name: 'storageId', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'path', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'fileName', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'mimeType', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'sizeBytes', columnType: _isp.ColumnType.bigint, isNullable: false, dartType: 'int', ), + _isp.ColumnDefinition( + name: 'status', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'protocol:StoredFileStatus', + ), _isp.ColumnDefinition( name: 'createdAt', columnType: _isp.ColumnType.timestampWithoutTimeZone, isNullable: false, dartType: 'DateTime', ), + _isp.ColumnDefinition( + name: 'completedAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: true, + dartType: 'DateTime?', + ), _isp.ColumnDefinition( name: 'expiresAt', columnType: _isp.ColumnType.timestampWithoutTimeZone, - isNullable: false, - dartType: 'DateTime', + isNullable: true, + dartType: 'DateTime?', ), ], foreignKeys: [ _isp.ForeignKeyDefinition( - constraintName: 'storage_reservation_fk_0', - columns: ['userId'], + constraintName: 'stored_file_fk_0', + columns: ['ownerId'], referenceTable: 'user_profile', referenceTableSchema: 'public', referenceColumns: ['id'], onUpdate: _isp.ForeignKeyAction.noAction, - onDelete: _isp.ForeignKeyAction.cascade, + onDelete: _isp.ForeignKeyAction.setNull, matchType: null, ), _isp.ForeignKeyDefinition( - constraintName: 'storage_reservation_fk_1', + constraintName: 'stored_file_fk_1', columns: ['itemId'], referenceTable: 'drive_item', referenceTableSchema: 'public', @@ -12808,7 +13712,7 @@ class Protocol extends _is.DatabaseSerializationManager ], indexes: [ _isp.IndexDefinition( - indexName: 'storage_reservation_file_idx', + indexName: 'stored_file_uuid_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( @@ -12821,12 +13725,12 @@ class Protocol extends _is.DatabaseSerializationManager isPrimary: false, ), _isp.IndexDefinition( - indexName: 'storage_reservation_user_idx', + indexName: 'stored_file_item_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'userId', + definition: 'itemId', ), ], type: 'btree', @@ -12834,7 +13738,7 @@ class Protocol extends _is.DatabaseSerializationManager isPrimary: false, ), _isp.IndexDefinition( - indexName: 'storage_reservation_expiry_idx', + indexName: 'stored_file_expiry_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( @@ -12846,12 +13750,50 @@ class Protocol extends _is.DatabaseSerializationManager isUnique: false, isPrimary: false, ), + _isp.IndexDefinition( + indexName: 'stored_file_owner_kind_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'ownerId', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'kind', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'createdAt', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'stored_file_status_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'status', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'createdAt', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), ], managed: true, ), _isp.TableDefinition( - name: 'stored_file', - dartName: 'StoredFile', + name: 'submission', + dartName: 'Submission', schema: 'public', module: 'wonky', columns: [ @@ -12863,64 +13805,70 @@ class Protocol extends _is.DatabaseSerializationManager columnDefault: 'serial', ), _isp.ColumnDefinition( - name: 'fileUuid', + name: 'uuid', columnType: _isp.ColumnType.uuid, isNullable: false, dartType: 'UuidValue', ), _isp.ColumnDefinition( - name: 'ownerId', + name: 'publicationId', columnType: _isp.ColumnType.bigint, - isNullable: true, - dartType: 'int?', + isNullable: false, + dartType: 'int', ), _isp.ColumnDefinition( name: 'itemId', columnType: _isp.ColumnType.bigint, - isNullable: true, - dartType: 'int?', + isNullable: false, + dartType: 'int', ), _isp.ColumnDefinition( - name: 'kind', + name: 'ref', columnType: _isp.ColumnType.text, - isNullable: false, - dartType: 'protocol:StoredFileKind', + isNullable: true, + dartType: 'String?', ), _isp.ColumnDefinition( - name: 'storageId', + name: 'status', columnType: _isp.ColumnType.text, isNullable: false, - dartType: 'String', + dartType: 'protocol:SubmissionStatus', ), _isp.ColumnDefinition( - name: 'path', + name: 'statusBeforeSubmit', columnType: _isp.ColumnType.text, - isNullable: false, - dartType: 'String', + isNullable: true, + dartType: 'protocol:SubmissionStatus?', ), _isp.ColumnDefinition( - name: 'fileName', + name: 'delivery', columnType: _isp.ColumnType.text, + isNullable: true, + dartType: 'protocol:SubmissionDeliveryState?', + ), + _isp.ColumnDefinition( + name: 'values', + columnType: _isp.ColumnType.json, isNullable: false, - dartType: 'String', + dartType: 'protocol:SubmissionValues', ), _isp.ColumnDefinition( - name: 'mimeType', + name: 'publicUrl', columnType: _isp.ColumnType.text, - isNullable: false, - dartType: 'String', + isNullable: true, + dartType: 'String?', ), _isp.ColumnDefinition( - name: 'sizeBytes', + name: 'feedbackThreadId', columnType: _isp.ColumnType.bigint, - isNullable: false, - dartType: 'int', + isNullable: true, + dartType: 'int?', ), _isp.ColumnDefinition( - name: 'status', - columnType: _isp.ColumnType.text, + name: 'createdById', + columnType: _isp.ColumnType.bigint, isNullable: false, - dartType: 'protocol:StoredFileStatus', + dartType: 'int', ), _isp.ColumnDefinition( name: 'createdAt', @@ -12929,13 +13877,13 @@ class Protocol extends _is.DatabaseSerializationManager dartType: 'DateTime', ), _isp.ColumnDefinition( - name: 'completedAt', + name: 'updatedAt', columnType: _isp.ColumnType.timestampWithoutTimeZone, - isNullable: true, - dartType: 'DateTime?', + isNullable: false, + dartType: 'DateTime', ), _isp.ColumnDefinition( - name: 'expiresAt', + name: 'disconnectedAt', columnType: _isp.ColumnType.timestampWithoutTimeZone, isNullable: true, dartType: 'DateTime?', @@ -12943,19 +13891,104 @@ class Protocol extends _is.DatabaseSerializationManager ], foreignKeys: [ _isp.ForeignKeyDefinition( - constraintName: 'stored_file_fk_0', - columns: ['ownerId'], - referenceTable: 'user_profile', + constraintName: 'submission_fk_0', + columns: ['publicationId'], + referenceTable: 'publication', referenceTableSchema: 'public', referenceColumns: ['id'], onUpdate: _isp.ForeignKeyAction.noAction, - onDelete: _isp.ForeignKeyAction.setNull, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, + ), + _isp.ForeignKeyDefinition( + constraintName: 'submission_fk_1', + columns: ['itemId'], + referenceTable: 'drive_item', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, matchType: null, ), + ], + indexes: [ + _isp.IndexDefinition( + indexName: 'submission_uuid_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'uuid', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'submission_item_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'itemId', + ), + ], + type: 'btree', + isUnique: true, + isPrimary: false, + ), + _isp.IndexDefinition( + indexName: 'submission_publication_idx', + tableSpace: null, + elements: [ + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'publicationId', + ), + _isp.IndexElementDefinition( + type: _isp.IndexElementDefinitionType.column, + definition: 'status', + ), + ], + type: 'btree', + isUnique: false, + isPrimary: false, + ), + ], + managed: true, + ), + _isp.TableDefinition( + name: 'submission_asset', + dartName: 'SubmissionAsset', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'submissionId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'fileUuid', + columnType: _isp.ColumnType.uuid, + isNullable: false, + dartType: 'UuidValue', + ), + ], + foreignKeys: [ _isp.ForeignKeyDefinition( - constraintName: 'stored_file_fk_1', - columns: ['itemId'], - referenceTable: 'drive_item', + constraintName: 'submission_asset_fk_0', + columns: ['submissionId'], + referenceTable: 'submission', referenceTableSchema: 'public', referenceColumns: ['id'], onUpdate: _isp.ForeignKeyAction.noAction, @@ -12965,80 +13998,128 @@ class Protocol extends _is.DatabaseSerializationManager ], indexes: [ _isp.IndexDefinition( - indexName: 'stored_file_uuid_idx', + indexName: 'submission_asset_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'fileUuid', + definition: 'submissionId', ), - ], - type: 'btree', - isUnique: true, - isPrimary: false, - ), - _isp.IndexDefinition( - indexName: 'stored_file_item_idx', - tableSpace: null, - elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'itemId', + definition: 'fileUuid', ), ], type: 'btree', - isUnique: false, + isUnique: true, isPrimary: false, ), _isp.IndexDefinition( - indexName: 'stored_file_expiry_idx', + indexName: 'submission_asset_file_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'expiresAt', + definition: 'fileUuid', ), ], type: 'btree', isUnique: false, isPrimary: false, ), - _isp.IndexDefinition( - indexName: 'stored_file_owner_kind_idx', - tableSpace: null, - elements: [ - _isp.IndexElementDefinition( - type: _isp.IndexElementDefinitionType.column, - definition: 'ownerId', - ), - _isp.IndexElementDefinition( - type: _isp.IndexElementDefinitionType.column, - definition: 'kind', - ), - _isp.IndexElementDefinition( - type: _isp.IndexElementDefinitionType.column, - definition: 'createdAt', - ), - ], - type: 'btree', - isUnique: false, - isPrimary: false, + ], + managed: true, + ), + _isp.TableDefinition( + name: 'submission_revision', + dartName: 'SubmissionRevision', + schema: 'public', + module: 'wonky', + columns: [ + _isp.ColumnDefinition( + name: 'id', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int?', + columnDefault: 'serial', + ), + _isp.ColumnDefinition( + name: 'submissionId', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'sequence', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'revision', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'versionId', + columnType: _isp.ColumnType.bigint, + isNullable: true, + dartType: 'int?', + ), + _isp.ColumnDefinition( + name: 'values', + columnType: _isp.ColumnType.json, + isNullable: false, + dartType: 'protocol:SubmissionValues', + ), + _isp.ColumnDefinition( + name: 'payload', + columnType: _isp.ColumnType.text, + isNullable: false, + dartType: 'String', + ), + _isp.ColumnDefinition( + name: 'submittedById', + columnType: _isp.ColumnType.bigint, + isNullable: false, + dartType: 'int', + ), + _isp.ColumnDefinition( + name: 'submittedAt', + columnType: _isp.ColumnType.timestampWithoutTimeZone, + isNullable: false, + dartType: 'DateTime', + ), + ], + foreignKeys: [ + _isp.ForeignKeyDefinition( + constraintName: 'submission_revision_fk_0', + columns: ['submissionId'], + referenceTable: 'submission', + referenceTableSchema: 'public', + referenceColumns: ['id'], + onUpdate: _isp.ForeignKeyAction.noAction, + onDelete: _isp.ForeignKeyAction.cascade, + matchType: null, ), + ], + indexes: [ _isp.IndexDefinition( - indexName: 'stored_file_status_idx', + indexName: 'submission_revision_idx', tableSpace: null, elements: [ _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'status', + definition: 'submissionId', ), _isp.IndexElementDefinition( type: _isp.IndexElementDefinitionType.column, - definition: 'createdAt', + definition: 'sequence', ), ], type: 'btree', - isUnique: false, + isUnique: true, isPrimary: false, ), ], @@ -13866,6 +14947,9 @@ class Protocol extends _is.DatabaseSerializationManager if (t == _inb6x2l0.NotificationEmailFutureCallSendModel) { return _inb6x2l0.NotificationEmailFutureCallSendModel.fromJson(data) as T; } + if (t == _il37cz87.PublicationsFutureCallDeliverModel) { + return _il37cz87.PublicationsFutureCallDeliverModel.fromJson(data) as T; + } if (t == _io4auc29.StorageFutureCallRefreshItemSizeModel) { return _io4auc29.StorageFutureCallRefreshItemSizeModel.fromJson(data) as T; @@ -14332,6 +15416,78 @@ class Protocol extends _is.DatabaseSerializationManager if (t == _isz2sju0.PresenceUpdate) { return _isz2sju0.PresenceUpdate.fromJson(data) as T; } + if (t == _ikkxb56h.Publication) { + return _ikkxb56h.Publication.fromJson(data) as T; + } + if (t == _i5vk42yw.PublicationBlock) { + return _i5vk42yw.PublicationBlock.fromJson(data) as T; + } + if (t == _i9g6l3wu.PublicationCard) { + return _i9g6l3wu.PublicationCard.fromJson(data) as T; + } + if (t == _i0a1sw0a.PublicationCheckResult) { + return _i0a1sw0a.PublicationCheckResult.fromJson(data) as T; + } + if (t == _iqa48qn0.PublicationConsent) { + return _iqa48qn0.PublicationConsent.fromJson(data) as T; + } + if (t == _ihiygfti.PublicationDelivery) { + return _ihiygfti.PublicationDelivery.fromJson(data) as T; + } + if (t == _iz1gego0.PublicationDeliveryView) { + return _iz1gego0.PublicationDeliveryView.fromJson(data) as T; + } + if (t == _iucp51pg.PublicationFieldMode) { + return _iucp51pg.PublicationFieldMode.fromJson(data) as T; + } + if (t == _i63wbtw0.PublicationFields) { + return _i63wbtw0.PublicationFields.fromJson(data) as T; + } + if (t == _iv6bey6s.PublicationInput) { + return _iv6bey6s.PublicationInput.fromJson(data) as T; + } + if (t == _i1u9dlta.PublicationModerator) { + return _i1u9dlta.PublicationModerator.fromJson(data) as T; + } + if (t == _ij9tsbn9.PublicationModeratorView) { + return _ij9tsbn9.PublicationModeratorView.fromJson(data) as T; + } + if (t == _ivvukfve.PublicationOpenSubmission) { + return _ivvukfve.PublicationOpenSubmission.fromJson(data) as T; + } + if (t == _iyqlj2kr.PublicationSecret) { + return _iyqlj2kr.PublicationSecret.fromJson(data) as T; + } + if (t == _i5i48220.PublicationSettings) { + return _i5i48220.PublicationSettings.fromJson(data) as T; + } + if (t == _ipbg6o7y.Submission) { + return _ipbg6o7y.Submission.fromJson(data) as T; + } + if (t == _i49gtkgr.SubmissionAsset) { + return _i49gtkgr.SubmissionAsset.fromJson(data) as T; + } + if (t == _ip6l83ta.SubmissionDeliveryState) { + return _ip6l83ta.SubmissionDeliveryState.fromJson(data) as T; + } + if (t == _i71zy0hy.SubmissionRevision) { + return _i71zy0hy.SubmissionRevision.fromJson(data) as T; + } + if (t == _iegijpud.SubmissionRevisionView) { + return _iegijpud.SubmissionRevisionView.fromJson(data) as T; + } + if (t == _ijb8v3k4.SubmissionStarted) { + return _ijb8v3k4.SubmissionStarted.fromJson(data) as T; + } + if (t == _i7hbulg4.SubmissionStatus) { + return _i7hbulg4.SubmissionStatus.fromJson(data) as T; + } + if (t == _iq9uje8l.SubmissionValues) { + return _iq9uje8l.SubmissionValues.fromJson(data) as T; + } + if (t == _iakndug7.SubmissionView) { + return _iakndug7.SubmissionView.fromJson(data) as T; + } if (t == _ie6clghy.RevAck) { return _ie6clghy.RevAck.fromJson(data) as T; } @@ -15037,6 +16193,12 @@ class Protocol extends _is.DatabaseSerializationManager : null) as T; } + if (t == _is.getType<_il37cz87.PublicationsFutureCallDeliverModel?>()) { + return (data != null + ? _il37cz87.PublicationsFutureCallDeliverModel.fromJson(data) + : null) + as T; + } if (t == _is.getType<_io4auc29.StorageFutureCallRefreshItemSizeModel?>()) { return (data != null ? _io4auc29.StorageFutureCallRefreshItemSizeModel.fromJson(data) @@ -15639,6 +16801,120 @@ class Protocol extends _is.DatabaseSerializationManager return (data != null ? _isz2sju0.PresenceUpdate.fromJson(data) : null) as T; } + if (t == _is.getType<_ikkxb56h.Publication?>()) { + return (data != null ? _ikkxb56h.Publication.fromJson(data) : null) as T; + } + if (t == _is.getType<_i5vk42yw.PublicationBlock?>()) { + return (data != null ? _i5vk42yw.PublicationBlock.fromJson(data) : null) + as T; + } + if (t == _is.getType<_i9g6l3wu.PublicationCard?>()) { + return (data != null ? _i9g6l3wu.PublicationCard.fromJson(data) : null) + as T; + } + if (t == _is.getType<_i0a1sw0a.PublicationCheckResult?>()) { + return (data != null + ? _i0a1sw0a.PublicationCheckResult.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_iqa48qn0.PublicationConsent?>()) { + return (data != null ? _iqa48qn0.PublicationConsent.fromJson(data) : null) + as T; + } + if (t == _is.getType<_ihiygfti.PublicationDelivery?>()) { + return (data != null + ? _ihiygfti.PublicationDelivery.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_iz1gego0.PublicationDeliveryView?>()) { + return (data != null + ? _iz1gego0.PublicationDeliveryView.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_iucp51pg.PublicationFieldMode?>()) { + return (data != null + ? _iucp51pg.PublicationFieldMode.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_i63wbtw0.PublicationFields?>()) { + return (data != null ? _i63wbtw0.PublicationFields.fromJson(data) : null) + as T; + } + if (t == _is.getType<_iv6bey6s.PublicationInput?>()) { + return (data != null ? _iv6bey6s.PublicationInput.fromJson(data) : null) + as T; + } + if (t == _is.getType<_i1u9dlta.PublicationModerator?>()) { + return (data != null + ? _i1u9dlta.PublicationModerator.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_ij9tsbn9.PublicationModeratorView?>()) { + return (data != null + ? _ij9tsbn9.PublicationModeratorView.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_ivvukfve.PublicationOpenSubmission?>()) { + return (data != null + ? _ivvukfve.PublicationOpenSubmission.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_iyqlj2kr.PublicationSecret?>()) { + return (data != null ? _iyqlj2kr.PublicationSecret.fromJson(data) : null) + as T; + } + if (t == _is.getType<_i5i48220.PublicationSettings?>()) { + return (data != null + ? _i5i48220.PublicationSettings.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_ipbg6o7y.Submission?>()) { + return (data != null ? _ipbg6o7y.Submission.fromJson(data) : null) as T; + } + if (t == _is.getType<_i49gtkgr.SubmissionAsset?>()) { + return (data != null ? _i49gtkgr.SubmissionAsset.fromJson(data) : null) + as T; + } + if (t == _is.getType<_ip6l83ta.SubmissionDeliveryState?>()) { + return (data != null + ? _ip6l83ta.SubmissionDeliveryState.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_i71zy0hy.SubmissionRevision?>()) { + return (data != null ? _i71zy0hy.SubmissionRevision.fromJson(data) : null) + as T; + } + if (t == _is.getType<_iegijpud.SubmissionRevisionView?>()) { + return (data != null + ? _iegijpud.SubmissionRevisionView.fromJson(data) + : null) + as T; + } + if (t == _is.getType<_ijb8v3k4.SubmissionStarted?>()) { + return (data != null ? _ijb8v3k4.SubmissionStarted.fromJson(data) : null) + as T; + } + if (t == _is.getType<_i7hbulg4.SubmissionStatus?>()) { + return (data != null ? _i7hbulg4.SubmissionStatus.fromJson(data) : null) + as T; + } + if (t == _is.getType<_iq9uje8l.SubmissionValues?>()) { + return (data != null ? _iq9uje8l.SubmissionValues.fromJson(data) : null) + as T; + } + if (t == _is.getType<_iakndug7.SubmissionView?>()) { + return (data != null ? _iakndug7.SubmissionView.fromJson(data) : null) + as T; + } if (t == _is.getType<_ie6clghy.RevAck?>()) { return (data != null ? _ie6clghy.RevAck.fromJson(data) : null) as T; } @@ -16754,6 +18030,24 @@ class Protocol extends _is.DatabaseSerializationManager .toList() as T; } + if (t == List<_ivvukfve.PublicationOpenSubmission>) { + return (data as List) + .map((e) => deserialize<_ivvukfve.PublicationOpenSubmission>(e)) + .toList() + as T; + } + if (t == List<_ij9tsbn9.PublicationModeratorView>) { + return (data as List) + .map((e) => deserialize<_ij9tsbn9.PublicationModeratorView>(e)) + .toList() + as T; + } + if (t == List<_iegijpud.SubmissionRevisionView>) { + return (data as List) + .map((e) => deserialize<_iegijpud.SubmissionRevisionView>(e)) + .toList() + as T; + } if (t == List<_it4o2pk5.RevOpView>) { return (data as List) .map((e) => deserialize<_it4o2pk5.RevOpView>(e)) @@ -16968,9 +18262,21 @@ class Protocol extends _is.DatabaseSerializationManager .toList() as T; } + if (t == List<_i9ilkmgj.PublicationSettings>) { + return (data as List) + .map((e) => deserialize<_i9ilkmgj.PublicationSettings>(e)) + .toList() + as T; + } if (t == List) { return (data as List).map((e) => deserialize(e)).toList() as T; } + if (t == List<_idovycpn.PublicationDeliveryView>) { + return (data as List) + .map((e) => deserialize<_idovycpn.PublicationDeliveryView>(e)) + .toList() + as T; + } if (t == List<_ioyb7a1p.AccessTokenView>) { return (data as List) .map((e) => deserialize<_ioyb7a1p.AccessTokenView>(e)) @@ -17113,6 +18419,8 @@ class Protocol extends _is.DatabaseSerializationManager 'FilePreviewFutureCallGenerateModel', _inb6x2l0.NotificationEmailFutureCallSendModel => 'NotificationEmailFutureCallSendModel', + _il37cz87.PublicationsFutureCallDeliverModel => + 'PublicationsFutureCallDeliverModel', _io4auc29.StorageFutureCallRefreshItemSizeModel => 'StorageFutureCallRefreshItemSizeModel', _izr1y672.ActivityDashboard => 'ActivityDashboard', @@ -17269,6 +18577,30 @@ class Protocol extends _is.DatabaseSerializationManager _i8r9afjv.PresenceUpdated => 'PresenceUpdated', _ik055xb9.PresenceState => 'PresenceState', _isz2sju0.PresenceUpdate => 'PresenceUpdate', + _ikkxb56h.Publication => 'Publication', + _i5vk42yw.PublicationBlock => 'PublicationBlock', + _i9g6l3wu.PublicationCard => 'PublicationCard', + _i0a1sw0a.PublicationCheckResult => 'PublicationCheckResult', + _iqa48qn0.PublicationConsent => 'PublicationConsent', + _ihiygfti.PublicationDelivery => 'PublicationDelivery', + _iz1gego0.PublicationDeliveryView => 'PublicationDeliveryView', + _iucp51pg.PublicationFieldMode => 'PublicationFieldMode', + _i63wbtw0.PublicationFields => 'PublicationFields', + _iv6bey6s.PublicationInput => 'PublicationInput', + _i1u9dlta.PublicationModerator => 'PublicationModerator', + _ij9tsbn9.PublicationModeratorView => 'PublicationModeratorView', + _ivvukfve.PublicationOpenSubmission => 'PublicationOpenSubmission', + _iyqlj2kr.PublicationSecret => 'PublicationSecret', + _i5i48220.PublicationSettings => 'PublicationSettings', + _ipbg6o7y.Submission => 'Submission', + _i49gtkgr.SubmissionAsset => 'SubmissionAsset', + _ip6l83ta.SubmissionDeliveryState => 'SubmissionDeliveryState', + _i71zy0hy.SubmissionRevision => 'SubmissionRevision', + _iegijpud.SubmissionRevisionView => 'SubmissionRevisionView', + _ijb8v3k4.SubmissionStarted => 'SubmissionStarted', + _i7hbulg4.SubmissionStatus => 'SubmissionStatus', + _iq9uje8l.SubmissionValues => 'SubmissionValues', + _iakndug7.SubmissionView => 'SubmissionView', _ie6clghy.RevAck => 'RevAck', _i6ck957q.RevPing => 'RevPing', _i6ck957q.RevRequestOps => 'RevRequestOps', @@ -17518,6 +18850,8 @@ class Protocol extends _is.DatabaseSerializationManager return 'FilePreviewFutureCallGenerateModel'; case _inb6x2l0.NotificationEmailFutureCallSendModel(): return 'NotificationEmailFutureCallSendModel'; + case _il37cz87.PublicationsFutureCallDeliverModel(): + return 'PublicationsFutureCallDeliverModel'; case _io4auc29.StorageFutureCallRefreshItemSizeModel(): return 'StorageFutureCallRefreshItemSizeModel'; case _izr1y672.ActivityDashboard(): @@ -17828,6 +19162,54 @@ class Protocol extends _is.DatabaseSerializationManager return 'PresenceState'; case _isz2sju0.PresenceUpdate(): return 'PresenceUpdate'; + case _ikkxb56h.Publication(): + return 'Publication'; + case _i5vk42yw.PublicationBlock(): + return 'PublicationBlock'; + case _i9g6l3wu.PublicationCard(): + return 'PublicationCard'; + case _i0a1sw0a.PublicationCheckResult(): + return 'PublicationCheckResult'; + case _iqa48qn0.PublicationConsent(): + return 'PublicationConsent'; + case _ihiygfti.PublicationDelivery(): + return 'PublicationDelivery'; + case _iz1gego0.PublicationDeliveryView(): + return 'PublicationDeliveryView'; + case _iucp51pg.PublicationFieldMode(): + return 'PublicationFieldMode'; + case _i63wbtw0.PublicationFields(): + return 'PublicationFields'; + case _iv6bey6s.PublicationInput(): + return 'PublicationInput'; + case _i1u9dlta.PublicationModerator(): + return 'PublicationModerator'; + case _ij9tsbn9.PublicationModeratorView(): + return 'PublicationModeratorView'; + case _ivvukfve.PublicationOpenSubmission(): + return 'PublicationOpenSubmission'; + case _iyqlj2kr.PublicationSecret(): + return 'PublicationSecret'; + case _i5i48220.PublicationSettings(): + return 'PublicationSettings'; + case _ipbg6o7y.Submission(): + return 'Submission'; + case _i49gtkgr.SubmissionAsset(): + return 'SubmissionAsset'; + case _ip6l83ta.SubmissionDeliveryState(): + return 'SubmissionDeliveryState'; + case _i71zy0hy.SubmissionRevision(): + return 'SubmissionRevision'; + case _iegijpud.SubmissionRevisionView(): + return 'SubmissionRevisionView'; + case _ijb8v3k4.SubmissionStarted(): + return 'SubmissionStarted'; + case _i7hbulg4.SubmissionStatus(): + return 'SubmissionStatus'; + case _iq9uje8l.SubmissionValues(): + return 'SubmissionValues'; + case _iakndug7.SubmissionView(): + return 'SubmissionView'; case _ie6clghy.RevAck(): return 'RevAck'; case _i6ck957q.RevPing(): @@ -18326,6 +19708,11 @@ class Protocol extends _is.DatabaseSerializationManager data['data'], ); } + if (dataClassName == 'PublicationsFutureCallDeliverModel') { + return deserialize<_il37cz87.PublicationsFutureCallDeliverModel>( + data['data'], + ); + } if (dataClassName == 'StorageFutureCallRefreshItemSizeModel') { return deserialize<_io4auc29.StorageFutureCallRefreshItemSizeModel>( data['data'], @@ -18793,6 +20180,78 @@ class Protocol extends _is.DatabaseSerializationManager if (dataClassName == 'PresenceUpdate') { return deserialize<_isz2sju0.PresenceUpdate>(data['data']); } + if (dataClassName == 'Publication') { + return deserialize<_ikkxb56h.Publication>(data['data']); + } + if (dataClassName == 'PublicationBlock') { + return deserialize<_i5vk42yw.PublicationBlock>(data['data']); + } + if (dataClassName == 'PublicationCard') { + return deserialize<_i9g6l3wu.PublicationCard>(data['data']); + } + if (dataClassName == 'PublicationCheckResult') { + return deserialize<_i0a1sw0a.PublicationCheckResult>(data['data']); + } + if (dataClassName == 'PublicationConsent') { + return deserialize<_iqa48qn0.PublicationConsent>(data['data']); + } + if (dataClassName == 'PublicationDelivery') { + return deserialize<_ihiygfti.PublicationDelivery>(data['data']); + } + if (dataClassName == 'PublicationDeliveryView') { + return deserialize<_iz1gego0.PublicationDeliveryView>(data['data']); + } + if (dataClassName == 'PublicationFieldMode') { + return deserialize<_iucp51pg.PublicationFieldMode>(data['data']); + } + if (dataClassName == 'PublicationFields') { + return deserialize<_i63wbtw0.PublicationFields>(data['data']); + } + if (dataClassName == 'PublicationInput') { + return deserialize<_iv6bey6s.PublicationInput>(data['data']); + } + if (dataClassName == 'PublicationModerator') { + return deserialize<_i1u9dlta.PublicationModerator>(data['data']); + } + if (dataClassName == 'PublicationModeratorView') { + return deserialize<_ij9tsbn9.PublicationModeratorView>(data['data']); + } + if (dataClassName == 'PublicationOpenSubmission') { + return deserialize<_ivvukfve.PublicationOpenSubmission>(data['data']); + } + if (dataClassName == 'PublicationSecret') { + return deserialize<_iyqlj2kr.PublicationSecret>(data['data']); + } + if (dataClassName == 'PublicationSettings') { + return deserialize<_i5i48220.PublicationSettings>(data['data']); + } + if (dataClassName == 'Submission') { + return deserialize<_ipbg6o7y.Submission>(data['data']); + } + if (dataClassName == 'SubmissionAsset') { + return deserialize<_i49gtkgr.SubmissionAsset>(data['data']); + } + if (dataClassName == 'SubmissionDeliveryState') { + return deserialize<_ip6l83ta.SubmissionDeliveryState>(data['data']); + } + if (dataClassName == 'SubmissionRevision') { + return deserialize<_i71zy0hy.SubmissionRevision>(data['data']); + } + if (dataClassName == 'SubmissionRevisionView') { + return deserialize<_iegijpud.SubmissionRevisionView>(data['data']); + } + if (dataClassName == 'SubmissionStarted') { + return deserialize<_ijb8v3k4.SubmissionStarted>(data['data']); + } + if (dataClassName == 'SubmissionStatus') { + return deserialize<_i7hbulg4.SubmissionStatus>(data['data']); + } + if (dataClassName == 'SubmissionValues') { + return deserialize<_iq9uje8l.SubmissionValues>(data['data']); + } + if (dataClassName == 'SubmissionView') { + return deserialize<_iakndug7.SubmissionView>(data['data']); + } if (dataClassName == 'RevAck') { return deserialize<_ie6clghy.RevAck>(data['data']); } @@ -19545,6 +21004,22 @@ class Protocol extends _is.DatabaseSerializationManager return _im8eh74x.StoredFile.t; case _ik59hiyp.UserNotification: return _ik59hiyp.UserNotification.t; + case _ikkxb56h.Publication: + return _ikkxb56h.Publication.t; + case _i5vk42yw.PublicationBlock: + return _i5vk42yw.PublicationBlock.t; + case _iqa48qn0.PublicationConsent: + return _iqa48qn0.PublicationConsent.t; + case _ihiygfti.PublicationDelivery: + return _ihiygfti.PublicationDelivery.t; + case _i1u9dlta.PublicationModerator: + return _i1u9dlta.PublicationModerator.t; + case _ipbg6o7y.Submission: + return _ipbg6o7y.Submission.t; + case _i49gtkgr.SubmissionAsset: + return _i49gtkgr.SubmissionAsset.t; + case _i71zy0hy.SubmissionRevision: + return _i71zy0hy.SubmissionRevision.t; case _ip7h3lg0.RevFile: return _ip7h3lg0.RevFile.t; case _ivfqwl6l.RevHookState: diff --git a/wonky_server/lib/src/generated/protocol.yaml b/wonky_server/lib/src/generated/protocol.yaml index c9f5ebff..5b1e53be 100644 --- a/wonky_server/lib/src/generated/protocol.yaml +++ b/wonky_server/lib/src/generated/protocol.yaml @@ -162,6 +162,26 @@ notification: - watch: presence: - join: +publication: + - resolve: + - startSubmission: + - list: + - create: + - update: + - delete: + - verify: + - rotateSecret: + - createApiKey: + - setModerators: + - deliveries: + - resend: + - sendTest: +submission: + - get: + - submit: + - withdraw: + - disconnect: + - reconnect: sharing: - getSharing: - share: diff --git a/wonky_server/lib/src/platform/activity/activity_type.spy.yaml b/wonky_server/lib/src/platform/activity/activity_type.spy.yaml index 53063929..5ac7b94b 100644 --- a/wonky_server/lib/src/platform/activity/activity_type.spy.yaml +++ b/wonky_server/lib/src/platform/activity/activity_type.spy.yaml @@ -14,3 +14,7 @@ values: - exported ### (v2) A file was uploaded (Drive 02 §3.3). - uploaded + ### (M14) Submitted to, withdrawn from or disconnected from a publication, + ### or the publication changed the status (specs/18 §6; summary + ### {publication, action, status?}). + - submission diff --git a/wonky_server/lib/src/platform/board/ai/spec_index.g.dart b/wonky_server/lib/src/platform/board/ai/spec_index.g.dart index a46f4a5d..5e708acb 100644 --- a/wonky_server/lib/src/platform/board/ai/spec_index.g.dart +++ b/wonky_server/lib/src/platform/board/ai/spec_index.g.dart @@ -29,10 +29,11 @@ const specIndexReadme = '| 11 | Quality (specs/11-quality-testing-accessibility.md) | Testing, performance budgets, accessibility, i18n, observability |\n' '| 12 | Offline & sync (specs/12-offline-and-sync.md) | Local stores, Write offline, Sheets/Slides on RevLog (summary), upload queue, scale limits |\n' '| 13 | Security & operations (specs/13-security-and-operations.md) | Threat model, privacy, deployment, scheduled jobs, arbitrary uploads |\n' - '| 14 | Roadmap (specs/14-roadmap.md) | Milestones M0–M13 (v2: M8 Drive + suite changes, M9–M11 Slides; M12 Bugs & improvements; M13 RevLog), how parallel agents execute the work packages, shared workstreams, risks |\n' + '| 14 | Roadmap (specs/14-roadmap.md) | Milestones M0–M14 (v2: M8 Drive + suite changes, M9–M11 Slides; M12 Bugs & improvements; M13 RevLog; M14 Publications), how parallel agents execute the work packages, shared workstreams, risks |\n' '| 15 | Writing tests (specs/15-writing-tests.md) | How to write tests: layout, naming, helpers, server/widget/golden/property/E2E patterns, determinism, running |\n' '| 16 | Bugs & improvements (specs/16-bugs-and-improvements.md) | Public board for bug reports and improvement ideas: report dialog with annotated screenshots, votes, comments, AI triage and moderation, admins, tasks with contributor prompts, claims, GitHub PR rules (M12, built) |\n' '| 17 | RevLog sync (specs/17-revlog-sync.md) | Server-sequenced op log of Sheets and Slides: decisions, data model, change sets and apply rules, protocol, server (sequencer, hooks, pages, headless cache), client (cache, outbox, bootstrap, conflicts), performance gates, as-built notes (M13) |\n' + '| 18 | Publications & submissions (specs/18-publications-and-submissions.md) | Blogs register a publication; contributors write in Wonky Write and *Submit* to the blog\'s review queue (signed webhooks, publication API, moderators with comment access, feedback in the document) (M14, built) |\n' '## Conventions used in all specs'; /// Headings of the suite specs (`specs/*.md`). @@ -231,6 +232,7 @@ const specIndexSuite = ' ### 2.1 Second iteration (v2)\n' ' ### 2.1a Bugs & improvements (M12, built)\n' ' ### 2.1b RevLog sync (M13, built)\n' + ' ### 2.1c Publications & submissions (M14, built)\n' ' ### 2.2 Executing the plan with parallel agents (v2)\n' ' ## 3. Workstreams (suite-level, shared)\n' ' ## 4. Dependency graph (simplified)\n' @@ -361,6 +363,39 @@ const specIndexSuite = ' ### 9. Sync status\n' ' ### 10. Commit hints\n' ' ## Part 7 · Performance gates\n' + 'specs/18-publications-and-submissions.md\n' + ' # 18 · Publications and submissions (M14, built)\n' + ' ## 1. Decisions\n' + ' ## 2. Concepts\n' + ' ### 2.1 Submission status\n' + ' ## 3. Contributor flow\n' + ' ## 4. Write UI\n' + ' ### 4.1 Title row\n' + ' ### 4.2 Submit dialog\n' + ' ### 4.3 Status popover\n' + ' ### 4.4 Menus and commands\n' + ' ### 4.5 Copies, trash and history\n' + ' ## 5. Moderators and feedback\n' + ' ### 5.1 Moderator access\n' + ' ### 5.2 Feedback thread\n' + ' ### 5.3 Notifications\n' + ' ## 6. Data model (server, `platform/publications/`)\n' + ' ## 7. Protocol\n' + ' ### 7.1 Webhooks (Wonky → blog)\n' + ' ### 7.2 Delivery\n' + ' ### 7.3 Publication API (blog → Wonky)\n' + ' ## 8. Publication setup (blog owner)\n' + ' ### 8.1 Settings › Publications\n' + ' ### 8.2 Verification\n' + ' ### 8.3 Blog-side checklist (also in the developer guide, §12 PUB-7)\n' + ' ## 9. Endpoints and MCP\n' + ' ### 9.1 `PublicationEndpoint` (`publication`, signed in)\n' + ' ### 9.2 `SubmissionEndpoint` (`submission`)\n' + ' ### 9.3 MCP and AI\n' + ' ## 10. Limits and abuse\n' + ' ## 11. Security and privacy summary\n' + ' ## 12. Work packages\n' + ' ## 13. As built (M14)\n' 'specs/v2-review.md\n' ' # Wonky Work v2 — review decisions\n' ' ## Summary\n' diff --git a/wonky_server/lib/src/platform/comments/comment.spy.yaml b/wonky_server/lib/src/platform/comments/comment.spy.yaml index 1c93279c..83227a61 100644 --- a/wonky_server/lib/src/platform/comments/comment.spy.yaml +++ b/wonky_server/lib/src/platform/comments/comment.spy.yaml @@ -18,6 +18,8 @@ fields: ### Soft delete: shown as "Comment deleted". deletedAt: DateTime? systemEvent: CommentSystemEvent? + ### (M14) A publication's message (authorKind system), specs/18 §5.2. + publicationId: int?, relation(parent=publication, onDelete=SetNull) indexes: comment_thread_idx: fields: threadId, createdAt diff --git a/wonky_server/lib/src/platform/comments/comment_service.dart b/wonky_server/lib/src/platform/comments/comment_service.dart index 144f1e12..b52c0f4b 100644 --- a/wonky_server/lib/src/platform/comments/comment_service.dart +++ b/wonky_server/lib/src/platform/comments/comment_service.dart @@ -6,10 +6,12 @@ import 'package:wonky_core/wonky_core.dart' show Role; import '../activity/activity_service.dart'; import '../common/actor.dart'; import '../common/errors.dart'; +import '../common/guarded.dart'; import '../common/json.dart'; import '../common/models.dart'; import '../common/time.dart'; import '../notifications/notification_service.dart'; +import '../publications/submission_service.dart'; import '../sharing/access_service.dart'; import '../users/user_service.dart'; import '../cluster/cluster_bus.dart'; @@ -128,6 +130,20 @@ abstract final class CommentService { for (final t in threads) ...[t.createdById, t.resolvedById, t.assigneeId], for (final c in comments) ...[c.authorId, ...c.mentions], ]); + // (M14) A publication's messages show its name (specs/18 §5.2). + final publicationIds = { + for (final c in comments) + if (c.publicationId != null) c.publicationId!, + }; + final publications = publicationIds.isEmpty + ? const {} + : { + for (final p in await Publication.db.find( + session, + where: (t) => t.id.inSet(publicationIds), + )) + p.id!: p.name, + }; return [ for (final t in threads) CommentThreadView( @@ -163,6 +179,9 @@ abstract final class CommentService { editedAt: c.editedAt, deleted: c.deletedAt != null, systemEvent: c.systemEvent, + authorLabel: c.publicationId == null + ? null + : publications[c.publicationId] ?? 'Publication', ), ], ), @@ -391,6 +410,18 @@ abstract final class CommentService { ActivityType.commented, summary: {'thread': threadUuid.uuid, 'reply': true}, ); + // Replies to a publication's messages go to the blog (specs/18 §5.2). + await runGuarded( + session, + 'publications.onReply', + () => SubmissionService.onReply( + session, + thread, + actor, + body: clean, + commentUuid: commentUuid, + ), + ); final participants = { thread.createdById, ?thread.assigneeId, diff --git a/wonky_server/lib/src/platform/comments/comment_view.spy.yaml b/wonky_server/lib/src/platform/comments/comment_view.spy.yaml index b20969fc..9a885f1a 100644 --- a/wonky_server/lib/src/platform/comments/comment_view.spy.yaml +++ b/wonky_server/lib/src/platform/comments/comment_view.spy.yaml @@ -14,3 +14,6 @@ fields: editedAt: DateTime? deleted: bool systemEvent: CommentSystemEvent? + ### (M14) Name shown instead of a user: the publication of a message + ### (specs/18 §5.2). + authorLabel: String? diff --git a/wonky_server/lib/src/platform/drive/drive_trash.dart b/wonky_server/lib/src/platform/drive/drive_trash.dart index 4c634b3c..33d87b6c 100644 --- a/wonky_server/lib/src/platform/drive/drive_trash.dart +++ b/wonky_server/lib/src/platform/drive/drive_trash.dart @@ -10,9 +10,11 @@ import '../../write/ot/document_cache.dart'; import '../activity/activity_service.dart'; import '../common/actor.dart'; import '../common/errors.dart'; +import '../common/guarded.dart'; import '../common/models.dart'; import '../common/time.dart'; import '../files/file_service.dart'; +import '../publications/submission_service.dart'; import '../sharing/access_service.dart'; import '../sharing/acl_events.dart'; import '../storage/storage_service.dart'; @@ -63,6 +65,12 @@ abstract final class DriveTrash { await ActivityService.log(session, item.id!, actor, ActivityType.trashed); final updated = (await DriveItem.db.findById(session, item.id!))!; await AclEvents.changed(session, updated, kind: DriveChangeKind.trashed); + // Open submissions are withdrawn (specs/18 §4.5). + await runGuarded( + session, + 'publications.onTrashed', + () => SubmissionService.onTrashed(session, nodes), + ); } } @@ -128,6 +136,14 @@ abstract final class DriveTrash { ActivityType.restored, ); await AclEvents.changed(session, updated, kind: DriveChangeKind.restored); + await runGuarded( + session, + 'publications.onRestored', + () => SubmissionService.onRestored(session, [ + for (final n in nodes) + if (ids.contains(n.id)) n, + ]), + ); } } diff --git a/wonky_server/lib/src/platform/notifications/email/notification_emails.dart b/wonky_server/lib/src/platform/notifications/email/notification_emails.dart index 92425fee..d6ee65d3 100644 --- a/wonky_server/lib/src/platform/notifications/email/notification_emails.dart +++ b/wonky_server/lib/src/platform/notifications/email/notification_emails.dart @@ -102,6 +102,9 @@ class NotificationEmails { p['line'] is String ? '${p['line']}' : 'Update on “${p['title'] ?? 'Bugs & improvements'}”', + NotificationKind.submission => + '${p['publication'] ?? 'A publication'} · $what: ' + '${p['excerpt'] ?? 'your story was updated'}', }; } diff --git a/wonky_server/lib/src/platform/notifications/notification_kind.spy.yaml b/wonky_server/lib/src/platform/notifications/notification_kind.spy.yaml index 14ef2a2c..182cebc9 100644 --- a/wonky_server/lib/src/platform/notifications/notification_kind.spy.yaml +++ b/wonky_server/lib/src/platform/notifications/notification_kind.spy.yaml @@ -20,3 +20,6 @@ values: - boardStatus ### My claim: warning, expiry, released, PR closed. - boardClaim + ### (M14) A publication changed the status of a story I can edit or sent + ### a message; a submission could not be delivered (specs/18 §5.3). + - submission diff --git a/wonky_server/lib/src/platform/notifications/notification_service.dart b/wonky_server/lib/src/platform/notifications/notification_service.dart index 7f2471b7..a12a9001 100644 --- a/wonky_server/lib/src/platform/notifications/notification_service.dart +++ b/wonky_server/lib/src/platform/notifications/notification_service.dart @@ -55,6 +55,8 @@ abstract final class NotificationService { static const immediateKinds = { NotificationKind.mention, NotificationKind.assigned, + // (M14) Rare and waited for (specs/18 §5.3). + NotificationKind.submission, }; static String channel(int userId) => 'notifications:$userId'; @@ -74,8 +76,12 @@ abstract final class NotificationService { NotificationKind.boardReply => 'board', NotificationKind.boardStatus => 'board', NotificationKind.boardClaim => 'board', + NotificationKind.submission => 'submissions', }; + /// Categories whose default is in-app + email instead of in-app only. + static const _emailByDefault = {'submissions'}; + /// Older settings stored access requests under `shares`. static const _fallbackKeys = {'accessRequests': 'shares'}; @@ -86,7 +92,10 @@ abstract final class NotificationService { NotificationKind kind, ) { final key = settingKey(kind); - final value = settings[key] ?? settings[_fallbackKeys[key]]; + final value = + settings[key] ?? + settings[_fallbackKeys[key]] ?? + (_emailByDefault.contains(key) ? 'email' : null); return value == 'email' || value == 'off' ? value as String : 'inApp'; } diff --git a/wonky_server/lib/src/platform/publications/models/publication.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication.spy.yaml new file mode 100644 index 00000000..f21275ac --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication.spy.yaml @@ -0,0 +1,43 @@ +### A destination that takes stories from Wonky Write (specs/18 §2, §6), +### owned by one user (the blog owner). Holds the signing secret, so it +### never leaves the server; clients see [PublicationSettings] and +### [PublicationCard]. +class: Publication +table: publication +serverOnly: true +fields: + ### "pub_" + 22 url-safe characters; in contributor links, not a secret. + publicId: String + ownerId: int, relation(parent=user_profile, onDelete=Cascade) + name: String + ### https origin of the blog (`https://blog.example.com`). + siteUrl: String + ### https URL the webhooks go to. + webhookUrl: String + ### The site host proven by `/.well-known/wonky-publications.json` + ### (specs/18 §8.2); null = unverified. + verifiedHost: String? + verifiedAt: DateTime? + ### The owner's Write document new stories start from. + templateItemId: int?, relation(parent=drive_item, onDelete=SetNull) + termsUrl: String? + fields: PublicationFields + ### "whsec_" + base64 key; must be kept in plain to sign (specs/13 §2). + signingSecret: String + ### The previous secret signs too until [previousSecretUntil] (rotation). + previousSigningSecret: String? + previousSecretUntil: DateTime? + ### SHA-256 (hex) of the API key "wpk_…", shown once. + apiKeyHash: String? + apiKeyLast4: String? + enabled: bool, default=true + createdAt: DateTime + updatedAt: DateTime +indexes: + publication_public_idx: + fields: publicId + unique: true + publication_owner_idx: + fields: ownerId + publication_api_key_idx: + fields: apiKeyHash diff --git a/wonky_server/lib/src/platform/publications/models/publication_block.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_block.spy.yaml new file mode 100644 index 00000000..2f30a8dd --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_block.spy.yaml @@ -0,0 +1,12 @@ +### A user the publication doesn't take stories from (specs/18 §7.3). +class: PublicationBlock +table: publication_block +serverOnly: true +fields: + publicationId: int, relation(parent=publication, onDelete=Cascade) + userId: int, relation(parent=user_profile, onDelete=Cascade) + at: DateTime +indexes: + publication_block_idx: + fields: publicationId, userId + unique: true diff --git a/wonky_server/lib/src/platform/publications/models/publication_card.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_card.spy.yaml new file mode 100644 index 00000000..c09b1051 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_card.spy.yaml @@ -0,0 +1,20 @@ +### What a contributor sees of a publication (specs/18 §3, §9.1). +class: PublicationCard +fields: + publicId: String + name: String + ### The verified site host, or the webhook host when unverified. + shownHost: String + verified: bool + siteHost: String + webhookHost: String + termsUrl: String? + fields: PublicationFields + ownerName: String + enabled: bool + ### The caller must agree first (never asked or what was agreed changed). + consentNeeded: bool + ### The publication doesn't take stories from the caller. + blocked: bool + ### The caller's drafts and stories with changes requested. + openSubmissions: List diff --git a/wonky_server/lib/src/platform/publications/models/publication_check_result.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_check_result.spy.yaml new file mode 100644 index 00000000..e3a263bc --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_check_result.spy.yaml @@ -0,0 +1,7 @@ +### Result of *Verify* or *Send test* (specs/18 §8.1, §8.2). +class: PublicationCheckResult +fields: + ok: bool + ### What went wrong, for the owner. + message: String? + settings: PublicationSettings diff --git a/wonky_server/lib/src/platform/publications/models/publication_consent.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_consent.spy.yaml new file mode 100644 index 00000000..5a803f95 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_consent.spy.yaml @@ -0,0 +1,15 @@ +### A user's consent to write for a publication (specs/18 §3). Asked again +### when the site host, webhook host or terms URL change ([consentKey]). +class: PublicationConsent +table: publication_consent +serverOnly: true +fields: + publicationId: int, relation(parent=publication, onDelete=Cascade) + userId: int, relation(parent=user_profile, onDelete=Cascade) + ### Hash of what was agreed to (shown host, webhook host, terms URL). + consentKey: String + at: DateTime +indexes: + publication_consent_idx: + fields: publicationId, userId + unique: true diff --git a/wonky_server/lib/src/platform/publications/models/publication_delivery.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_delivery.spy.yaml new file mode 100644 index 00000000..0b8f8938 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_delivery.spy.yaml @@ -0,0 +1,34 @@ +### A webhook in the outbox (specs/18 §7.2): retried with the same id until +### the blog answers 2xx or the retries run out. +class: PublicationDelivery +table: publication_delivery +serverOnly: true +fields: + publicationId: int, relation(parent=publication, onDelete=Cascade) + submissionId: int?, relation(parent=submission, onDelete=SetNull) + ### "msg_", the `webhook-id` header; stable across retries. + webhookId: String + type: String + ### The submit's sequence of a `submission.submitted`. + sequence: int? + ### The JSON body. + payload: String + attempts: int, default=0 + ### Null once delivered or given up. + nextAttemptAt: DateTime? + ### Lease of the instance sending it (specs/13 §4). + leaseUntil: DateTime? + ### HTTP status of the last attempt; 0 = network error or timeout. + lastStatus: int? + lastError: String? + deliveredAt: DateTime? + failedAt: DateTime? + createdAt: DateTime +indexes: + publication_delivery_webhook_idx: + fields: webhookId + unique: true + publication_delivery_due_idx: + fields: nextAttemptAt + publication_delivery_publication_idx: + fields: publicationId, createdAt diff --git a/wonky_server/lib/src/platform/publications/models/publication_delivery_view.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_delivery_view.spy.yaml new file mode 100644 index 00000000..67e48996 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_delivery_view.spy.yaml @@ -0,0 +1,12 @@ +### A webhook delivery in the owner's *Deliveries* list (specs/18 §8.1). +class: PublicationDeliveryView +fields: + webhookId: String + type: String + createdAt: DateTime + attempts: int + lastStatus: int? + lastError: String? + deliveredAt: DateTime? + failedAt: DateTime? + nextAttemptAt: DateTime? diff --git a/wonky_server/lib/src/platform/publications/models/publication_field_mode.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_field_mode.spy.yaml new file mode 100644 index 00000000..c954f347 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_field_mode.spy.yaml @@ -0,0 +1,7 @@ +### Whether a submission field is shown and required (specs/18 §8.1). +enum: PublicationFieldMode +serialized: byName +values: + - off + - optional + - required diff --git a/wonky_server/lib/src/platform/publications/models/publication_fields.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_fields.spy.yaml new file mode 100644 index 00000000..7b7a61bb --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_fields.spy.yaml @@ -0,0 +1,11 @@ +### Which submission fields a publication asks for (specs/18 §8.1). The +### title is always asked for and required. +class: PublicationFields +fields: + summary: PublicationFieldMode + tags: PublicationFieldMode + ### When not empty, tags must come from this list. + allowedTags: List + coverImage: PublicationFieldMode + authorBio: PublicationFieldMode + note: PublicationFieldMode diff --git a/wonky_server/lib/src/platform/publications/models/publication_input.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_input.spy.yaml new file mode 100644 index 00000000..26248a86 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_input.spy.yaml @@ -0,0 +1,10 @@ +### Create or update a publication (specs/18 §8.1). +class: PublicationInput +fields: + name: String + siteUrl: String + webhookUrl: String + templateItemUuid: UuidValue? + termsUrl: String? + fields: PublicationFields + enabled: bool diff --git a/wonky_server/lib/src/platform/publications/models/publication_moderator.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_moderator.spy.yaml new file mode 100644 index 00000000..72753a9d --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_moderator.spy.yaml @@ -0,0 +1,17 @@ +### A moderator of a publication (specs/18 §5.1): gets Commenter on the +### publication's open submissions. Pending ([userId] null) until the +### email signs up. +class: PublicationModerator +table: publication_moderator +serverOnly: true +fields: + publicationId: int, relation(parent=publication, onDelete=Cascade) + userId: int?, relation(parent=user_profile, onDelete=Cascade) + ### Lower-case email; kept after sign-up for display. + email: String +indexes: + publication_moderator_idx: + fields: publicationId, email + unique: true + publication_moderator_user_idx: + fields: userId diff --git a/wonky_server/lib/src/platform/publications/models/publication_moderator_view.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_moderator_view.spy.yaml new file mode 100644 index 00000000..7e0707be --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_moderator_view.spy.yaml @@ -0,0 +1,5 @@ +class: PublicationModeratorView +fields: + email: String + ### Null while no account has this email. + name: String? diff --git a/wonky_server/lib/src/platform/publications/models/publication_open_submission.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_open_submission.spy.yaml new file mode 100644 index 00000000..b900aab1 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_open_submission.spy.yaml @@ -0,0 +1,7 @@ +### A story the caller can continue (specs/18 §3). +class: PublicationOpenSubmission +fields: + itemUuid: UuidValue + name: String + status: SubmissionStatus + updatedAt: DateTime diff --git a/wonky_server/lib/src/platform/publications/models/publication_secret.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_secret.spy.yaml new file mode 100644 index 00000000..435d2399 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_secret.spy.yaml @@ -0,0 +1,6 @@ +### A secret shown once (specs/18 §8.1): the signing secret at creation or +### rotation, or an API key. +class: PublicationSecret +fields: + settings: PublicationSettings + secret: String diff --git a/wonky_server/lib/src/platform/publications/models/publication_settings.spy.yaml b/wonky_server/lib/src/platform/publications/models/publication_settings.spy.yaml new file mode 100644 index 00000000..21ba2c0b --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/publication_settings.spy.yaml @@ -0,0 +1,24 @@ +### The owner's view of a publication (specs/18 §8.1). Never holds secrets. +class: PublicationSettings +fields: + publicId: String + name: String + siteUrl: String + webhookUrl: String + verifiedHost: String? + verifiedAt: DateTime? + templateItemUuid: UuidValue? + templateName: String? + termsUrl: String? + fields: PublicationFields + moderators: List + hasApiKey: bool + apiKeyLast4: String? + ### Set while the previous signing secret still signs. + previousSecretUntil: DateTime? + enabled: bool + ### `https:///write/new?publication=`. + contributorLink: String + ### Submissions in review or with changes requested. + openSubmissionCount: int + createdAt: DateTime diff --git a/wonky_server/lib/src/platform/publications/models/submission.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission.spy.yaml new file mode 100644 index 00000000..394163a6 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission.spy.yaml @@ -0,0 +1,35 @@ +### The link between a Write document and a publication (specs/18 §2, §6). +### A document has at most one. +class: Submission +table: submission +serverOnly: true +fields: + ### Public as "sub_". + uuid: UuidValue, defaultModel=random_v7 + publicationId: int, relation(parent=publication, onDelete=Cascade) + itemId: int, relation(parent=drive_item, onDelete=Cascade) + ### The blog's own reference from the contributor link. + ref: String? + status: SubmissionStatus + ### The status before the last submit, restored when its delivery fails + ### (specs/18 §7.2). + statusBeforeSubmit: SubmissionStatus? + ### Null = the last delivery was accepted. + delivery: SubmissionDeliveryState? + values: SubmissionValues + publicUrl: String? + ### The document-level comment thread of the publication's messages. + feedbackThreadId: int? + createdById: int + createdAt: DateTime + updatedAt: DateTime + disconnectedAt: DateTime? +indexes: + submission_uuid_idx: + fields: uuid + unique: true + submission_item_idx: + fields: itemId + unique: true + submission_publication_idx: + fields: publicationId, status diff --git a/wonky_server/lib/src/platform/publications/models/submission_asset.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_asset.spy.yaml new file mode 100644 index 00000000..e1965a2c --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_asset.spy.yaml @@ -0,0 +1,14 @@ +### An image a submit referenced (specs/18 §5, §7.3): the publication's API +### key may download it while the file exists. +class: SubmissionAsset +table: submission_asset +serverOnly: true +fields: + submissionId: int, relation(parent=submission, onDelete=Cascade) + fileUuid: UuidValue +indexes: + submission_asset_idx: + fields: submissionId, fileUuid + unique: true + submission_asset_file_idx: + fields: fileUuid diff --git a/wonky_server/lib/src/platform/publications/models/submission_delivery_state.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_delivery_state.spy.yaml new file mode 100644 index 00000000..0137b4bb --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_delivery_state.spy.yaml @@ -0,0 +1,8 @@ +### State of the last submit's webhook delivery (specs/18 §7.2). +enum: SubmissionDeliveryState +serialized: byName +values: + ### Not accepted yet; the outbox retries. + - pending + ### Every retry failed. + - failed diff --git a/wonky_server/lib/src/platform/publications/models/submission_revision.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_revision.spy.yaml new file mode 100644 index 00000000..566150d7 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_revision.spy.yaml @@ -0,0 +1,22 @@ +### One submit of a submission (specs/18 §2, §6). +class: SubmissionRevision +table: submission_revision +serverOnly: true +fields: + submissionId: int, relation(parent=submission, onDelete=Cascade) + ### 1, 2, … per submission. + sequence: int + ### The Write document revision that was sent. + revision: int + ### The named version of this submit (specs/18 P8). + versionId: int? + values: SubmissionValues + ### The `submission.submitted` body sent for this submit (JSON), served + ### again by `GET submissions/{id}/content` (specs/18 §7.3). + payload: String + submittedById: int + submittedAt: DateTime +indexes: + submission_revision_idx: + fields: submissionId, sequence + unique: true diff --git a/wonky_server/lib/src/platform/publications/models/submission_revision_view.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_revision_view.spy.yaml new file mode 100644 index 00000000..724fc116 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_revision_view.spy.yaml @@ -0,0 +1,8 @@ +class: SubmissionRevisionView +fields: + sequence: int + revision: int + submittedByName: String + submittedAt: DateTime + ### The named version of this submit, when it still exists. + versionId: int? diff --git a/wonky_server/lib/src/platform/publications/models/submission_started.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_started.spy.yaml new file mode 100644 index 00000000..c407dd44 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_started.spy.yaml @@ -0,0 +1,4 @@ +### Result of starting a story (specs/18 §3 step 3). +class: SubmissionStarted +fields: + itemUuid: UuidValue diff --git a/wonky_server/lib/src/platform/publications/models/submission_status.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_status.spy.yaml new file mode 100644 index 00000000..da4e0d50 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_status.spy.yaml @@ -0,0 +1,12 @@ +### Lifecycle of a submission (specs/18 §2.1). +enum: SubmissionStatus +serialized: byName +values: + ### Started from the link, never submitted. + - draft + - inReview + - changesRequested + ### Final for this submission. + - declined + - published + - withdrawn diff --git a/wonky_server/lib/src/platform/publications/models/submission_values.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_values.spy.yaml new file mode 100644 index 00000000..87036a37 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_values.spy.yaml @@ -0,0 +1,10 @@ +### The fields a contributor filled in (specs/18 §4.2). +class: SubmissionValues +fields: + title: String + summary: String? + tags: List + ### A `wonky-file` uuid of an image in the document. + coverImage: UuidValue? + authorBio: String? + note: String? diff --git a/wonky_server/lib/src/platform/publications/models/submission_view.spy.yaml b/wonky_server/lib/src/platform/publications/models/submission_view.spy.yaml new file mode 100644 index 00000000..1aec31a8 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/models/submission_view.spy.yaml @@ -0,0 +1,28 @@ +### A document's submission as editors and moderators see it (specs/18 §4). +class: SubmissionView +fields: + ### "sub_". + id: String + itemUuid: UuidValue + status: SubmissionStatus + delivery: SubmissionDeliveryState? + publicationId: String + publicationName: String + shownHost: String + verified: bool + ### The publication still takes submissions (enabled, caller not blocked). + accepting: bool + fields: PublicationFields + termsUrl: String? + ### The caller still has to agree to the terms before submitting. + consentNeeded: bool + values: SubmissionValues + publicUrl: String? + feedbackThreadUuid: UuidValue? + ### The publication's last message (Markdown) and when it came. + lastMessage: String? + lastMessageAt: DateTime? + ### The document revision of the last submit (null before the first). + lastSubmittedRevision: int? + revisions: List + updatedAt: DateTime diff --git a/wonky_server/lib/src/platform/publications/publication_api.dart b/wonky_server/lib/src/platform/publications/publication_api.dart new file mode 100644 index 00000000..e6de69bb --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_api.dart @@ -0,0 +1,464 @@ +import 'dart:convert'; +import 'dart:typed_data'; + +import 'package:serverpod/serverpod.dart'; + +import '../common/models.dart'; +import '../common/time.dart'; +import '../files/storage_reads.dart'; +import 'publication_common.dart'; +import 'publication_keys.dart'; +import 'publication_rules.dart'; +import 'submission_service.dart'; + +/// The answer of a publication API call (JSON, or a byte stream). +class PublicationApiResult { + const PublicationApiResult( + this.status, + this.json, { + this.headers = const {}, + this.stream, + this.contentType, + this.contentLength, + }); + + factory PublicationApiResult.error(int status, String code, String message) => + PublicationApiResult(status, {'error': code, 'message': message}); + + final int status; + final Map? json; + final Map headers; + final Stream? stream; + final String? contentType; + final int? contentLength; +} + +/// Result of checking the API key from the headers. +class PublicationApiAuth { + const PublicationApiAuth.ok(Publication this.publication) : refused = null; + const PublicationApiAuth.refused(PublicationApiResult this.refused) + : publication = null; + + final Publication? publication; + final PublicationApiResult? refused; +} + +/// The publication API (specs/18 §7.3) behind `/api/pub/v1/**`. +abstract final class PublicationApi { + static const maxBodyBytes = 1024 * 1024; + + static PublicationApiResult notFound([String what = 'Not found.']) => + PublicationApiResult.error(404, 'notFound', what); + + static PublicationApiResult invalid(String message) => + PublicationApiResult.error(400, 'invalidArgument', message); + + /// Checks the declared size and the bearer key before any body is read. + static Future authenticate( + Session session, { + required String? authorization, + required int? declaredLength, + }) async { + if (declaredLength != null && declaredLength > maxBodyBytes) { + return PublicationApiAuth.refused( + PublicationApiResult.error(413, 'tooLarge', 'The body is too large.'), + ); + } + const prefix = 'Bearer '; + final key = authorization != null && authorization.startsWith(prefix) + ? authorization.substring(prefix.length).trim() + : null; + if (key == null || !PublicationKeys.apiKeyPattern.hasMatch(key)) { + return const PublicationApiAuth.refused(_unauthorized); + } + final hash = PublicationKeys.hashApiKey(key); + final retry = await Publications.apiLimiter.check(hash); + if (retry != null) { + return PublicationApiAuth.refused( + PublicationApiResult( + 429, + {'error': 'rateLimited', 'message': 'Too many requests.'}, + headers: {'retry-after': '${retry.inSeconds + 1}'}, + ), + ); + } + final p = await Publication.db.findFirstRow( + session, + where: (t) => t.apiKeyHash.equals(hash), + ); + if (p == null) return const PublicationApiAuth.refused(_unauthorized); + return PublicationApiAuth.ok(p); + } + + static const _unauthorized = PublicationApiResult(401, { + 'error': 'unauthorized', + 'message': 'Send the API key as "Authorization: Bearer wpk_…".', + }); + + /// Routes one call. + static Future handle( + Session session, + Publication p, { + required String method, + required List segments, + required Map query, + required String body, + }) async { + try { + return switch ((method, segments)) { + ('GET', ['submissions']) => await _list(session, p, query), + ('GET', ['submissions', final id]) => await _get(session, p, id), + ('GET', ['submissions', final id, 'content']) => await _content( + session, + p, + id, + query, + ), + ('POST', ['submissions', final id, 'status']) => await _status( + session, + p, + id, + body, + ), + ('POST', ['submissions', final id, 'messages']) => await _message( + session, + p, + id, + body, + ), + ('GET', ['assets', final id]) => await _asset(session, p, id), + ('POST', ['blocks']) => await _block(session, p, body), + ('DELETE', ['blocks', final id]) => await _unblock(session, p, id), + _ => notFound('No such API call.'), + }; + } on PublicationGone { + return PublicationApiResult.error( + 410, + 'gone', + 'The submission was withdrawn or disconnected.', + ); + } on PublicationTransitionError catch (e) { + return PublicationApiResult.error(409, 'invalidTransition', e.message); + } on WonkyException catch (e) { + return switch (e.code) { + WonkyErrorCode.notFound => notFound(e.message), + WonkyErrorCode.invalidArgument => invalid(e.message), + WonkyErrorCode.tooLarge => PublicationApiResult.error( + 413, + 'tooLarge', + e.message, + ), + _ => PublicationApiResult.error(400, e.code.name, e.message), + }; + } on FormatException { + return invalid('The body must be a JSON object.'); + } + } + + static Map _object(String body) { + final json = jsonDecode(body.isEmpty ? '{}' : body); + if (json is! Map) throw const FormatException(); + return json; + } + + static Future _find( + Session session, + Publication p, + String id, + ) async { + final uuid = Publications.parseSubmissionId(id); + if (uuid == null) return null; + return Submission.db.findFirstRow( + session, + where: (t) => t.uuid.equals(uuid) & t.publicationId.equals(p.id!), + ); + } + + static Future> _entry( + Session session, + Submission s, { + bool withFields = false, + }) async { + final item = await DriveItem.db.findById(session, s.itemId); + final last = await SubmissionRevision.db.findFirstRow( + session, + where: (t) => t.submissionId.equals(s.id!), + orderBy: (t) => t.sequence.desc(), + ); + return { + 'id': Publications.submissionId(s), + 'ref': s.ref, + 'status': s.status.name, + 'documentUrl': item == null + ? null + : Publications.documentUrl(session, item.uuid), + 'title': s.values.title, + 'sequence': last?.sequence, + 'revision': last?.revision, + 'submittedAt': last?.submittedAt.toIso8601String(), + 'updatedAt': s.updatedAt.toIso8601String(), + 'publicUrl': s.publicUrl, + if (withFields) + 'fields': { + 'title': s.values.title, + 'summary': s.values.summary, + 'tags': s.values.tags, + 'coverImage': s.values.coverImage == null + ? null + : Publications.assetId(s.values.coverImage!), + 'authorBio': s.values.authorBio, + 'note': s.values.note, + }, + }; + } + + static Future _list( + Session session, + Publication p, + Map query, + ) async { + final status = query['status']; + final SubmissionStatus? filter; + if (status == null || status.isEmpty) { + filter = null; + } else { + filter = SubmissionStatus.values.asNameMap()[status]; + if (filter == null) return invalid('Unknown status "$status".'); + } + final limit = int.tryParse(query['limit'] ?? '') ?? 50; + if (limit < 1 || limit > 100) return invalid('limit must be 1–100.'); + // Cursor: "_" of the last entry of a page. + DateTime? afterAt; + int? afterId; + if (query['after'] case final after? when after.isNotEmpty) { + final parts = after.split('_'); + final micros = parts.length == 2 ? int.tryParse(parts[0]) : null; + afterId = parts.length == 2 ? int.tryParse(parts[1]) : null; + if (micros == null || afterId == null) return invalid('Invalid cursor.'); + afterAt = DateTime.fromMicrosecondsSinceEpoch(micros, isUtc: true); + } + final rows = await Submission.db.find( + session, + where: (t) { + var w = + t.publicationId.equals(p.id!) & + t.status.notEquals( + SubmissionStatus.draft, + ); + if (filter != null) w = w & t.status.equals(filter); + if (afterAt != null) { + w = + w & + ((t.updatedAt < afterAt) | + (t.updatedAt.equals(afterAt) & (t.id < afterId!))); + } + return w; + }, + orderByList: (t) => [t.updatedAt.desc(), t.id.desc()], + limit: limit + 1, + ); + final page = rows.take(limit).toList(); + return PublicationApiResult(200, { + 'submissions': [for (final s in page) await _entry(session, s)], + 'next': rows.length > limit + ? '${page.last.updatedAt.microsecondsSinceEpoch}_${page.last.id}' + : null, + }); + } + + static Future _get( + Session session, + Publication p, + String id, + ) async { + final s = await _find(session, p, id); + if (s == null || s.status == SubmissionStatus.draft) { + return notFound('No such submission.'); + } + return PublicationApiResult( + 200, + await _entry(session, s, withFields: true), + ); + } + + static Future _content( + Session session, + Publication p, + String id, + Map query, + ) async { + final s = await _find(session, p, id); + if (s == null) return notFound('No such submission.'); + final sequence = int.tryParse(query['sequence'] ?? ''); + if (query['sequence'] != null && sequence == null) { + return invalid('sequence must be a number.'); + } + final rev = await SubmissionRevision.db.findFirstRow( + session, + where: (t) => sequence == null + ? t.submissionId.equals(s.id!) + : t.submissionId.equals(s.id!) & t.sequence.equals(sequence), + orderBy: (t) => t.sequence.desc(), + ); + if (rev == null) return notFound('No such submitted version.'); + return PublicationApiResult( + 200, + (jsonDecode(rev.payload) as Map).cast(), + ); + } + + static Future _status( + Session session, + Publication p, + String id, + String body, + ) async { + final s = await _find(session, p, id); + if (s == null || s.status == SubmissionStatus.draft) { + return notFound('No such submission.'); + } + final json = _object(body); + final status = SubmissionStatus.values.asNameMap()['${json['status']}']; + if (status == null) { + return invalid( + 'status must be inReview, changesRequested, declined or published.', + ); + } + final message = json['message']; + final url = json['publicUrl']; + if (message != null && message is! String) { + return invalid('message must be a string.'); + } + if (url != null && url is! String) { + return invalid('publicUrl must be a string.'); + } + if (message is String && + message.length > PublicationRules.maxMessageLength) { + return invalid('message is longer than 10,000 characters.'); + } + final updated = await SubmissionService.setStatus( + session, + p, + s, + status: status, + message: message as String?, + publicUrl: url as String?, + ); + return PublicationApiResult( + 200, + await _entry(session, updated, withFields: true), + ); + } + + static Future _message( + Session session, + Publication p, + String id, + String body, + ) async { + final s = await _find(session, p, id); + if (s == null || s.status == SubmissionStatus.draft) { + return notFound('No such submission.'); + } + final text = _object(body)['body']; + if (text is! String || text.trim().isEmpty) { + return invalid('body must be a non-empty string.'); + } + if (text.length > PublicationRules.maxMessageLength) { + return invalid('body is longer than 10,000 characters.'); + } + await SubmissionService.postMessage(session, p, s, text); + return const PublicationApiResult(200, {'ok': true}); + } + + static Future _asset( + Session session, + Publication p, + String id, + ) async { + final uuid = Publications.parseAssetId(id); + if (uuid == null) return notFound('No such asset.'); + final uses = await SubmissionAsset.db.find( + session, + where: (t) => t.fileUuid.equals(uuid), + ); + final allowed = + uses.isNotEmpty && + await Submission.db.count( + session, + where: (t) => + t.id.inSet({for (final a in uses) a.submissionId}) & + t.publicationId.equals(p.id!), + ) > + 0; + if (!allowed) return notFound('No such asset.'); + final file = await StoredFile.db.findFirstRow( + session, + where: (t) => t.fileUuid.equals(uuid), + ); + if (file == null || file.status != StoredFileStatus.ready) { + return notFound('The image no longer exists.'); + } + return PublicationApiResult( + 200, + null, + headers: const { + 'x-content-type-options': 'nosniff', + 'content-security-policy': "sandbox; default-src 'none'", + 'cache-control': 'private, no-store', + }, + stream: StorageReads.stream(session.serverpod, file), + contentType: file.mimeType, + contentLength: file.sizeBytes, + ); + } + + static Future _profileOf(Session session, Object? wonkyUserId) async { + if (wonkyUserId is! String) return null; + try { + final uuid = UuidValue.withValidation(wonkyUserId); + final profile = await UserProfile.db.findFirstRow( + session, + where: (t) => t.authUserId.equals(uuid), + ); + return profile?.id; + } on FormatException { + return null; + } + } + + static Future _block( + Session session, + Publication p, + String body, + ) async { + final userId = await _profileOf(session, _object(body)['wonkyUserId']); + if (userId == null) return notFound('No such Wonky user.'); + final existing = await PublicationBlock.db.findFirstRow( + session, + where: (t) => t.publicationId.equals(p.id!) & t.userId.equals(userId), + ); + if (existing == null) { + await PublicationBlock.db.insertRow( + session, + PublicationBlock(publicationId: p.id!, userId: userId, at: nowUtc()), + ); + } + return const PublicationApiResult(200, {'ok': true}); + } + + static Future _unblock( + Session session, + Publication p, + String wonkyUserId, + ) async { + final userId = await _profileOf(session, wonkyUserId); + if (userId != null) { + await PublicationBlock.db.deleteWhere( + session, + where: (t) => t.publicationId.equals(p.id!) & t.userId.equals(userId), + ); + } + return const PublicationApiResult(200, {'ok': true}); + } +} diff --git a/wonky_server/lib/src/platform/publications/publication_common.dart b/wonky_server/lib/src/platform/publications/publication_common.dart new file mode 100644 index 00000000..0e0ca275 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_common.dart @@ -0,0 +1,182 @@ +import 'dart:convert'; + +import 'package:crypto/crypto.dart'; +import 'package:serverpod/serverpod.dart'; + +import '../common/errors.dart'; +import '../common/models.dart'; +import '../common/rate_limiter.dart'; +import '../common/time.dart'; +import '../config/wonky_config.dart'; +import 'publication_keys.dart'; +import 'publication_rules.dart'; + +/// Shared lookups and links of publications (specs/18). +abstract final class Publications { + /// The public id of a submission: `sub_`. + static String submissionId(Submission s) => 'sub_${s.uuid.uuid}'; + + static UuidValue? parseSubmissionId(String id) => + _uuid(id.startsWith('sub_') ? id.substring(4) : null); + + /// The public id of an image of a submission: `ast_`. + static String assetId(UuidValue fileUuid) => 'ast_${fileUuid.uuid}'; + + static UuidValue? parseAssetId(String id) => + _uuid(id.startsWith('ast_') ? id.substring(4) : null); + + static UuidValue? _uuid(String? s) { + if (s == null) return null; + try { + return UuidValue.withValidation(s); + } on FormatException { + return null; + } + } + + static Uri webOrigin(Session session) => + WonkyConfig.current.webOrigin(session.serverpod.config); + + /// `https:///write/d/`. + static String documentUrl(Session session, UuidValue itemUuid) => + webOrigin(session).resolve('write/d/${itemUuid.uuid}').toString(); + + /// `https:///write/new?publication=`. + static String contributorLink(Session session, String publicId) => webOrigin( + session, + ).resolve('write/new?publication=$publicId').toString(); + + /// The API URL of an image (specs/18 §7.1). + static String assetUrl(Session session, UuidValue fileUuid) => webOrigin( + session, + ).resolve('api/pub/v1/assets/${assetId(fileUuid)}').toString(); + + /// The host contributors are shown: the verified site host, else the + /// webhook host (specs/18 §8.2). + static String shownHost(Publication p) => + p.verifiedHost ?? PublicationRules.hostOf(p.webhookUrl); + + /// What a contributor agrees to; consent is asked again when it changes. + static String consentKey(Publication p) => sha256 + .convert( + utf8.encode( + '${shownHost(p)}|${PublicationRules.hostOf(p.webhookUrl)}|' + '${p.termsUrl ?? ''}', + ), + ) + .toString(); + + static Future byPublicId( + Session session, + String publicId, + ) async { + if (!PublicationKeys.publicIdPattern.hasMatch(publicId)) { + throw Errors.notFound('Publication'); + } + final p = await Publication.db.findFirstRow( + session, + where: (t) => t.publicId.equals(publicId), + ); + if (p == null) throw Errors.notFound('Publication'); + return p; + } + + static Future isBlocked( + Session session, + int publicationId, + int userId, + ) async => + await PublicationBlock.db.findFirstRow( + session, + where: (t) => + t.publicationId.equals(publicationId) & t.userId.equals(userId), + ) != + null; + + static Future consentNeeded( + Session session, + Publication p, + int userId, + ) async { + final consent = await PublicationConsent.db.findFirstRow( + session, + where: (t) => t.publicationId.equals(p.id!) & t.userId.equals(userId), + ); + return consent?.consentKey != consentKey(p); + } + + static Future recordConsent( + Session session, + Publication p, + int userId, + ) async { + final key = consentKey(p); + final now = nowUtc(); + final existing = await PublicationConsent.db.findFirstRow( + session, + where: (t) => t.publicationId.equals(p.id!) & t.userId.equals(userId), + ); + if (existing == null) { + await PublicationConsent.db.insertRow( + session, + PublicationConsent( + publicationId: p.id!, + userId: userId, + consentKey: key, + at: now, + ), + ); + } else if (existing.consentKey != key) { + await PublicationConsent.db.updateRow( + session, + existing.copyWith(consentKey: key, at: now), + columns: (t) => [t.consentKey, t.at], + ); + } + } + + /// The users who may edit [item]: its owner and Editor grants. + static Future> editorsOf(Session session, DriveItem item) async { + final grants = await DriveItemPermission.db.find( + session, + where: (t) => + t.itemId.equals(item.id!) & + t.userId.notEquals(null) & + t.role.inSet({AccessRole.editor, AccessRole.owner}), + ); + return {item.ownerId, for (final g in grants) g.userId!}; + } + + /// Per user and publication: stories started and submits per day + /// (specs/18 §10). + static final startLimiter = RateLimiter( + name: 'publications.start', + limit: PublicationRules.startsPerDay, + window: const Duration(days: 1), + ); + static final submitLimiter = RateLimiter( + name: 'publications.submit', + limit: PublicationRules.submitsPerDay, + window: const Duration(days: 1), + ); + + /// Calls of the publication API per key (specs/18 §7.3). + static final apiLimiter = RateLimiter( + name: 'publications.api', + limit: PublicationRules.apiCallsPerMinute, + ); + + static Future checkLimit( + RateLimiter limiter, + Object key, + String message, + ) async { + final retry = await limiter.check(key); + if (retry != null) { + throw Errors.limit( + message, + detailsJson: jsonEncode({'retryAfterSeconds': retry.inSeconds + 1}), + ); + } + } +} diff --git a/wonky_server/lib/src/platform/publications/publication_endpoint.dart b/wonky_server/lib/src/platform/publications/publication_endpoint.dart new file mode 100644 index 00000000..a76f04d1 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_endpoint.dart @@ -0,0 +1,133 @@ +import 'package:serverpod/serverpod.dart'; + +import '../common/models.dart'; +import '../users/user_service.dart'; +import 'publication_service.dart'; + +/// Publications (specs/18 §9.1): starting a story from a contributor link, +/// and the owner's settings. +class PublicationEndpoint extends Endpoint { + @override + bool get requireLogin => true; + + /// The publication of a contributor link. + Future resolve(Session session, String publicId) async => + PublicationService.resolve( + session, + await UserService.actorOf(session), + publicId, + ); + + /// Creates the document of a new story; [agreed] confirms the consent + /// dialog. + Future startSubmission( + Session session, + String publicId, + String? ref, + bool agreed, + ) async => PublicationService.startSubmission( + session, + await UserService.actorOf(session), + publicId, + ref: ref, + agreed: agreed, + ); + + Future> list(Session session) async => + PublicationService.list(session, await UserService.actorOf(session)); + + /// Creates a publication; the result holds the signing secret once. + Future create( + Session session, + PublicationInput input, + ) async => PublicationService.create( + session, + await UserService.actorOf(session), + input, + ); + + Future update( + Session session, + String publicId, + PublicationInput input, + ) async => PublicationService.update( + session, + await UserService.actorOf(session), + publicId, + input, + ); + + Future delete(Session session, String publicId) async => + PublicationService.delete( + session, + await UserService.actorOf(session), + publicId, + ); + + Future verify( + Session session, + String publicId, + ) async => PublicationService.verify( + session, + await UserService.actorOf(session), + publicId, + ); + + Future rotateSecret( + Session session, + String publicId, + ) async => PublicationService.rotateSecret( + session, + await UserService.actorOf(session), + publicId, + ); + + Future createApiKey( + Session session, + String publicId, + ) async => PublicationService.createApiKey( + session, + await UserService.actorOf(session), + publicId, + ); + + Future setModerators( + Session session, + String publicId, + List emails, + ) async => PublicationService.setModerators( + session, + await UserService.actorOf(session), + publicId, + emails, + ); + + Future> deliveries( + Session session, + String publicId, + ) async => PublicationService.deliveries( + session, + await UserService.actorOf(session), + publicId, + ); + + Future resend( + Session session, + String publicId, + String webhookId, + ) async => PublicationService.resend( + session, + await UserService.actorOf(session), + publicId, + webhookId, + ); + + Future sendTest( + Session session, + String publicId, + ) async => PublicationService.sendTest( + session, + await UserService.actorOf(session), + publicId, + ); +} diff --git a/wonky_server/lib/src/platform/publications/publication_future_call.dart b/wonky_server/lib/src/platform/publications/publication_future_call.dart new file mode 100644 index 00000000..b9008b79 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_future_call.dart @@ -0,0 +1,24 @@ +import 'package:serverpod/serverpod.dart'; + +import '../common/guarded.dart'; +import 'publication_webhooks.dart'; + +/// Webhook deliveries of publications (specs/18 §7.2): one right after an +/// event, and the sweep of due retries (`wonky.publicationSweep`, every +/// minute). +class PublicationsFutureCall extends FutureCall { + Future deliver(Session session, int deliveryId) => runGuarded( + session, + 'publications.deliver $deliveryId', + () => PublicationWebhooks.attempt(session, deliveryId), + ); + + Future sweep(Session session) => runGuarded( + session, + 'publications.sweep', + () async => + await PublicationWebhooks.sweep(session) + + await PublicationWebhooks.purgeOld(session), + describe: describeCount, + ); +} diff --git a/wonky_server/lib/src/platform/publications/publication_http.dart b/wonky_server/lib/src/platform/publications/publication_http.dart new file mode 100644 index 00000000..29549e35 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_http.dart @@ -0,0 +1,90 @@ +import 'package:wonky_sheets_script/wonky_sheets_script.dart' + show FetchFailure, FetchRequestData; + +import '../../sheets/scripts/url_fetch_proxy.dart'; + +/// The answer of a blog's server to an outbound call. +class PublicationHttpResult { + const PublicationHttpResult(this.status, {this.body = '', this.error}); + + /// HTTP status; 0 when the call failed before an answer (network error, + /// timeout, blocked address). + final int status; + final String body; + final String? error; + + bool get ok => status >= 200 && status < 300; +} + +/// Outbound HTTP of publications (specs/18 §7.2, §8.2): webhooks and the +/// `.well-known` verification. Tests replace [instance] with a fake. +abstract class PublicationHttp { + static PublicationHttp? override; + + static PublicationHttp get instance => override ?? _default; + static final PublicationHttp _default = SafePublicationHttp(); + + Future post( + String url, { + required Map headers, + required String body, + }); + + Future get(String url); +} + +/// [PublicationHttp] through the SSRF-safe [UrlFetchProxy] (specs/13 §1): +/// https on port 443 only, public addresses only (pinned), no redirects, +/// 10 s timeout, answers read up to 1 MB. +class SafePublicationHttp implements PublicationHttp { + SafePublicationHttp({UrlFetchProxy? proxy}) + : _proxy = + proxy ?? + UrlFetchProxy( + ports: const {443}, + maxRedirects: 0, + maxResponseBytes: 1024 * 1024, + maxPayloadBytes: 6 * 1024 * 1024, + userAgent: 'WonkyWork-Publications/1.0 (+https://wonky.work)', + ); + + final UrlFetchProxy _proxy; + + static const timeoutSeconds = 10; + + @override + Future post( + String url, { + required Map headers, + required String body, + }) => _send( + FetchRequestData( + url: url, + method: 'post', + headers: headers, + payload: body, + contentType: 'application/json', + followRedirects: false, + timeoutSeconds: timeoutSeconds, + ), + ); + + @override + Future get(String url) => _send( + FetchRequestData( + url: url, + headers: const {'accept': 'application/json'}, + followRedirects: false, + timeoutSeconds: timeoutSeconds, + ), + ); + + Future _send(FetchRequestData request) async { + try { + final res = await _proxy.fetch(request); + return PublicationHttpResult(res.statusCode, body: res.contentText); + } on FetchFailure catch (e) { + return PublicationHttpResult(0, error: e.message); + } + } +} diff --git a/wonky_server/lib/src/platform/publications/publication_keys.dart b/wonky_server/lib/src/platform/publications/publication_keys.dart new file mode 100644 index 00000000..f071094b --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_keys.dart @@ -0,0 +1,72 @@ +import 'dart:convert'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart'; + +/// Ids, secrets and webhook signatures of publications (specs/18 §6, §7.1). +/// +/// Webhooks are signed per Standard Webhooks +/// (https://www.standardwebhooks.com/): the secret is `whsec_` + base64 of +/// the key bytes, the signature `v1,` + base64 of +/// HMAC-SHA256(key, `..`). +abstract final class PublicationKeys { + static Random random = Random.secure(); + + static const _alphabet = + 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'; + + static String _token(int length) => List.generate( + length, + (_) => _alphabet[random.nextInt(_alphabet.length)], + ).join(); + + /// The public id in contributor links: `pub_` + 22 url-safe characters. + static String newPublicId() => 'pub_${_token(22)}'; + + static final publicIdPattern = RegExp(r'^pub_[A-Za-z0-9_-]{22}$'); + + /// A new signing secret: `whsec_` + base64 of 32 random bytes. + static String newSigningSecret() { + final bytes = Uint8List.fromList( + List.generate(32, (_) => random.nextInt(256)), + ); + return 'whsec_${base64.encode(bytes)}'; + } + + /// A new API key: `wpk_` + 40 url-safe characters. + static String newApiKey() => 'wpk_${_token(40)}'; + + static final apiKeyPattern = RegExp(r'^wpk_[A-Za-z0-9_-]{40}$'); + + /// SHA-256 (hex) of an API key, the form it is stored in. + static String hashApiKey(String key) => + sha256.convert(utf8.encode(key)).toString(); + + /// The signature of one webhook: `v1,`. + static String sign({ + required String secret, + required String webhookId, + required int timestamp, + required String body, + }) { + final key = base64.decode(secret.substring('whsec_'.length)); + final mac = Hmac( + sha256, + key, + ).convert(utf8.encode('$webhookId.$timestamp.$body')); + return 'v1,${base64.encode(mac.bytes)}'; + } + + /// The `webhook-signature` header: one signature per [secrets] (two while + /// a rotated secret still signs), space separated. + static String signatureHeader({ + required Iterable secrets, + required String webhookId, + required int timestamp, + required String body, + }) => [ + for (final s in secrets) + sign(secret: s, webhookId: webhookId, timestamp: timestamp, body: body), + ].join(' '); +} diff --git a/wonky_server/lib/src/platform/publications/publication_rules.dart b/wonky_server/lib/src/platform/publications/publication_rules.dart new file mode 100644 index 00000000..9cb94c65 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_rules.dart @@ -0,0 +1,174 @@ +import '../common/errors.dart'; +import '../common/models.dart'; + +/// Pure rules of publications and submissions (specs/18): limits, URL and +/// field validation, and the status transitions the blog may make. +abstract final class PublicationRules { + static const maxPublicationsPerOwner = 10; + static const maxModerators = 20; + static const maxNameLength = 60; + static const maxUrlLength = 2000; + static const maxFieldLength = 2000; + static const maxTitleLength = 300; + static const maxTags = 20; + static const maxTagLength = 40; + static const maxMessageLength = 10000; + static const maxRefLength = 64; + static const maxMarkdownBytes = 5 * 1024 * 1024; + + /// Per user and publication per day (specs/18 §10). + static const startsPerDay = 10; + static const submitsPerDay = 20; + + /// Publication API calls per key and minute (specs/18 §7.3). + static const apiCallsPerMinute = 120; + + static final refPattern = RegExp(r'^[A-Za-z0-9_-]{1,64}$'); + + /// Parses an `https` URL; [originOnly] refuses a path, query or fragment. + static Uri httpsUrl(String raw, String what, {bool originOnly = false}) { + final value = raw.trim(); + if (value.isEmpty || value.length > maxUrlLength) { + throw Errors.invalid('Enter the $what.'); + } + final uri = Uri.tryParse(value); + if (uri == null || + uri.scheme != 'https' || + uri.host.isEmpty || + uri.userInfo.isNotEmpty || + uri.fragment.isNotEmpty) { + throw Errors.invalid('The $what must be an https:// address.'); + } + if (uri.hasPort && uri.port != 443) { + throw Errors.invalid('The $what must use the standard https port.'); + } + if (originOnly && + ((uri.path.isNotEmpty && uri.path != '/') || uri.hasQuery)) { + throw Errors.invalid( + 'The $what must be the site address only, like https://blog.example.com.', + ); + } + return uri; + } + + /// `https://host` of a site URL. + static String origin(Uri uri) => 'https://${uri.host.toLowerCase()}'; + + static String hostOf(String url) => Uri.parse(url).host.toLowerCase(); + + /// The publication's status calls (specs/18 §2.1, §7.3): which status the + /// blog may set from [from]. + static bool blogMayMove(SubmissionStatus from, SubmissionStatus to) => + switch (to) { + SubmissionStatus.inReview || + SubmissionStatus.changesRequested || + SubmissionStatus.declined => const { + SubmissionStatus.inReview, + SubmissionStatus.changesRequested, + }.contains(from), + SubmissionStatus.published => const { + SubmissionStatus.inReview, + SubmissionStatus.changesRequested, + SubmissionStatus.published, + }.contains(from), + SubmissionStatus.draft || SubmissionStatus.withdrawn => false, + }; + + /// Whether an editor may submit in [status]. + static bool maySubmit(SubmissionStatus status) => switch (status) { + SubmissionStatus.draft || + SubmissionStatus.inReview || + SubmissionStatus.changesRequested || + SubmissionStatus.published || + SubmissionStatus.withdrawn => true, + SubmissionStatus.declined => false, + }; + + /// Whether moderators hold Commenter in [status] (specs/18 §5.1). + static bool moderatorsHaveAccess(SubmissionStatus status) => switch (status) { + SubmissionStatus.inReview || + SubmissionStatus.changesRequested || + SubmissionStatus.published => true, + SubmissionStatus.draft || + SubmissionStatus.declined || + SubmissionStatus.withdrawn => false, + }; + + /// Open = the blog is reviewing it or waits for the author. + static bool isOpen(SubmissionStatus status) => + status == SubmissionStatus.inReview || + status == SubmissionStatus.changesRequested; + + /// Checks and normalizes the fields of a submit against [fields]. + static SubmissionValues values( + SubmissionValues v, + PublicationFields fields, + ) { + String? text(String? s, PublicationFieldMode mode, String label) { + final t = s?.trim(); + if (mode == PublicationFieldMode.off) return null; + if (t == null || t.isEmpty) { + if (mode == PublicationFieldMode.required) { + throw Errors.invalid('Enter the $label.'); + } + return null; + } + if (t.length > maxFieldLength) { + throw Errors.invalid('The $label is too long.'); + } + return t; + } + + final title = v.title.trim(); + if (title.isEmpty) throw Errors.invalid('Enter a title.'); + if (title.length > maxTitleLength) { + throw Errors.invalid('The title is too long.'); + } + var tags = []; + if (fields.tags != PublicationFieldMode.off) { + final allowed = {for (final t in fields.allowedTags) t.toLowerCase()}; + final seen = {}; + for (final raw in v.tags) { + final t = raw.trim(); + if (t.isEmpty || !seen.add(t.toLowerCase())) continue; + if (t.length > maxTagLength) { + throw Errors.invalid('The tag "$t" is too long.'); + } + if (allowed.isNotEmpty && !allowed.contains(t.toLowerCase())) { + throw Errors.invalid('"$t" isn\'t one of the tags you can pick.'); + } + tags.add(t); + } + if (tags.length > maxTags) { + throw Errors.invalid('Pick at most $maxTags tags.'); + } + if (tags.isEmpty && fields.tags == PublicationFieldMode.required) { + throw Errors.invalid('Add at least one tag.'); + } + } + final cover = fields.coverImage == PublicationFieldMode.off + ? null + : v.coverImage; + if (cover == null && fields.coverImage == PublicationFieldMode.required) { + throw Errors.invalid('Pick a cover image.'); + } + return SubmissionValues( + title: title, + summary: text(v.summary, fields.summary, 'summary'), + tags: tags, + coverImage: cover, + authorBio: text(v.authorBio, fields.authorBio, 'author bio'), + note: text(v.note, fields.note, 'note to the moderators'), + ); + } + + /// The fields of a new publication: summary and tags optional. + static PublicationFields defaultFields() => PublicationFields( + summary: PublicationFieldMode.optional, + tags: PublicationFieldMode.optional, + allowedTags: [], + coverImage: PublicationFieldMode.off, + authorBio: PublicationFieldMode.off, + note: PublicationFieldMode.optional, + ); +} diff --git a/wonky_server/lib/src/platform/publications/publication_service.dart b/wonky_server/lib/src/platform/publications/publication_service.dart new file mode 100644 index 00000000..f99f6d68 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_service.dart @@ -0,0 +1,748 @@ +import 'dart:convert'; + +import 'package:serverpod/serverpod.dart'; +import 'package:wonky_core/wonky_core.dart' show Role; +import 'package:wonky_write_core/wonky_write_core.dart' as core; + +import '../../write/ot/document_store.dart'; +import '../common/actor.dart'; +import '../common/errors.dart'; +import '../common/guarded.dart'; +import '../common/models.dart'; +import '../common/time.dart'; +import '../drive/drive_service.dart'; +import '../files/file_service.dart'; +import '../sharing/access_service.dart'; +import '../storage/storage_service.dart'; +import '../users/user_service.dart'; +import 'publication_common.dart'; +import 'publication_http.dart'; +import 'publication_keys.dart'; +import 'publication_rules.dart'; +import 'publication_webhooks.dart'; +import 'submission_service.dart'; + +/// Publications (specs/18 §3, §8, §9.1): the owner's settings, secrets, +/// moderators, verification and deliveries, and starting a story from a +/// contributor link. +abstract final class PublicationService { + static final _emailPattern = RegExp(r'^[^@\s]+@[^@\s]+\.[^@\s]+$'); + + // ---------------------------------------------------------- contributor + + /// The card a contributor sees before starting (specs/18 §3 step 3). + static Future resolve( + Session session, + Actor actor, + String publicId, + ) async { + final p = await Publications.byPublicId(session, publicId); + final owner = (await UserService.summaries(session, [ + p.ownerId, + ]))[p.ownerId]; + final open = await Submission.db.find( + session, + where: (t) => + t.publicationId.equals(p.id!) & + t.createdById.equals(actor.userId) & + t.disconnectedAt.equals(null) & + t.status.inSet({ + SubmissionStatus.draft, + SubmissionStatus.changesRequested, + }), + orderBy: (t) => t.updatedAt.desc(), + limit: 20, + ); + final openViews = []; + for (final s in open) { + final item = await DriveItem.db.findById(session, s.itemId); + if (item == null || item.trashedAt != null) continue; + final role = await AccessService.effectiveRole( + session, + actor.userId, + item, + ); + if (role == null || role < Role.editor) continue; + openViews.add( + PublicationOpenSubmission( + itemUuid: item.uuid, + name: item.name, + status: s.status, + updatedAt: s.updatedAt, + ), + ); + } + return PublicationCard( + publicId: p.publicId, + name: p.name, + shownHost: Publications.shownHost(p), + verified: p.verifiedHost != null, + siteHost: PublicationRules.hostOf(p.siteUrl), + webhookHost: PublicationRules.hostOf(p.webhookUrl), + termsUrl: p.termsUrl, + fields: p.fields, + ownerName: owner?.displayName ?? 'Deleted user', + enabled: p.enabled, + consentNeeded: await Publications.consentNeeded(session, p, actor.userId), + blocked: await Publications.isBlocked(session, p.id!, actor.userId), + openSubmissions: openViews, + ); + } + + /// Creates a document for a new story (from the publication's template) + /// and its draft submission (specs/18 §3 step 3). + static Future startSubmission( + Session session, + Actor actor, + String publicId, { + String? ref, + bool agreed = false, + }) async { + final p = await Publications.byPublicId(session, publicId); + if (!p.enabled) { + throw Errors.forbidden('${p.name} isn\'t accepting stories right now.'); + } + if (await Publications.isBlocked(session, p.id!, actor.userId)) { + throw Errors.forbidden('${p.name} isn\'t accepting stories from you.'); + } + final cleanRef = ref == null || ref.isEmpty ? null : ref; + if (cleanRef != null && !PublicationRules.refPattern.hasMatch(cleanRef)) { + throw Errors.invalid('The link has an invalid ref.'); + } + if (await Publications.consentNeeded(session, p, actor.userId)) { + if (!agreed) { + throw Errors.invalid('Agree to write for ${p.name} first.'); + } + } + await Publications.checkLimit( + Publications.startLimiter, + '${p.id}:${actor.userId}', + "You've started a lot of stories for ${p.name} today. " + 'Try again tomorrow.', + ); + await Publications.recordConsent(session, p, actor.userId); + const name = 'Untitled story'; + final view = await _createDocument(session, actor, p, name); + final item = (await AccessService.findItem(session, view.uuid))!; + final now = nowUtc(); + await Submission.db.insertRow( + session, + Submission( + uuid: const Uuid().v7obj(), + publicationId: p.id!, + itemId: item.id!, + ref: cleanRef, + status: SubmissionStatus.draft, + values: SubmissionValues(title: name, tags: []), + createdById: actor.userId, + createdAt: now, + updatedAt: now, + ), + ); + return SubmissionStarted(itemUuid: item.uuid); + } + + /// A new document in the actor's root: empty, or a copy of the + /// publication's template without comments and suggestions, with its + /// images copied into the new document. + static Future _createDocument( + Session session, + Actor actor, + Publication p, + String name, + ) async { + final template = p.templateItemId == null + ? null + : await DriveItem.db.findById(session, p.templateItemId!); + final tplDoc = template == null || template.trashedAt != null + ? null + : await DocumentStore.byItem(session, template.id!); + if (tplDoc == null) { + return DriveService.createDocument(session, actor, name: name); + } + var content = core.SuggestionView.accepted( + await DocumentStore.head(session, tplDoc), + stripComments: true, + ); + // Template images belong to the template; copies get their own. + final copies = {}; + content = core.Delta.fromOperations([ + for (final op in content.toList()) + if (op.data case { + 'image': final Map image, + } when '${image['src']}'.startsWith('wonky-file://')) + core.Operation.insert({ + 'image': { + ...image, + 'src': () { + final source = UuidValue.withValidation( + '${image['src']}'.substring('wonky-file://'.length), + ); + final copy = copies[source] ??= const Uuid().v7obj(); + return 'wonky-file://${copy.uuid}'; + }(), + }, + }, op.attributes) + else + op, + ]); + final view = await DriveService.createDocumentFromContent( + session, + actor, + name: name, + content: content, + source: tplDoc, + activitySummary: {'publication': p.name}, + quotaReason: QuotaReason.copy, + ); + final item = (await AccessService.findItem(session, view.uuid))!; + for (final MapEntry(key: source, value: copy) in copies.entries) { + await runGuarded( + session, + 'publications.copyTemplateImage', + () async { + final file = await FileService.byUuid(session, source); + if (file == null || + file.status != StoredFileStatus.ready || + file.itemId != template!.id) { + return; + } + final bytes = await FileService.readBytes(session, file); + final stored = await FileService.storeServerFile( + session, + ownerId: actor.userId, + itemId: item.id, + kind: StoredFileKind.image, + fileName: file.fileName, + mimeType: file.mimeType, + bytes: bytes.buffer.asUint8List( + bytes.offsetInBytes, + bytes.lengthInBytes, + ), + fileUuid: copy, + ); + await StorageService.instance.addAttachment( + session, + item, + stored.sizeBytes, + ); + }, + ); + } + return view; + } + + // ---------------------------------------------------------------- owner + + static Future> list( + Session session, + Actor actor, + ) async { + final pubs = await Publication.db.find( + session, + where: (t) => t.ownerId.equals(actor.userId), + orderBy: (t) => t.createdAt, + ); + return [for (final p in pubs) await settingsOf(session, p)]; + } + + static Future _own( + Session session, + Actor actor, + String publicId, + ) async { + final p = await Publications.byPublicId(session, publicId); + if (p.ownerId != actor.userId) throw Errors.notFound('Publication'); + return p; + } + + static Future settingsOf( + Session session, + Publication p, + ) async { + final mods = await PublicationModerator.db.find( + session, + where: (t) => t.publicationId.equals(p.id!), + orderBy: (t) => t.email, + ); + final users = await UserService.summaries(session, [ + for (final m in mods) m.userId, + ]); + final template = p.templateItemId == null + ? null + : await DriveItem.db.findById(session, p.templateItemId!); + final open = await Submission.db.count( + session, + where: (t) => + t.publicationId.equals(p.id!) & + t.disconnectedAt.equals(null) & + t.status.inSet({ + SubmissionStatus.inReview, + SubmissionStatus.changesRequested, + }), + ); + final now = nowUtc(); + return PublicationSettings( + publicId: p.publicId, + name: p.name, + siteUrl: p.siteUrl, + webhookUrl: p.webhookUrl, + verifiedHost: p.verifiedHost, + verifiedAt: p.verifiedAt, + templateItemUuid: template?.uuid, + templateName: template?.name, + termsUrl: p.termsUrl, + fields: p.fields, + moderators: [ + for (final m in mods) + PublicationModeratorView( + email: m.email, + name: m.userId == null ? null : users[m.userId]?.displayName, + ), + ], + hasApiKey: p.apiKeyHash != null, + apiKeyLast4: p.apiKeyLast4, + previousSecretUntil: (p.previousSecretUntil?.isAfter(now) ?? false) + ? p.previousSecretUntil + : null, + enabled: p.enabled, + contributorLink: Publications.contributorLink(session, p.publicId), + openSubmissionCount: open, + createdAt: p.createdAt, + ); + } + + /// Validated input: (name, site origin, webhook URL, terms URL, template). + static Future<(String, String, String, String?, DriveItem?)> _validate( + Session session, + Actor actor, + PublicationInput input, + ) async { + final name = input.name.trim(); + if (name.isEmpty) throw Errors.invalid('Enter a name.'); + if (name.length > PublicationRules.maxNameLength) { + throw Errors.invalid( + 'Use at most ${PublicationRules.maxNameLength} characters for the name.', + ); + } + final site = PublicationRules.origin( + PublicationRules.httpsUrl(input.siteUrl, 'site URL', originOnly: true), + ); + final webhook = PublicationRules.httpsUrl( + input.webhookUrl, + 'webhook URL', + ).toString(); + final terms = input.termsUrl == null || input.termsUrl!.trim().isEmpty + ? null + : PublicationRules.httpsUrl(input.termsUrl!, 'terms URL').toString(); + DriveItem? template; + if (input.templateItemUuid case final uuid?) { + final (item, _) = await AccessService.require( + session, + actor, + uuid, + Role.owner, + ); + if (item.kind != DriveItemKind.document) { + throw Errors.invalid('The template must be a Wonky Write document.'); + } + template = item; + } + final allowed = []; + for (final t in input.fields.allowedTags) { + final tag = t.trim(); + if (tag.isEmpty || allowed.contains(tag)) continue; + if (tag.length > PublicationRules.maxTagLength) { + throw Errors.invalid('The tag "$tag" is too long.'); + } + allowed.add(tag); + } + if (allowed.length > 200) throw Errors.invalid('Use at most 200 tags.'); + return (name, site, webhook, terms, template); + } + + /// Creates a publication; the result holds the signing secret (shown + /// once). + static Future create( + Session session, + Actor actor, + PublicationInput input, + ) async { + final count = await Publication.db.count( + session, + where: (t) => t.ownerId.equals(actor.userId), + ); + if (count >= PublicationRules.maxPublicationsPerOwner) { + throw Errors.limit( + 'You can have at most ${PublicationRules.maxPublicationsPerOwner} ' + 'publications.', + ); + } + final (name, site, webhook, terms, template) = await _validate( + session, + actor, + input, + ); + final secret = PublicationKeys.newSigningSecret(); + final now = nowUtc(); + final p = await Publication.db.insertRow( + session, + Publication( + publicId: PublicationKeys.newPublicId(), + ownerId: actor.userId, + name: name, + siteUrl: site, + webhookUrl: webhook, + templateItemId: template?.id, + termsUrl: terms, + fields: _fields(input.fields), + signingSecret: secret, + enabled: input.enabled, + createdAt: now, + updatedAt: now, + ), + ); + await _ping(session, p); + return PublicationSecret( + settings: await settingsOf(session, p), + secret: secret, + ); + } + + static PublicationFields _fields(PublicationFields f) => f.copyWith( + allowedTags: { + for (final t in f.allowedTags) + if (t.trim().isNotEmpty) t.trim(), + }.toList(), + ); + + static Future update( + Session session, + Actor actor, + String publicId, + PublicationInput input, + ) async { + final p = await _own(session, actor, publicId); + final (name, site, webhook, terms, template) = await _validate( + session, + actor, + input, + ); + final siteChanged = site != p.siteUrl; + final webhookChanged = webhook != p.webhookUrl; + final updated = await Publication.db.updateRow( + session, + p.copyWith( + name: name, + siteUrl: site, + webhookUrl: webhook, + termsUrl: terms, + templateItemId: template?.id, + fields: _fields(input.fields), + enabled: input.enabled, + verifiedHost: siteChanged ? null : p.verifiedHost, + verifiedAt: siteChanged ? null : p.verifiedAt, + updatedAt: nowUtc(), + ), + columns: (t) => [ + t.name, + t.siteUrl, + t.webhookUrl, + t.termsUrl, + t.templateItemId, + t.fields, + t.enabled, + t.verifiedHost, + t.verifiedAt, + t.updatedAt, + ], + ); + if (webhookChanged) await _ping(session, updated); + return settingsOf(session, updated); + } + + /// Deletes a publication: its submissions disconnect (cascade), the + /// moderators' grants go with it; nothing is sent. + static Future delete( + Session session, + Actor actor, + String publicId, + ) async { + final p = await _own(session, actor, publicId); + final items = [ + for (final s in await Submission.db.find( + session, + where: (t) => t.publicationId.equals(p.id!), + )) + s.itemId, + ]; + await Publication.db.deleteRow(session, p); + for (final id in items) { + final item = await DriveItem.db.findById(session, id); + if (item != null) { + await SubmissionService.changedAfterDelete(session, item); + } + } + } + + static Future rotateSecret( + Session session, + Actor actor, + String publicId, + ) async { + final p = await _own(session, actor, publicId); + final secret = PublicationKeys.newSigningSecret(); + final updated = await Publication.db.updateRow( + session, + p.copyWith( + signingSecret: secret, + previousSigningSecret: p.signingSecret, + previousSecretUntil: nowUtc().add(const Duration(hours: 24)), + updatedAt: nowUtc(), + ), + columns: (t) => [ + t.signingSecret, + t.previousSigningSecret, + t.previousSecretUntil, + t.updatedAt, + ], + ); + return PublicationSecret( + settings: await settingsOf(session, updated), + secret: secret, + ); + } + + /// Creates or replaces the API key; the old key stops working at once. + static Future createApiKey( + Session session, + Actor actor, + String publicId, + ) async { + final p = await _own(session, actor, publicId); + final key = PublicationKeys.newApiKey(); + final updated = await Publication.db.updateRow( + session, + p.copyWith( + apiKeyHash: PublicationKeys.hashApiKey(key), + apiKeyLast4: key.substring(key.length - 4), + updatedAt: nowUtc(), + ), + columns: (t) => [t.apiKeyHash, t.apiKeyLast4, t.updatedAt], + ); + return PublicationSecret( + settings: await settingsOf(session, updated), + secret: key, + ); + } + + static Future setModerators( + Session session, + Actor actor, + String publicId, + List emails, + ) async { + final p = await _own(session, actor, publicId); + final wanted = {}; + for (final raw in emails) { + final e = raw.trim().toLowerCase(); + if (e.isEmpty) continue; + if (!_emailPattern.hasMatch(e)) { + throw Errors.invalid('"$raw" isn\'t an email address.'); + } + wanted.add(e); + } + if (wanted.length > PublicationRules.maxModerators) { + throw Errors.limit( + 'A publication can have at most ${PublicationRules.maxModerators} ' + 'moderators.', + ); + } + final existing = await PublicationModerator.db.find( + session, + where: (t) => t.publicationId.equals(p.id!), + ); + final gone = [ + for (final m in existing) + if (!wanted.contains(m.email)) m, + ]; + if (gone.isNotEmpty) await PublicationModerator.db.delete(session, gone); + final have = {for (final m in existing) m.email}; + final added = [ + for (final e in wanted) + if (!have.contains(e)) e, + ]; + if (added.isNotEmpty) { + final profiles = await UserProfile.db.find( + session, + where: (t) => t.email.inSet(added.toSet()), + ); + final byEmail = {for (final u in profiles) u.email.toLowerCase(): u.id!}; + await PublicationModerator.db.insert(session, [ + for (final e in added) + PublicationModerator( + publicationId: p.id!, + userId: byEmail[e], + email: e, + ), + ]); + } + if (gone.isNotEmpty || added.isNotEmpty) { + await SubmissionService.syncPublication(session, p); + } + return settingsOf(session, p); + } + + // ------------------------------------------- verification and deliveries + + /// Checks `/.well-known/wonky-publications.json` on the site host + /// (specs/18 §8.2). + static Future verify( + Session session, + Actor actor, + String publicId, + ) async { + final p = await _own(session, actor, publicId); + final host = PublicationRules.hostOf(p.siteUrl); + final url = 'https://$host/.well-known/wonky-publications.json'; + final res = await PublicationHttp.instance.get(url); + String? problem; + if (!res.ok) { + problem = res.status == 0 + ? 'Could not load $url: ${res.error}' + : '$url answered with HTTP ${res.status}.'; + } else { + try { + final json = jsonDecode(res.body); + final ids = json is Map ? json['publications'] : null; + if (ids is! List || !ids.contains(p.publicId)) { + problem = '$url doesn\'t list ${p.publicId}.'; + } + } on FormatException { + problem = '$url isn\'t valid JSON.'; + } + } + var updated = p; + if (problem == null || p.verifiedHost != null) { + updated = await Publication.db.updateRow( + session, + p.copyWith( + verifiedHost: problem == null ? host : null, + verifiedAt: problem == null ? nowUtc() : null, + ), + columns: (t) => [t.verifiedHost, t.verifiedAt], + ); + } + return PublicationCheckResult( + ok: problem == null, + message: problem, + settings: await settingsOf(session, updated), + ); + } + + /// Sends a `publication.ping` now and reports the answer. + static Future sendTest( + Session session, + Actor actor, + String publicId, + ) async { + final p = await _own(session, actor, publicId); + final d = await PublicationWebhooks.enqueue( + session, + p, + PublicationWebhooks.envelope('publication.ping', p), + ); + final ok = await PublicationWebhooks.attempt(session, d.id!); + final after = await PublicationDelivery.db.findById(session, d.id!); + return PublicationCheckResult( + ok: ok, + message: ok + ? null + : after?.lastError ?? 'The webhook didn\'t answer with 2xx.', + settings: await settingsOf(session, p), + ); + } + + /// A ping after the webhook URL is set; failures only show under + /// *Deliveries*. + static Future _ping(Session session, Publication p) async { + final d = await PublicationWebhooks.enqueue( + session, + p, + PublicationWebhooks.envelope('publication.ping', p), + ); + await PublicationWebhooks.scheduler(session, d.id!); + } + + static Future> deliveries( + Session session, + Actor actor, + String publicId, + ) async { + final p = await _own(session, actor, publicId); + final rows = await PublicationDelivery.db.find( + session, + where: (t) => t.publicationId.equals(p.id!), + orderBy: (t) => t.createdAt.desc(), + limit: 50, + ); + return [ + for (final d in rows) + PublicationDeliveryView( + webhookId: d.webhookId, + type: d.type, + createdAt: d.createdAt, + attempts: d.attempts, + lastStatus: d.lastStatus, + lastError: d.lastError, + deliveredAt: d.deliveredAt, + failedAt: d.failedAt, + nextAttemptAt: d.nextAttemptAt, + ), + ]; + } + + /// Sends a delivery again now (same `webhook-id`). + static Future resend( + Session session, + Actor actor, + String publicId, + String webhookId, + ) async { + final p = await _own(session, actor, publicId); + final d = await PublicationDelivery.db.findFirstRow( + session, + where: (t) => + t.publicationId.equals(p.id!) & t.webhookId.equals(webhookId), + ); + if (d == null) throw Errors.notFound('Delivery'); + await PublicationDelivery.db.updateRow( + session, + d.copyWith( + deliveredAt: null, + failedAt: null, + nextAttemptAt: nowUtc(), + leaseUntil: null, + ), + columns: (t) => [ + t.deliveredAt, + t.failedAt, + t.nextAttemptAt, + t.leaseUntil, + ], + ); + await PublicationWebhooks.attempt(session, d.id!); + final after = (await PublicationDelivery.db.findById(session, d.id!))!; + return PublicationDeliveryView( + webhookId: after.webhookId, + type: after.type, + createdAt: after.createdAt, + attempts: after.attempts, + lastStatus: after.lastStatus, + lastError: after.lastError, + deliveredAt: after.deliveredAt, + failedAt: after.failedAt, + nextAttemptAt: after.nextAttemptAt, + ); + } +} diff --git a/wonky_server/lib/src/platform/publications/publication_webhooks.dart b/wonky_server/lib/src/platform/publications/publication_webhooks.dart new file mode 100644 index 00000000..097d8bc1 --- /dev/null +++ b/wonky_server/lib/src/platform/publications/publication_webhooks.dart @@ -0,0 +1,269 @@ +import 'dart:convert'; + +import 'package:serverpod/serverpod.dart'; + +import '../../generated/future_calls.dart'; + +import '../common/guarded.dart'; +import '../common/models.dart'; +import '../common/time.dart'; +import 'publication_common.dart'; +import 'publication_http.dart'; +import 'publication_keys.dart'; +import 'submission_service.dart'; + +/// The webhook outbox of publications (specs/18 §7.1, §7.2): every event +/// is stored first, then sent signed; failures are retried with the same +/// `webhook-id`. +abstract final class PublicationWebhooks { + /// Delays after the 1st … 6th failed attempt; after the 7th attempt the + /// delivery fails. + static const retryDelays = [ + Duration(minutes: 1), + Duration(minutes: 5), + Duration(minutes: 30), + Duration(hours: 2), + Duration(hours: 6), + Duration(hours: 12), + ]; + + /// How long one instance holds a delivery while sending it. + static Duration leaseDuration = const Duration(seconds: 60); + + /// At most this many deliveries are sent per sweep. + static const sweepBatch = 50; + + /// Schedules sending a delivery soon (tests replace it to send inline or + /// record). + static Future Function(Session session, int deliveryId) scheduler = + _viaFutureCall; + + static Future _viaFutureCall(Session session, int deliveryId) => session + .serverpod + .futureCalls + .callWithDelay(Duration.zero) + .publications + .deliver(deliveryId); + + /// The common fields of every body. + static Map envelope(String type, Publication p) => { + 'type': type, + 'createdAt': nowUtc().toIso8601String(), + 'publicationId': p.publicId, + }; + + /// The `submission` object of a body. + static Map submissionJson( + Session session, + Submission s, + DriveItem item, + ) => { + 'id': Publications.submissionId(s), + 'ref': s.ref, + 'status': s.status.name, + 'documentUrl': Publications.documentUrl(session, item.uuid), + }; + + /// Stores a delivery of [body]; returns the row. + static Future enqueue( + Session session, + Publication p, + Map body, { + Submission? submission, + int? sequence, + Transaction? transaction, + }) => PublicationDelivery.db.insertRow( + session, + PublicationDelivery( + publicationId: p.id!, + submissionId: submission?.id, + webhookId: 'msg_${const Uuid().v4().replaceAll('-', '')}', + type: body['type'] as String, + payload: jsonEncode(body), + sequence: sequence, + nextAttemptAt: nowUtc(), + createdAt: nowUtc(), + ), + transaction: transaction, + ); + + /// Stores a delivery and schedules sending it right away. + static Future send( + Session session, + Publication p, + Map body, { + Submission? submission, + }) async { + final d = await enqueue(session, p, body, submission: submission); + await scheduler(session, d.id!); + return d; + } + + /// Sends the delivery [id] once if it is due and not held by another + /// instance; returns whether the blog accepted it. + static Future attempt(Session session, int id) async { + final now = nowUtc(); + final claimed = await PublicationDelivery.db.updateWhere( + session, + columnValues: (t) => [t.leaseUntil(now.add(leaseDuration))], + where: (t) => + t.id.equals(id) & + t.deliveredAt.equals(null) & + t.failedAt.equals(null) & + (t.leaseUntil.equals(null) | (t.leaseUntil < now)), + ); + if (claimed.isEmpty) return false; + final d = claimed.single; + final p = await Publication.db.findById(session, d.publicationId); + if (p == null) return false; + final timestamp = now.millisecondsSinceEpoch ~/ 1000; + final secrets = [ + p.signingSecret, + if (p.previousSigningSecret != null && + (p.previousSecretUntil?.isAfter(now) ?? false)) + p.previousSigningSecret!, + ]; + final result = await PublicationHttp.instance.post( + p.webhookUrl, + headers: { + 'webhook-id': d.webhookId, + 'webhook-timestamp': '$timestamp', + 'webhook-signature': PublicationKeys.signatureHeader( + secrets: secrets, + webhookId: d.webhookId, + timestamp: timestamp, + body: d.payload, + ), + }, + body: d.payload, + ); + final attempts = d.attempts + 1; + final done = nowUtc(); + if (result.ok) { + await PublicationDelivery.db.updateRow( + session, + d.copyWith( + attempts: attempts, + lastStatus: result.status, + lastError: null, + deliveredAt: done, + nextAttemptAt: null, + leaseUntil: null, + ), + columns: _resultColumns, + ); + await _settled(session, d, delivered: true); + return true; + } + final error = result.error ?? 'HTTP ${result.status}'; + final giveUp = attempts > retryDelays.length; + await PublicationDelivery.db.updateRow( + session, + d.copyWith( + attempts: attempts, + lastStatus: result.status, + lastError: error.length > 500 ? error.substring(0, 500) : error, + failedAt: giveUp ? done : null, + nextAttemptAt: giveUp ? null : done.add(retryDelays[attempts - 1]), + leaseUntil: null, + ), + columns: _resultColumns, + ); + if (giveUp) await _settled(session, d, delivered: false); + return false; + } + + static List> _resultColumns(PublicationDeliveryTable t) => [ + t.attempts, + t.lastStatus, + t.lastError, + t.deliveredAt, + t.failedAt, + t.nextAttemptAt, + t.leaseUntil, + ]; + + /// After the last attempt of a `submission.submitted`: clears or marks the + /// submission's delivery state, when it is still the latest submit. + static Future _settled( + Session session, + PublicationDelivery d, { + required bool delivered, + }) async { + if (d.type != 'submission.submitted' || + d.submissionId == null || + d.sequence == null) { + return; + } + final latest = await SubmissionRevision.db.findFirstRow( + session, + where: (t) => t.submissionId.equals(d.submissionId!), + orderBy: (t) => t.sequence.desc(), + ); + if (latest?.sequence != d.sequence) return; + final s = await Submission.db.findById(session, d.submissionId!); + if (s == null) return; + if (delivered) { + await Submission.db.updateRow( + session, + s.copyWith(delivery: null, updatedAt: nowUtc()), + columns: (t) => [t.delivery, t.updatedAt], + ); + } else { + final back = s.status == SubmissionStatus.inReview + ? (s.statusBeforeSubmit ?? SubmissionStatus.draft) + : s.status; + await Submission.db.updateRow( + session, + s.copyWith( + delivery: SubmissionDeliveryState.failed, + status: back, + updatedAt: nowUtc(), + ), + columns: (t) => [t.delivery, t.status, t.updatedAt], + ); + } + await SubmissionService.afterDelivery( + session, + s.id!, + delivered: delivered, + submitterId: latest!.submittedById, + ); + } + + /// Sends the due deliveries (`wonky.publicationSweep`, every minute). + static Future sweep(Session session) async { + final now = nowUtc(); + final due = await PublicationDelivery.db.find( + session, + where: (t) => + (t.nextAttemptAt <= now) & + t.deliveredAt.equals(null) & + t.failedAt.equals(null) & + (t.leaseUntil.equals(null) | (t.leaseUntil < now)), + orderBy: (t) => t.nextAttemptAt, + limit: sweepBatch, + ); + var sent = 0; + for (final d in due) { + final ok = await runGuarded( + session, + 'publications.deliver ${d.webhookId}', + () => attempt(session, d.id!), + ); + if (ok ?? false) sent++; + } + return sent; + } + + /// Deliveries older than 30 days are deleted (daily). + static Future purgeOld(Session session) async { + final removed = await PublicationDelivery.db.deleteWhere( + session, + where: (t) => + (t.createdAt < nowUtc().subtract(const Duration(days: 30))) & + t.nextAttemptAt.equals(null), + ); + return removed.length; + } +} diff --git a/wonky_server/lib/src/platform/publications/submission_endpoint.dart b/wonky_server/lib/src/platform/publications/submission_endpoint.dart new file mode 100644 index 00000000..702e4a6f --- /dev/null +++ b/wonky_server/lib/src/platform/publications/submission_endpoint.dart @@ -0,0 +1,58 @@ +import 'package:serverpod/serverpod.dart'; + +import '../common/models.dart'; +import '../users/user_service.dart'; +import 'submission_service.dart'; + +/// A document's submission to a publication (specs/18 §9.2). +class SubmissionEndpoint extends Endpoint { + @override + bool get requireLogin => true; + + /// The document's submission, or null (viewer+). + Future get(Session session, UuidValue itemUuid) async => + SubmissionService.get( + session, + await UserService.actorOf(session), + itemUuid, + ); + + /// Submits the current revision (editor+); [agreed] confirms the + /// publication's terms when they changed. + Future submit( + Session session, + UuidValue itemUuid, + SubmissionValues values, + bool agreed, + ) async => SubmissionService.submit( + session, + await UserService.actorOf(session), + itemUuid, + values, + agreed: agreed, + ); + + Future withdraw(Session session, UuidValue itemUuid) async => + SubmissionService.withdraw( + session, + await UserService.actorOf(session), + itemUuid, + ); + + Future disconnect(Session session, UuidValue itemUuid) async => + SubmissionService.disconnect( + session, + await UserService.actorOf(session), + itemUuid, + ); + + /// Undoes [disconnect]. + Future reconnect( + Session session, + UuidValue itemUuid, + ) async => SubmissionService.reconnect( + session, + await UserService.actorOf(session), + itemUuid, + ); +} diff --git a/wonky_server/lib/src/platform/publications/submission_service.dart b/wonky_server/lib/src/platform/publications/submission_service.dart new file mode 100644 index 00000000..1638b58e --- /dev/null +++ b/wonky_server/lib/src/platform/publications/submission_service.dart @@ -0,0 +1,944 @@ +import 'dart:convert'; + +import 'package:serverpod/serverpod.dart'; +import 'package:wonky_core/wonky_core.dart' show Role; +import 'package:wonky_write_core/wonky_write_core.dart' as core; + +import '../../write/ot/document_store.dart'; +import '../activity/activity_service.dart'; +import '../comments/comment_service.dart'; +import '../common/actor.dart'; +import '../common/errors.dart'; +import '../common/guarded.dart'; +import '../common/models.dart'; +import '../common/time.dart'; +import '../drive/drive_events.dart'; +import '../files/file_service.dart'; +import '../notifications/notification_service.dart'; +import '../sharing/access_service.dart'; +import '../sharing/acl_events.dart'; +import '../users/user_service.dart'; +import '../versions/version_service.dart'; +import 'publication_common.dart'; +import 'publication_rules.dart'; +import 'publication_webhooks.dart'; + +/// Submissions of Write documents to publications (specs/18 §4, §5, §7): +/// submit, withdraw, disconnect, moderator access, the blog's status calls +/// and messages, and the hooks of trash and comment replies. +abstract final class SubmissionService { + static final _wonkyFile = RegExp( + r'wonky-file://([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})', + ); + + // ------------------------------------------------------------- lookups + + static Future ofItem(Session session, DriveItem item) => + Submission.db.findFirstRow( + session, + where: (t) => t.itemId.equals(item.id!), + ); + + /// The connected submission of [itemUuid] for a caller with [min]. + static Future<(Submission, Publication, DriveItem, Role)> _require( + Session session, + Actor actor, + UuidValue itemUuid, + Role min, + ) async { + final (item, role) = await AccessService.require( + session, + actor, + itemUuid, + min, + ); + final s = await ofItem(session, item); + if (s == null || s.disconnectedAt != null) { + throw Errors.notFound('Submission'); + } + final p = await Publication.db.findById(session, s.publicationId); + if (p == null) throw Errors.notFound('Publication'); + return (s, p, item, role); + } + + // --------------------------------------------------------------- views + + /// The submission of a document, or null when it has none (viewer+). + static Future get( + Session session, + Actor actor, + UuidValue itemUuid, + ) async { + final (item, _) = await AccessService.require( + session, + actor, + itemUuid, + Role.viewer, + ); + final s = await ofItem(session, item); + if (s == null || s.disconnectedAt != null) return null; + final p = await Publication.db.findById(session, s.publicationId); + if (p == null) return null; + return view(session, actor, s, p, item); + } + + static Future view( + Session session, + Actor actor, + Submission s, + Publication p, + DriveItem item, + ) async { + final revisions = await SubmissionRevision.db.find( + session, + where: (t) => t.submissionId.equals(s.id!), + orderBy: (t) => t.sequence, + ); + final users = await UserService.summaries(session, [ + for (final r in revisions) r.submittedById, + ]); + final versions = { + for (final v in await ItemVersion.db.find( + session, + where: (t) => t.id.inSet({ + for (final r in revisions) + if (r.versionId != null) r.versionId!, + }), + )) + v.id!: v, + }; + CommentThread? thread; + Comment? last; + if (s.feedbackThreadId != null) { + thread = await CommentThread.db.findById(session, s.feedbackThreadId!); + last = await Comment.db.findFirstRow( + session, + where: (t) => + t.threadId.equals(s.feedbackThreadId!) & + t.publicationId.equals(p.id!) & + t.deletedAt.equals(null), + orderBy: (t) => t.createdAt.desc(), + ); + } + final blocked = await Publications.isBlocked(session, p.id!, actor.userId); + return SubmissionView( + id: Publications.submissionId(s), + itemUuid: item.uuid, + status: s.status, + delivery: s.delivery, + publicationId: p.publicId, + publicationName: p.name, + shownHost: Publications.shownHost(p), + verified: p.verifiedHost != null, + accepting: p.enabled && !blocked, + fields: p.fields, + termsUrl: p.termsUrl, + consentNeeded: await Publications.consentNeeded( + session, + p, + actor.userId, + ), + values: s.values, + publicUrl: s.publicUrl, + feedbackThreadUuid: thread?.uuid, + lastMessage: last?.body, + lastMessageAt: last?.createdAt, + lastSubmittedRevision: revisions.isEmpty ? null : revisions.last.revision, + revisions: [ + for (final r in revisions) + SubmissionRevisionView( + sequence: r.sequence, + revision: r.revision, + submittedByName: + users[r.submittedById]?.displayName ?? 'Deleted user', + submittedAt: r.submittedAt, + versionId: versions.containsKey(r.versionId) ? r.versionId : null, + ), + ], + updatedAt: s.updatedAt, + ); + } + + // -------------------------------------------------------------- submit + + /// Submits the document's current revision (specs/18 §4.2, §7.2): names + /// a version, stores the payload, grants the moderators Commenter and + /// tries the webhook once (≤ 10 s); a failure is retried by the outbox. + static Future submit( + Session session, + Actor actor, + UuidValue itemUuid, + SubmissionValues values, { + bool agreed = false, + }) async { + final (s, p, item, _) = await _require( + session, + actor, + itemUuid, + Role.editor, + ); + if (!p.enabled) { + throw Errors.forbidden('${p.name} isn\'t accepting stories right now.'); + } + if (await Publications.isBlocked(session, p.id!, actor.userId)) { + throw Errors.forbidden('${p.name} isn\'t accepting stories from you.'); + } + if (!PublicationRules.maySubmit(s.status)) { + throw Errors.forbidden('${p.name} declined this story.'); + } + if (await Publications.consentNeeded(session, p, actor.userId)) { + if (!agreed) { + throw Errors.invalid('Agree to send your story to ${p.name} first.'); + } + await Publications.recordConsent(session, p, actor.userId); + } + final clean = PublicationRules.values(values, p.fields); + await Publications.checkLimit( + Publications.submitLimiter, + '${p.id}:${actor.userId}', + "You've sent a lot to ${p.name} today. Try again tomorrow.", + ); + final doc = await DocumentStore.requireByItem(session, item.id!); + final version = await VersionService.capture( + session, + item, + kind: VersionKind.named, + name: 'Submitted to ${p.name}', + createdById: actor.userId, + ); + final revision = version.revision ?? doc.headRevision; + final content = await DocumentStore.contentAt( + session, + (await DocumentStore.requireByItem(session, item.id!)), + revision, + ); + var markdown = const core.MarkdownCodec().exportMarkdown( + content, + view: core.SuggestionViewMode.original, + ); + final assets = await _assets(session, actor, markdown); + markdown = markdown.replaceAllMapped(_wonkyFile, (m) { + final uuid = UuidValue.withValidation(m[1]!.toLowerCase()); + return assets.containsKey(uuid) + ? Publications.assetUrl(session, uuid) + : m[0]!; + }); + if (utf8.encode(markdown).length > PublicationRules.maxMarkdownBytes) { + throw Errors.tooLarge('This story is too long to submit (over 5 MB).'); + } + final cover = + clean.coverImage != null && assets.containsKey(clean.coverImage) + ? clean.coverImage + : null; + final stored = clean.copyWith(coverImage: cover); + final submitter = (await UserService.summaries(session, [ + actor.userId, + ]))[actor.userId]; + final profile = await UserProfile.db.findById(session, actor.userId); + final now = nowUtc(); + final last = await SubmissionRevision.db.findFirstRow( + session, + where: (t) => t.submissionId.equals(s.id!), + orderBy: (t) => t.sequence.desc(), + ); + final sequence = (last?.sequence ?? 0) + 1; + final submitted = s.copyWith( + status: SubmissionStatus.inReview, + statusBeforeSubmit: s.status, + delivery: SubmissionDeliveryState.pending, + values: stored, + updatedAt: now, + ); + final body = { + ...PublicationWebhooks.envelope('submission.submitted', p), + 'submission': PublicationWebhooks.submissionJson( + session, + submitted, + item, + ), + 'sequence': sequence, + 'revision': revision, + 'fields': { + 'title': stored.title, + 'summary': stored.summary, + 'tags': stored.tags, + 'coverImage': cover == null ? null : Publications.assetId(cover), + 'authorBio': stored.authorBio, + 'note': stored.note, + }, + 'markdown': markdown, + 'assets': [ + for (final f in assets.values) + { + 'id': Publications.assetId(f.fileUuid), + 'name': f.fileName, + 'type': f.mimeType, + 'bytes': f.sizeBytes, + 'url': Publications.assetUrl(session, f.fileUuid), + }, + ], + 'submittedBy': { + 'name': submitter?.displayName ?? 'Someone', + 'wonkyUserId': profile?.authUserId.uuid, + }, + }; + final delivery = await session.db.transaction((tx) async { + await SubmissionRevision.db.insertRow( + session, + SubmissionRevision( + submissionId: s.id!, + sequence: sequence, + revision: revision, + versionId: version.id, + values: stored, + payload: jsonEncode(body), + submittedById: actor.userId, + submittedAt: now, + ), + transaction: tx, + ); + final known = { + for (final a in await SubmissionAsset.db.find( + session, + where: (t) => t.submissionId.equals(s.id!), + transaction: tx, + )) + a.fileUuid, + }; + final fresh = [ + for (final u in assets.keys) + if (!known.contains(u)) + SubmissionAsset(submissionId: s.id!, fileUuid: u), + ]; + if (fresh.isNotEmpty) { + await SubmissionAsset.db.insert(session, fresh, transaction: tx); + } + await Submission.db.updateRow( + session, + submitted, + columns: (t) => [ + t.status, + t.statusBeforeSubmit, + t.delivery, + t.values, + t.updatedAt, + ], + transaction: tx, + ); + return PublicationWebhooks.enqueue( + session, + p, + body, + submission: s, + sequence: sequence, + transaction: tx, + ); + }); + await syncModerators(session, submitted, p, item); + await ActivityService.log( + session, + item.id!, + actor, + ActivityType.submission, + summary: {'publication': p.name, 'action': 'submitted'}, + ); + // One try while the contributor waits; the outbox retries the rest. + await runGuarded( + session, + 'publications.submit ${delivery.webhookId}', + () => PublicationWebhooks.attempt(session, delivery.id!), + ); + await _changed(session, item); + final fresh = await Submission.db.findById(session, s.id!); + return view(session, actor, fresh!, p, item); + } + + /// The images of [markdown] the submitter may read, by file uuid. + static Future> _assets( + Session session, + Actor actor, + String markdown, + ) async { + final result = {}; + for (final m in _wonkyFile.allMatches(markdown)) { + final uuid = UuidValue.withValidation(m[1]!.toLowerCase()); + if (result.containsKey(uuid)) continue; + final file = await FileService.byUuid(session, uuid); + if (file == null || + file.status != StoredFileStatus.ready || + !await FileService.canRead(session, actor, file)) { + continue; + } + result[uuid] = file; + } + return result; + } + + /// After a submit's delivery settled (from the outbox): drive signal, and + /// on failure the moderators' access follows the restored status and the + /// submitter is told (specs/18 §7.2). + static Future afterDelivery( + Session session, + int submissionId, { + required bool delivered, + required int submitterId, + }) async { + final s = await Submission.db.findById(session, submissionId); + if (s == null) return; + final item = await DriveItem.db.findById(session, s.itemId); + final p = await Publication.db.findById(session, s.publicationId); + if (item == null || p == null) return; + if (!delivered) { + await syncModerators(session, s, p, item); + await NotificationService.notify( + session, + userId: submitterId, + kind: NotificationKind.submission, + item: item, + payload: { + 'publication': p.name, + 'event': 'deliveryFailed', + 'excerpt': "${p.name} couldn't receive your submission.", + }, + ); + } + await _changed(session, item); + } + + // --------------------------------------------- withdraw and disconnect + + static Future withdraw( + Session session, + Actor actor, + UuidValue itemUuid, + ) async { + final (s, p, item, _) = await _require( + session, + actor, + itemUuid, + Role.editor, + ); + if (!PublicationRules.isOpen(s.status)) { + throw Errors.conflict('This story isn\'t in review.'); + } + final updated = await _withdraw(session, actor, s, p, item, 'author'); + return view(session, actor, updated, p, item); + } + + static Future _withdraw( + Session session, + Actor? actor, + Submission s, + Publication p, + DriveItem item, + String reason, + ) async { + final updated = s.copyWith( + status: SubmissionStatus.withdrawn, + delivery: null, + updatedAt: nowUtc(), + ); + await Submission.db.updateRow( + session, + updated, + columns: (t) => [t.status, t.delivery, t.updatedAt], + ); + await syncModerators(session, updated, p, item); + await PublicationWebhooks.send(session, p, { + ...PublicationWebhooks.envelope('submission.withdrawn', p), + 'submission': PublicationWebhooks.submissionJson(session, updated, item), + 'reason': reason, + }, submission: updated); + await ActivityService.log( + session, + item.id!, + actor, + ActivityType.submission, + summary: {'publication': p.name, 'action': 'withdrawn'}, + ); + await _changed(session, item); + return updated; + } + + /// Disconnects the document (specs/18 §4.5); undone by [reconnect]. + static Future disconnect( + Session session, + Actor actor, + UuidValue itemUuid, + ) async { + final (s, p, item, _) = await _require( + session, + actor, + itemUuid, + Role.editor, + ); + if (PublicationRules.isOpen(s.status)) { + throw Errors.conflict('Withdraw the story before you disconnect it.'); + } + final updated = s.copyWith(disconnectedAt: nowUtc(), updatedAt: nowUtc()); + await Submission.db.updateRow( + session, + updated, + columns: (t) => [t.disconnectedAt, t.updatedAt], + ); + await syncModerators(session, updated, p, item); + if (s.status != SubmissionStatus.draft) { + await PublicationWebhooks.send(session, p, { + ...PublicationWebhooks.envelope('submission.disconnected', p), + 'submission': PublicationWebhooks.submissionJson( + session, + updated, + item, + ), + }, submission: updated); + } + await ActivityService.log( + session, + item.id!, + actor, + ActivityType.submission, + summary: {'publication': p.name, 'action': 'disconnected'}, + ); + await _changed(session, item); + } + + /// Undoes [disconnect]. + static Future reconnect( + Session session, + Actor actor, + UuidValue itemUuid, + ) async { + final (item, _) = await AccessService.require( + session, + actor, + itemUuid, + Role.editor, + ); + final s = await ofItem(session, item); + if (s == null) throw Errors.notFound('Submission'); + final p = await Publication.db.findById(session, s.publicationId); + if (p == null) throw Errors.notFound('Publication'); + if (s.disconnectedAt == null) return view(session, actor, s, p, item); + final updated = s.copyWith(disconnectedAt: null, updatedAt: nowUtc()); + await Submission.db.updateRow( + session, + updated, + columns: (t) => [t.disconnectedAt, t.updatedAt], + ); + await syncModerators(session, updated, p, item); + await ActivityService.log( + session, + item.id!, + actor, + ActivityType.submission, + summary: {'publication': p.name, 'action': 'reconnected'}, + ); + await _changed(session, item); + return view(session, actor, updated, p, item); + } + + // --------------------------------------------------- moderator access + + /// Brings the moderators' Commenter grants of [item] in line with the + /// submission (specs/18 §5.1). + static Future syncModerators( + Session session, + Submission s, + Publication p, + DriveItem item, + ) async { + final wanted = {}; + if (s.disconnectedAt == null && + item.trashedAt == null && + PublicationRules.moderatorsHaveAccess(s.status)) { + final mods = await PublicationModerator.db.find( + session, + where: (t) => t.publicationId.equals(p.id!) & t.userId.notEquals(null), + ); + wanted.addAll([ + for (final m in mods) + if (m.userId != item.ownerId) m.userId!, + ]); + } + final existing = await DriveItemPermission.db.find( + session, + where: (t) => + t.itemId.equals(item.id!) & t.viaPublicationId.equals(p.id!), + ); + final have = {for (final g in existing) g.userId}; + final changed = {}; + final remove = [ + for (final g in existing) + if (!wanted.contains(g.userId)) g, + ]; + if (remove.isNotEmpty) { + await DriveItemPermission.db.delete(session, remove); + changed.addAll([for (final g in remove) g.userId!]); + } + final missing = wanted.difference(have); + if (missing.isNotEmpty) { + final direct = { + for (final g in await DriveItemPermission.db.find( + session, + where: (t) => + t.itemId.equals(item.id!) & + t.inheritedFromId.equals(null) & + t.invitedEmail.equals(null) & + t.userId.inSet(missing), + )) + g.userId, + }; + final now = nowUtc(); + final rows = [ + for (final u in missing) + if (!direct.contains(u)) + DriveItemPermission( + itemId: item.id!, + userId: u, + role: AccessRole.commenter, + grantedById: s.createdById, + grantedAt: now, + viaPublicationId: p.id, + ), + ]; + if (rows.isNotEmpty) { + await DriveItemPermission.db.insert(session, rows); + changed.addAll([for (final r in rows) r.userId!]); + } + } + if (changed.isNotEmpty) { + await AclEvents.changed( + session, + item, + affectedUsers: changed, + kind: DriveChangeKind.shared, + ); + } + } + + /// Grants a newly linked moderator access to the publication's open + /// submissions (after the owner adds them or they sign up). + static Future syncPublication(Session session, Publication p) async { + final subs = await Submission.db.find( + session, + where: (t) => + t.publicationId.equals(p.id!) & t.disconnectedAt.equals(null), + ); + for (final s in subs) { + final item = await DriveItem.db.findById(session, s.itemId); + if (item == null) continue; + await runGuarded( + session, + 'publications.syncModerators ${s.id}', + () => syncModerators(session, s, p, item), + ); + } + } + + // ------------------------------------------------------ blog → Wonky + + /// The blog's status call (specs/18 §7.3). + static Future setStatus( + Session session, + Publication p, + Submission s, { + required SubmissionStatus status, + String? message, + String? publicUrl, + }) async { + if (s.disconnectedAt != null || s.status == SubmissionStatus.withdrawn) { + throw const PublicationGone(); + } + if (!PublicationRules.blogMayMove(s.status, status)) { + throw PublicationTransitionError(s.status, status); + } + String? url = s.publicUrl; + if (status == SubmissionStatus.published) { + if (publicUrl == null || publicUrl.isEmpty) { + throw Errors.invalid('Set publicUrl when the status is published.'); + } + url = PublicationRules.httpsUrl(publicUrl, 'publicUrl').toString(); + } + final item = await DriveItem.db.findById(session, s.itemId); + if (item == null) throw Errors.notFound('Submission'); + final updated = s.copyWith( + status: status, + publicUrl: url, + updatedAt: nowUtc(), + ); + await Submission.db.updateRow( + session, + updated, + columns: (t) => [t.status, t.publicUrl, t.updatedAt], + ); + final heading = switch (status) { + SubmissionStatus.inReview => '**In review**', + SubmissionStatus.changesRequested => '**Changes requested**', + SubmissionStatus.declined => '**Declined**', + SubmissionStatus.published => '**Published**: $url', + _ => '', + }; + final text = [ + if (status != s.status || status == SubmissionStatus.published) heading, + if (message != null && message.trim().isNotEmpty) message.trim(), + ].join('\n\n'); + if (text.isNotEmpty) await _post(session, p, updated, item, text); + await syncModerators(session, updated, p, item); + if (status != s.status) { + await ActivityService.log( + session, + item.id!, + null, + ActivityType.submission, + summary: { + 'publication': p.name, + 'action': 'status', + 'status': status.name, + }, + ); + } + await _notifyEditors(session, p, item, { + 'event': 'status', + 'status': status.name, + 'excerpt': _excerpt(message) ?? _statusText(p, status), + }); + await _changed(session, item); + return updated; + } + + /// The blog's message without a status change (specs/18 §7.3). + static Future postMessage( + Session session, + Publication p, + Submission s, + String body, + ) async { + if (s.disconnectedAt != null || s.status == SubmissionStatus.withdrawn) { + throw const PublicationGone(); + } + final item = await DriveItem.db.findById(session, s.itemId); + if (item == null) throw Errors.notFound('Submission'); + await _post(session, p, s, item, body.trim()); + await _notifyEditors(session, p, item, { + 'event': 'message', + 'excerpt': _excerpt(body), + }); + await _changed(session, item); + } + + static String _statusText(Publication p, SubmissionStatus status) => + switch (status) { + SubmissionStatus.inReview => '${p.name} is reviewing your story.', + SubmissionStatus.changesRequested => + '${p.name} asked for changes to your story.', + SubmissionStatus.declined => '${p.name} declined your story.', + SubmissionStatus.published => '${p.name} published your story.', + _ => '${p.name} updated your story.', + }; + + static String? _excerpt(String? s) { + final t = s?.trim(); + if (t == null || t.isEmpty) return null; + return t.length <= 200 ? t : '${t.substring(0, 199)}…'; + } + + /// Adds a message of the publication to the feedback thread, creating or + /// reopening it (specs/18 §5.2). + static Future _post( + Session session, + Publication p, + Submission s, + DriveItem item, + String body, + ) async { + final now = nowUtc(); + CommentThread? thread = s.feedbackThreadId == null + ? null + : await CommentThread.db.findById(session, s.feedbackThreadId!); + var kind = CommentEventKind.threadUpdated; + await session.db.transaction((tx) async { + if (thread == null) { + thread = await CommentThread.db.insertRow( + session, + CommentThread( + uuid: const Uuid().v7obj(), + itemId: item.id!, + anchorKind: CommentAnchorKind.document, + anchorJson: '{"v":1}', + status: CommentStatus.open, + createdById: s.createdById, + createdAt: now, + ), + transaction: tx, + ); + kind = CommentEventKind.threadCreated; + await Submission.db.updateRow( + session, + s.copyWith(feedbackThreadId: thread!.id), + columns: (t) => [t.feedbackThreadId], + transaction: tx, + ); + } else if (thread!.status != CommentStatus.open) { + thread = await CommentThread.db.updateRow( + session, + thread!.copyWith( + status: CommentStatus.open, + resolvedAt: null, + resolvedById: null, + updatedAt: now, + ), + columns: (t) => [t.status, t.resolvedAt, t.resolvedById, t.updatedAt], + transaction: tx, + ); + } + await Comment.db.insertRow( + session, + Comment( + threadId: thread!.id!, + uuid: const Uuid().v7obj(), + authorKind: ActorKind.system, + body: body.length > PublicationRules.maxMessageLength + ? body.substring(0, PublicationRules.maxMessageLength) + : body, + mentions: const [], + createdAt: now, + publicationId: p.id, + ), + transaction: tx, + ); + }); + await CommentService.signal(session, item, kind, thread!.uuid); + } + + static Future _notifyEditors( + Session session, + Publication p, + DriveItem item, + Map payload, + ) async { + for (final userId in await Publications.editorsOf(session, item)) { + await NotificationService.notify( + session, + userId: userId, + kind: NotificationKind.submission, + item: item, + payload: {'publication': p.name, ...payload}, + ); + } + } + + // ---------------------------------------------------------------- hooks + + /// Withdraws open submissions of trashed documents (specs/18 §4.5). + static Future onTrashed(Session session, List nodes) async { + final docs = [ + for (final n in nodes) + if (n.kind == DriveItemKind.document) n, + ]; + if (docs.isEmpty) return; + final subs = await Submission.db.find( + session, + where: (t) => + t.itemId.inSet({for (final d in docs) d.id!}) & + t.disconnectedAt.equals(null), + ); + for (final s in subs) { + final item = await DriveItem.db.findById(session, s.itemId); + final p = await Publication.db.findById(session, s.publicationId); + if (item == null || p == null) continue; + if (PublicationRules.isOpen(s.status)) { + await _withdraw(session, null, s, p, item, 'trashed'); + } else { + await syncModerators(session, s, p, item); + } + } + } + + /// Moderator access returns with a restored document. + static Future onRestored(Session session, List nodes) async { + final subs = await Submission.db.find( + session, + where: (t) => + t.itemId.inSet({for (final n in nodes) n.id!}) & + t.disconnectedAt.equals(null), + ); + for (final s in subs) { + final item = await DriveItem.db.findById(session, s.itemId); + final p = await Publication.db.findById(session, s.publicationId); + if (item == null || p == null) continue; + await syncModerators(session, s, p, item); + } + } + + /// Sends `comment.created` for replies in a feedback thread (specs/18 + /// §5.2). + static Future onReply( + Session session, + CommentThread thread, + Actor actor, { + required String body, + UuidValue? commentUuid, + }) async { + final s = await Submission.db.findFirstRow( + session, + where: (t) => + t.feedbackThreadId.equals(thread.id!) & t.disconnectedAt.equals(null), + ); + if (s == null) return; + final p = await Publication.db.findById(session, s.publicationId); + final item = await DriveItem.db.findById(session, s.itemId); + if (p == null || item == null) return; + final author = (await UserService.summaries(session, [ + actor.userId, + ]))[actor.userId]; + final profile = await UserProfile.db.findById(session, actor.userId); + final isModerator = + await PublicationModerator.db.findFirstRow( + session, + where: (t) => + t.publicationId.equals(p.id!) & t.userId.equals(actor.userId), + ) != + null; + await PublicationWebhooks.send(session, p, { + ...PublicationWebhooks.envelope('comment.created', p), + 'submission': PublicationWebhooks.submissionJson(session, s, item), + 'comment': { + 'id': (commentUuid ?? const Uuid().v7obj()).uuid, + 'body': body, + 'author': { + 'name': author?.displayName ?? 'Someone', + 'wonkyUserId': profile?.authUserId.uuid, + 'isModerator': isModerator, + }, + }, + }, submission: s); + } + + /// After a publication was deleted: the moderators' grants went with it. + static Future changedAfterDelete( + Session session, + DriveItem item, + ) async { + await AclEvents.changed(session, item, kind: DriveChangeKind.shared); + await _changed(session, item); + } + + /// Tells open editors (and Drive) that the submission changed. + static Future _changed(Session session, DriveItem item) => + DriveEvents.notify(session, item, DriveChangeKind.updated); +} + +/// The submission was withdrawn or disconnected (`410 gone`). +class PublicationGone implements Exception { + const PublicationGone(); +} + +/// A status change the blog may not make (`409 invalidTransition`). +class PublicationTransitionError implements Exception { + const PublicationTransitionError(this.from, this.to); + final SubmissionStatus from; + final SubmissionStatus to; + + String get message => + 'A submission that is ${from.name} can\'t be set to ${to.name}.'; +} diff --git a/wonky_server/lib/src/platform/sharing/drive_item_permission.spy.yaml b/wonky_server/lib/src/platform/sharing/drive_item_permission.spy.yaml index 5c2e0760..c5075131 100644 --- a/wonky_server/lib/src/platform/sharing/drive_item_permission.spy.yaml +++ b/wonky_server/lib/src/platform/sharing/drive_item_permission.spy.yaml @@ -13,6 +13,8 @@ fields: grantedById: int grantedAt: DateTime expiresAt: DateTime? + ### (M14) Moderator grant of a submission (specs/18 §5.1); removed with it. + viaPublicationId: int?, relation(parent=publication, onDelete=Cascade) indexes: perm_item_user_idx: fields: itemId, userId, inheritedFromId, invitedEmail diff --git a/wonky_server/lib/src/platform/sharing/permission_view.spy.yaml b/wonky_server/lib/src/platform/sharing/permission_view.spy.yaml index 43380b81..e2be9754 100644 --- a/wonky_server/lib/src/platform/sharing/permission_view.spy.yaml +++ b/wonky_server/lib/src/platform/sharing/permission_view.spy.yaml @@ -9,3 +9,5 @@ fields: inheritedFromName: String? grantedAt: DateTime expiresAt: DateTime? + ### (M14) The publication a moderator grant comes from (specs/18 §5.1). + viaPublication: String? diff --git a/wonky_server/lib/src/platform/sharing/sharing_service.dart b/wonky_server/lib/src/platform/sharing/sharing_service.dart index 4f6897f5..f7775182 100644 --- a/wonky_server/lib/src/platform/sharing/sharing_service.dart +++ b/wonky_server/lib/src/platform/sharing/sharing_service.dart @@ -26,6 +26,7 @@ abstract final class SharingService { t.grantedById, t.grantedAt, t.expiresAt, + t.viaPublicationId, ]; static final _random = Random.secure(); @@ -129,6 +130,17 @@ abstract final class SharingService { best[key] = g; } } + // (M14) Moderator grants show the publication's name (specs/18 §5.1). + final publications = { + for (final p in await Publication.db.find( + session, + where: (t) => t.id.inSet({ + for (final g in best.values) + if (g.viaPublicationId != null) g.viaPublicationId!, + }), + )) + p.id!: p.name, + }; final permissions = [ for (final g in best.values) PermissionView( @@ -143,6 +155,9 @@ abstract final class SharingService { : sourceById[g.inheritedFromId]?.name, grantedAt: g.grantedAt, expiresAt: g.expiresAt, + viaPublication: g.viaPublicationId == null + ? null + : publications[g.viaPublicationId], ), ]..sort((a, b) => b.role.index.compareTo(a.role.index)); final link = await ShareLink.db.findFirstRow( @@ -282,6 +297,8 @@ abstract final class SharingService { grantedById: actor.userId, grantedAt: now, expiresAt: expiresAt, + // A moderator grant shared directly becomes a direct grant. + viaPublicationId: null, ), columns: _grantColumns, transaction: tx, @@ -391,6 +408,7 @@ abstract final class SharingService { grantedById: actor.userId, grantedAt: nowUtc(), expiresAt: expiresAt, + viaPublicationId: null, ), columns: _grantColumns, ); diff --git a/wonky_server/lib/src/platform/users/user_service.dart b/wonky_server/lib/src/platform/users/user_service.dart index f5eea851..0505ef74 100644 --- a/wonky_server/lib/src/platform/users/user_service.dart +++ b/wonky_server/lib/src/platform/users/user_service.dart @@ -164,6 +164,14 @@ abstract final class UserService { t.invitedEmail.equals(normalizedEmail) & t.userId.equals(null), transaction: tx, ); + // Pending publication moderators (specs/18 §5.1); their access to + // open submissions follows with the next submit or status change. + await PublicationModerator.db.updateWhere( + session, + columnValues: (t) => [t.userId(profile.id!)], + where: (t) => t.email.equals(normalizedEmail) & t.userId.equals(null), + transaction: tx, + ); return profile; } diff --git a/wonky_server/lib/src/web/routes/publication_api_route.dart b/wonky_server/lib/src/web/routes/publication_api_route.dart new file mode 100644 index 00000000..7bb259b4 --- /dev/null +++ b/wonky_server/lib/src/web/routes/publication_api_route.dart @@ -0,0 +1,107 @@ +// Named parameters can't initialize private fields directly. +// ignore_for_file: prefer_initializing_formals + +import 'dart:convert'; + +import 'package:serverpod/serverpod.dart'; + +import '../../platform/publications/publication_api.dart'; + +/// `/api/pub/v1/**` (specs/18 §7.3): the API blogs call with their +/// publication's API key (`Authorization: Bearer wpk_…`). Runs on an +/// internal session (the bearer token must not reach the app's JWT +/// handler, like `/mcp`); the key is checked from the headers before the +/// body is read. +class PublicationApiRoute extends Route { + PublicationApiRoute({Serverpod? pod}) + : _pod = pod, + super(methods: {Method.get, Method.post, Method.delete}); + + final Serverpod? _pod; + + static const prefix = '/api/pub/v1/'; + + @override + Future call(Request req) async { + final session = await (_pod ?? Serverpod.instance).createSession( + enableLogging: false, + ); + try { + return await handleCall(session, req); + } finally { + await session.close(); + } + } + + @override + Future handleCall(Session session, Request request) async { + final path = request.url.path; + if (!path.startsWith(prefix)) return _json(PublicationApi.notFound()); + final segments = path + .substring(prefix.length) + .split('/') + .where((s) => s.isNotEmpty) + .toList(); + final auth = await PublicationApi.authenticate( + session, + authorization: request.headers['authorization']?.join(', '), + declaredLength: request.body.contentLength, + ); + if (auth.refused case final refused?) return _json(refused); + String body = ''; + if (request.method == Method.post) { + try { + body = await request.readAsString( + maxLength: PublicationApi.maxBodyBytes, + ); + } on MaxBodySizeExceeded { + return _json( + PublicationApiResult.error(413, 'tooLarge', 'The body is too large.'), + ); + } + } + final result = await PublicationApi.handle( + session, + auth.publication!, + method: request.method.name.toUpperCase(), + segments: segments, + query: request.url.queryParameters, + body: body, + ); + if (result.stream case final stream?) { + return Response( + 200, + headers: Headers.build((h) { + for (final e in result.headers.entries) { + h[e.key] = [e.value]; + } + }), + body: Body.fromDataStream( + stream, + mimeType: _mime(result.contentType), + contentLength: result.contentLength, + ), + ); + } + return _json(result); + } + + static MimeType _mime(String? type) { + try { + return MimeType.parse(type ?? 'application/octet-stream'); + } on Object { + return MimeType.octetStream; + } + } + + static Response _json(PublicationApiResult r) => Response( + r.status, + headers: Headers.build((h) { + h['cache-control'] = ['no-store']; + for (final e in r.headers.entries) { + h[e.key] = [e.value]; + } + }), + body: Body.fromString(jsonEncode(r.json ?? {}), mimeType: MimeType.json), + ); +} diff --git a/wonky_server/migrations/20261020084059086-publications/definition.json b/wonky_server/migrations/20261020084059086-publications/definition.json new file mode 100644 index 00000000..ce3fd8ce --- /dev/null +++ b/wonky_server/migrations/20261020084059086-publications/definition.json @@ -0,0 +1,19781 @@ +{ + "__className__": "serverpod.DatabaseDefinition", + "schemaVersion": 2, + "moduleName": "wonky", + "tables": [ + { + "__className__": "serverpod.TableDefinition", + "name": "access_request", + "dartName": "AccessRequest", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requesterId", + "fieldName": "requesterId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requestedRole", + "fieldName": "requestedRole", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:AccessRole" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "message", + "fieldName": "message", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "handledAt", + "fieldName": "handledAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "handledById", + "fieldName": "handledById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outcome", + "fieldName": "outcome", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:AccessRequestOutcome?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "access_request_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "access_request_fk_1", + "columns": [ + "requesterId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "access_request_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "handledAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "activity_event", + "dartName": "ActivityEvent", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorId", + "fieldName": "actorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "type", + "fieldName": "type", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActivityType" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "summary", + "fieldName": "summary", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "activity_event_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "activity_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "at" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_function_cache", + "dartName": "AiFunctionCache", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "model", + "fieldName": "model", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hits", + "fieldName": "hits", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_function_cache_key_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "key" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_function_cache_sheet_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetUuid" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_preview_record", + "dartName": "AiPreviewRecord", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previewId", + "fieldName": "previewId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previewJson", + "fieldName": "previewJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changesJson", + "fieldName": "changesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_preview_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "previewId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_preview_expires_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_usage", + "dartName": "AiUsage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "model", + "fieldName": "model", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feature", + "fieldName": "feature", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inputTokens", + "fieldName": "inputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outputTokens", + "fieldName": "outputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cacheReadTokens", + "fieldName": "cacheReadTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cacheWriteTokens", + "fieldName": "cacheWriteTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ai_usage_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_usage_user_at_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "at" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_user_key", + "dartName": "AiUserKey", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "provider", + "fieldName": "provider", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:AiProvider" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKey", + "fieldName": "apiKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ai_user_key_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_user_key_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_user_setting", + "dartName": "AiUserSetting", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "quality", + "fieldName": "quality", + "columnType": 0, + "isNullable": false, + "columnDefault": "'best'", + "dartType": "protocol:AiQuality" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ai_user_setting_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_user_setting_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "assistant_message", + "dartName": "AssistantMessage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "threadId", + "fieldName": "threadId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "role", + "fieldName": "role", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentJson", + "fieldName": "contentJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayText", + "fieldName": "displayText", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toolCallsJson", + "fieldName": "toolCallsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "visible", + "fieldName": "visible", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "replay", + "fieldName": "replay", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runId", + "fieldName": "runId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stopReason", + "fieldName": "stopReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "assistant_message_fk_0", + "columns": [ + "threadId" + ], + "referenceTable": "assistant_thread", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "assistant_message_thread_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "threadId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "assistant_thread", + "dartName": "AssistantThread", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextRevision", + "fieldName": "contextRevision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextMarkdown", + "fieldName": "contextMarkdown", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "assistant_thread_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "assistant_thread_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "assistant_thread_user_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "updatedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "banding", + "dartName": "Banding", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "styleJson", + "fieldName": "styleJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "banding_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "banding_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "banding_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "basic_filter", + "dartName": "BasicFilter", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "criteriaJson", + "fieldName": "criteriaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortJson", + "fieldName": "sortJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "basic_filter_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "basic_filter_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "basic_filter_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_ai_usage", + "dartName": "BoardAiUsage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "day", + "fieldName": "day", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "provider", + "fieldName": "provider", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "model", + "fieldName": "model", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feature", + "fieldName": "feature", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requests", + "fieldName": "requests", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inputTokens", + "fieldName": "inputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outputTokens", + "fieldName": "outputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_ai_usage_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "provider" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "model" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "feature" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_bundle_suggestion", + "dartName": "BoardBundleSuggestion", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rationale", + "fieldName": "rationale", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "area", + "fieldName": "area", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:BoardArea?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postIds", + "fieldName": "postIds", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "state", + "fieldName": "state", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_comment", + "dartName": "BoardComment", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postId", + "fieldName": "postId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "taskId", + "fieldName": "taskId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "body", + "fieldName": "body", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "systemEvent", + "fieldName": "systemEvent", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderation", + "fieldName": "moderation", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardModeration" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderationReason", + "fieldName": "moderationReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "needsCheck", + "fieldName": "needsCheck", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedAt", + "fieldName": "editedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "removedAt", + "fieldName": "removedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_comment_fk_0", + "columns": [ + "postId" + ], + "referenceTable": "board_post", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_comment_fk_1", + "columns": [ + "taskId" + ], + "referenceTable": "board_task", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_comment_fk_2", + "columns": [ + "authorId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_comment_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_comment_post_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_comment_task_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "taskId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_flag", + "dartName": "BoardFlag", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postId", + "fieldName": "postId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "commentId", + "fieldName": "commentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reason", + "fieldName": "reason", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardFlagReason" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "note", + "fieldName": "note", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_flag_fk_0", + "columns": [ + "postId" + ], + "referenceTable": "board_post", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_flag_fk_1", + "columns": [ + "commentId" + ], + "referenceTable": "board_comment", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_flag_fk_2", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_flag_post_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_flag_comment_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "commentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_github_delivery", + "dartName": "BoardGithubDelivery", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deliveryId", + "fieldName": "deliveryId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "event", + "fieldName": "event", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "receivedAt", + "fieldName": "receivedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "processedAt", + "fieldName": "processedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_github_delivery_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deliveryId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_moderation_log", + "dartName": "BoardModerationLog", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "adminId", + "fieldName": "adminId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "action", + "fieldName": "action", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "targetKind", + "fieldName": "targetKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardTargetKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "targetId", + "fieldName": "targetId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "beforeJson", + "fieldName": "beforeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "afterJson", + "fieldName": "afterJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reason", + "fieldName": "reason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_moderation_log_target_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "targetKind" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "targetId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_post", + "dartName": "BoardPost", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardPostKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reportedKind", + "fieldName": "reportedKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardPostKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "area", + "fieldName": "area", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:BoardArea?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "size", + "fieldName": "size", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:BoardSize?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "aiLabels", + "fieldName": "aiLabels", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "body", + "fieldName": "body", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextJson", + "fieldName": "contextJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appHint", + "fieldName": "appHint", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "screenshotFileId", + "fieldName": "screenshotFileId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardPostStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderation", + "fieldName": "moderation", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardModeration" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderationReason", + "fieldName": "moderationReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "needsCheck", + "fieldName": "needsCheck", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedByModerator", + "fieldName": "editedByModerator", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triageState", + "fieldName": "triageState", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardTriageState" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triageJson", + "fieldName": "triageJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triageAttempts", + "fieldName": "triageAttempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "suggestedTitle", + "fieldName": "suggestedTitle", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "summary", + "fieldName": "summary", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duplicateOfId", + "fieldName": "duplicateOfId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "possibleDuplicateOfId", + "fieldName": "possibleDuplicateOfId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duplicateHintDismissed", + "fieldName": "duplicateHintDismissed", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "declineReason", + "fieldName": "declineReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "taskId", + "fieldName": "taskId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "score", + "fieldName": "score", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "voteCount", + "fieldName": "voteCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "commentCount", + "fieldName": "commentCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "flagCount", + "fieldName": "flagCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedAt", + "fieldName": "editedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "removedAt", + "fieldName": "removedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_post_fk_0", + "columns": [ + "authorId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_post_fk_1", + "columns": [ + "screenshotFileId" + ], + "referenceTable": "stored_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_post_fk_2", + "columns": [ + "taskId" + ], + "referenceTable": "board_task", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_post_list_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "moderation" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "kind" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "score" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_post_author_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "authorId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_post_task_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "taskId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_pull_request", + "dartName": "BoardPullRequest", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prNumber", + "fieldName": "prNumber", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "taskId", + "fieldName": "taskId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorLogin", + "fieldName": "authorLogin", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "headSha", + "fieldName": "headSha", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "state", + "fieldName": "state", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateState", + "fieldName": "gateState", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateReason", + "fieldName": "gateReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateFirstFailedAt", + "fieldName": "gateFirstFailedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateCommentId", + "fieldName": "gateCommentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewCommentId", + "fieldName": "reviewCommentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastReviewSha", + "fieldName": "lastReviewSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastReviewJson", + "fieldName": "lastReviewJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastReviewAt", + "fieldName": "lastReviewAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewDay", + "fieldName": "reviewDay", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewCount", + "fieldName": "reviewCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mergeCommitSha", + "fieldName": "mergeCommitSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewPendingSha", + "fieldName": "reviewPendingSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewDueAt", + "fieldName": "reviewDueAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_pull_request_fk_0", + "columns": [ + "taskId" + ], + "referenceTable": "board_task", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_pull_request_number_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "prNumber" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_task", + "dartName": "BoardTask", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "area", + "fieldName": "area", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardArea" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "size", + "fieldName": "size", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardSize" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardTaskStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptBody", + "fieldName": "promptBody", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptGeneratedAt", + "fieldName": "promptGeneratedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptRequestedAt", + "fieldName": "promptRequestedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptNote", + "fieldName": "promptNote", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptExcludedCommentIds", + "fieldName": "promptExcludedCommentIds", + "columnType": 8, + "isNullable": true, + "dartType": "List?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptEditedById", + "fieldName": "promptEditedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptEditedAt", + "fieldName": "promptEditedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publishedAt", + "fieldName": "publishedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimedById", + "fieldName": "claimedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimedAt", + "fieldName": "claimedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimExpiresAt", + "fieldName": "claimExpiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimWarnedAt", + "fieldName": "claimWarnedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimCode", + "fieldName": "claimCode", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "pullRequestUrl", + "fieldName": "pullRequestUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prNumber", + "fieldName": "prNumber", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prAuthorLogin", + "fieldName": "prAuthorLogin", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mergeCommitSha", + "fieldName": "mergeCommitSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "doneAt", + "fieldName": "doneAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shippedDeploySha", + "fieldName": "shippedDeploySha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shippedAt", + "fieldName": "shippedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_task_fk_0", + "columns": [ + "claimedById" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_task_status_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_task_claim_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "claimedById" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_user_profile", + "dartName": "BoardUserProfile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "githubLogin", + "fieldName": "githubLogin", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedAt", + "fieldName": "blockedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedUntil", + "fieldName": "blockedUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedReason", + "fieldName": "blockedReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedById", + "fieldName": "blockedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_user_profile_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_user_profile_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_vote", + "dartName": "BoardVote", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postId", + "fieldName": "postId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_vote_fk_0", + "columns": [ + "postId" + ], + "referenceTable": "board_post", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_vote_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_vote_unique_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_vote_recent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "cell", + "dartName": "Cell", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowId", + "fieldName": "rowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "columnId", + "fieldName": "columnId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "content", + "fieldName": "content", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "note", + "fieldName": "note", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "numberFormat", + "fieldName": "numberFormat", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fontFamily", + "fieldName": "fontFamily", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fontSize", + "fieldName": "fontSize", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "bold", + "fieldName": "bold", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "italic", + "fieldName": "italic", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "underline", + "fieldName": "underline", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "strikethrough", + "fieldName": "strikethrough", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "textColor", + "fieldName": "textColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fillColor", + "fieldName": "fillColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hAlign", + "fieldName": "hAlign", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:HorizontalAlign?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "vAlign", + "fieldName": "vAlign", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:VerticalAlign?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "wrap", + "fieldName": "wrap", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:WrapStrategy?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rotation", + "fieldName": "rotation", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderTop", + "fieldName": "borderTop", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderRight", + "fieldName": "borderRight", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderBottom", + "fieldName": "borderBottom", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderLeft", + "fieldName": "borderLeft", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "linkUrl", + "fieldName": "linkUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "cell_fk_0", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_row_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "rowId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_col_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "columnId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "cell_history", + "dartName": "CellHistory", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowId", + "fieldName": "rowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "colId", + "fieldName": "colId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userUuid", + "fieldName": "userUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "before", + "fieldName": "before", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "after", + "fieldName": "after", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_history_cell_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "rowId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "colId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "at" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_history_change_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "rowId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "colId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "chart_link", + "dartName": "ChartLink", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetItemUuid", + "fieldName": "spreadsheetItemUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "chartObjectId", + "fieldName": "chartObjectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceSpecJson", + "fieldName": "sourceSpecJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dataSnapshotJson", + "fieldName": "dataSnapshotJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceVersion", + "fieldName": "sourceVersion", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedBy", + "fieldName": "updatedBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "autoUpdate", + "fieldName": "autoUpdate", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "chart_link_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "chart_link_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "chart_link_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "chart_link_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "code_state", + "dartName": "CodeState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "code", + "fieldName": "code", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "language", + "fieldName": "language", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "highlight", + "fieldName": "highlight", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "annotationsJson", + "fieldName": "annotationsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "transitionJson", + "fieldName": "transitionJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "code_state_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "code_state_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "code_state_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "code_state_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "comment", + "dartName": "Comment", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "threadId", + "fieldName": "threadId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorKind", + "fieldName": "authorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "body", + "fieldName": "body", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mentions", + "fieldName": "mentions", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reactions", + "fieldName": "reactions", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedAt", + "fieldName": "editedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "systemEvent", + "fieldName": "systemEvent", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:CommentSystemEvent?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_fk_0", + "columns": [ + "threadId" + ], + "referenceTable": "comment_thread", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_fk_1", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_thread_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "threadId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "comment_thread", + "dartName": "CommentThread", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorKind", + "fieldName": "anchorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:CommentAnchorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorJson", + "fieldName": "anchorJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "quotedText", + "fieldName": "quotedText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "columnDefault": "'open'", + "dartType": "protocol:CommentStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "resolvedById", + "fieldName": "resolvedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "resolvedAt", + "fieldName": "resolvedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "assigneeId", + "fieldName": "assigneeId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "statusBeforeOrphan", + "fieldName": "statusBeforeOrphan", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:CommentStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "orphanReasonJson", + "fieldName": "orphanReasonJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "suggestionId", + "fieldName": "suggestionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_thread_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_thread_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_thread_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "conditional_format_rule", + "dartName": "ConditionalFormatRule", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangesJson", + "fieldName": "rangesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ruleJson", + "fieldName": "ruleJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "conditional_format_rule_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "conditional_format_rule_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "conditional_format_rule_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "data_validation_rule", + "dartName": "DataValidationRule", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangesJson", + "fieldName": "rangesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "criteriaJson", + "fieldName": "criteriaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "strict", + "fieldName": "strict", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showDropdown", + "fieldName": "showDropdown", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayStyle", + "fieldName": "displayStyle", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "helpText", + "fieldName": "helpText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "data_validation_rule_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "data_validation_rule_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "data_validation_rule_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "deck", + "dartName": "Deck", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "width", + "fieldName": "width", + "columnType": 3, + "isNullable": false, + "columnDefault": "1920.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "height", + "fieldName": "height", + "columnType": 3, + "isNullable": false, + "columnDefault": "1080.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizePreset", + "fieldName": "sizePreset", + "columnType": 0, + "isNullable": false, + "columnDefault": "'widescreen16x9'", + "dartType": "protocol:SlideSizePreset" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appearance", + "fieldName": "appearance", + "columnType": 0, + "isNullable": false, + "columnDefault": "'light'", + "dartType": "protocol:DeckAppearance" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "language", + "fieldName": "language", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showSlideNumbers", + "fieldName": "showSlideNumbers", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hideNumberOnTitle", + "fieldName": "hideNumberOnTitle", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "firstSlideNumber", + "fieldName": "firstSlideNumber", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "footerText", + "fieldName": "footerText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultsJson", + "fieldName": "defaultsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "guidesJson", + "fieldName": "guidesJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "presentJson", + "fieldName": "presentJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "deck_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "deck_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "deck_theme", + "dartName": "DeckTheme", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deckId", + "fieldName": "deckId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceKey", + "fieldName": "sourceKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "colorsJson", + "fieldName": "colorsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fontsJson", + "fieldName": "fontsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "textStylesJson", + "fieldName": "textStylesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shapeStyleJson", + "fieldName": "shapeStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "tableStyleJson", + "fieldName": "tableStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "codeStyleJson", + "fieldName": "codeStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "chartStyleJson", + "fieldName": "chartStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "deck_theme_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "deck_theme_fk_1", + "columns": [ + "deckId" + ], + "referenceTable": "deck", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "deck_theme_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "deck_theme_deck_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deckId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "dimension_group", + "dartName": "DimensionGroup", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dimension", + "fieldName": "dimension", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:Dimension" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "startId", + "fieldName": "startId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "endId", + "fieldName": "endId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "depth", + "fieldName": "depth", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "collapsed", + "fieldName": "collapsed", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "dimension_group_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "dimension_group_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "dimension_group_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document", + "dartName": "Document", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "headRevision", + "fieldName": "headRevision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "latestSnapshotRevision", + "fieldName": "latestSnapshotRevision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "pageSetupJson", + "fieldName": "pageSetupJson", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "language", + "fieldName": "language", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "frontMatter", + "fieldName": "frontMatter", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "charCount", + "fieldName": "charCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "wordCount", + "fieldName": "wordCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_import_report", + "dartName": "DocumentImportReport", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "warningsJson", + "fieldName": "warningsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "seenAt", + "fieldName": "seenAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_import_report_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_import_report_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_meta_change", + "dartName": "DocumentMetaChange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "field", + "fieldName": "field", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientOpId", + "fieldName": "clientOpId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "beforeJson", + "fieldName": "beforeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "afterJson", + "fieldName": "afterJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_meta_change_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_meta_change_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_meta_change_client_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "clientOpId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_op", + "dartName": "DocumentOp", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientOpId", + "fieldName": "clientOpId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionId", + "fieldName": "sessionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:DocumentOpKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "baseRevision", + "fieldName": "baseRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deltaJson", + "fieldName": "deltaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseJson", + "fieldName": "inverseJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_op_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_op_rev_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_op_client_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "clientOpId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_op_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_snapshot", + "dartName": "DocumentSnapshot", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deltaJson", + "fieldName": "deltaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "compressed", + "fieldName": "compressed", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_snapshot_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_snapshot_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "drive_item", + "dartName": "DriveItem", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:DriveItemKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "parentId", + "fieldName": "parentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "description", + "fieldName": "description", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentRef", + "fieldName": "contentRef", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "thumbnailFileId", + "fieldName": "thumbnailFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizeBytes", + "fieldName": "sizeBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attachmentBytes", + "fieldName": "attachmentBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kindMask", + "fieldName": "kindMask", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mimeType", + "fieldName": "mimeType", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileCategory", + "fieldName": "fileCategory", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:FileCategory?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uploadState", + "fieldName": "uploadState", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:FileUploadState?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileMetaJson", + "fieldName": "fileMetaJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previewFileId", + "fieldName": "previewFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "modifiedAt", + "fieldName": "modifiedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "modifiedById", + "fieldName": "modifiedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trashedAt", + "fieldName": "trashedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trashedById", + "fieldName": "trashedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateOf", + "fieldName": "templateOf", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:TemplateCategory?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateKey", + "fieldName": "templateKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editorsCanShare", + "fieldName": "editorsCanShare", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nonEditorsCanExport", + "fieldName": "nonEditorsCanExport", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "viewersSeeComments", + "fieldName": "viewersSeeComments", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "searchText", + "fieldName": "searchText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 2 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_fk_1", + "columns": [ + "parentId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_parent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "parentId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "trashedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_content_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "contentRef" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_template_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "templateOf" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_upload_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uploadState" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_trashed_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "trashedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "drive_item_permission", + "dartName": "DriveItemPermission", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "invitedEmail", + "fieldName": "invitedEmail", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "role", + "fieldName": "role", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:AccessRole" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inheritedFromId", + "fieldName": "inheritedFromId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "grantedById", + "fieldName": "grantedById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "grantedAt", + "fieldName": "grantedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "viaPublicationId", + "fieldName": "viaPublicationId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_2", + "columns": [ + "viaPublicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_item_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "inheritedFromId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "invitedEmail" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false, + "nullsDistinct": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_email_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "invitedEmail" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_expires_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "drive_item_user_state", + "dartName": "DriveItemUserState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "starred", + "fieldName": "starred", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastOpenedAt", + "fieldName": "lastOpenedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastEditedAt", + "fieldName": "lastEditedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "pinnedOffline", + "fieldName": "pinnedOffline", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shortcutParentId", + "fieldName": "shortcutParentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "viaLink", + "fieldName": "viaLink", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_user_state_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_user_state_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_user_state_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_user_recent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "lastOpenedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "embedded_object", + "dartName": "EmbeddedObject", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:EmbeddedObjectKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorJson", + "fieldName": "anchorJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "specJson", + "fieldName": "specJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "zIndex", + "fieldName": "zIndex", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "altText", + "fieldName": "altText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "embedded_object_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "embedded_object_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "embedded_object_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "feedback_report", + "dartName": "FeedbackReport", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:FeedbackKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "message", + "fieldName": "message", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "app", + "fieldName": "app", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appVersion", + "fieldName": "appVersion", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "platform", + "fieldName": "platform", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "route", + "fieldName": "route", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stackTrace", + "fieldName": "stackTrace", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextJson", + "fieldName": "contextJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "feedback_report_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "filter_view", + "dartName": "FilterView", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "criteriaJson", + "fieldName": "criteriaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortJson", + "fieldName": "sortJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "filter_view_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "filter_view_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "filter_view_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "headless_change", + "dartName": "HeadlessChange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseJson", + "fieldName": "inverseJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaField", + "fieldName": "metaField", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaBeforeJson", + "fieldName": "metaBeforeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaAfterJson", + "fieldName": "metaAfterJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toolName", + "fieldName": "toolName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revertedAt", + "fieldName": "revertedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "headless_change_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "headless_change_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "changeId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "headless_change_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "item_version", + "dartName": "ItemVersion", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:VersionKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authors", + "fieldName": "authors", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageKind", + "fieldName": "storageKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:VersionStorage" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "snapshotFileId", + "fieldName": "snapshotFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizeBytes", + "fieldName": "sizeBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_version_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_version_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "item_version_state", + "dartName": "ItemVersionState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastEditAt", + "fieldName": "lastEditAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dirtySince", + "fieldName": "dirtySince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastVersionAt", + "fieldName": "lastVersionAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editorsSinceLastVersion", + "fieldName": "editorsSinceLastVersion", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastRevision", + "fieldName": "lastRevision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "capturingSince", + "fieldName": "capturingSince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_version_state_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_version_state_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_version_state_dirty_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "dirtySince" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "item_view_day", + "dartName": "ItemViewDay", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "day", + "fieldName": "day", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "views", + "fieldName": "views", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastViewedAt", + "fieldName": "lastViewedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_view_day_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_view_day_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_view_day_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_view_day_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "macro", + "dartName": "Macro", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shortcutSlot", + "fieldName": "shortcutSlot", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "macro_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "macro_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "macro_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "merged_range", + "dartName": "MergedRange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "merged_range_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "merged_range_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "merged_range_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "named_range", + "dartName": "NamedRange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetId", + "fieldName": "spreadsheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formula", + "fieldName": "formula", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "comment", + "fieldName": "comment", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaJson", + "fieldName": "metaJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "named_range_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "named_range_fk_1", + "columns": [ + "spreadsheetId" + ], + "referenceTable": "spreadsheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "named_range_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "notification", + "dartName": "UserNotification", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:NotificationKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorId", + "fieldName": "actorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "readAt", + "fieldName": "readAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "emailedAt", + "fieldName": "emailedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "emailPending", + "fieldName": "emailPending", + "columnType": 1, + "isNullable": true, + "columnDefault": "false", + "dartType": "bool?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "notification_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "notification_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "notification_email_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "emailPending" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "notification_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ownership_transfer", + "dartName": "OwnershipTransfer", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fromUserId", + "fieldName": "fromUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toUserId", + "fieldName": "toUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "handledAt", + "fieldName": "handledAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "accepted", + "fieldName": "accepted", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ownership_transfer_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ownership_transfer_fk_1", + "columns": [ + "toUserId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ownership_transfer_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "handledAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "personal_access_token", + "dartName": "PersonalAccessToken", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "tokenHash", + "fieldName": "tokenHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prefix", + "fieldName": "prefix", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopes", + "fieldName": "scopes", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastUsedAt", + "fieldName": "lastUsedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revokedAt", + "fieldName": "revokedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "personal_access_token_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "personal_access_token_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "personal_access_token_hash_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "tokenHash" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "pivot_table", + "dartName": "PivotTable", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorRowId", + "fieldName": "anchorRowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorColId", + "fieldName": "anchorColId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceRangeJson", + "fieldName": "sourceRangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "specJson", + "fieldName": "specJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "pivot_table_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "pivot_table_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "pivot_table_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "protected_range", + "dartName": "ProtectedRange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "exceptRangesJson", + "fieldName": "exceptRangesJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "description", + "fieldName": "description", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "warningOnly", + "fieldName": "warningOnly", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editorsJson", + "fieldName": "editorsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "protected_range_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "protected_range_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "protected_range_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication", + "dartName": "Publication", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicId", + "fieldName": "publicId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "siteUrl", + "fieldName": "siteUrl", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "webhookUrl", + "fieldName": "webhookUrl", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verifiedHost", + "fieldName": "verifiedHost", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verifiedAt", + "fieldName": "verifiedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateItemId", + "fieldName": "templateItemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "termsUrl", + "fieldName": "termsUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fields", + "fieldName": "fields", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:PublicationFields" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "signingSecret", + "fieldName": "signingSecret", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previousSigningSecret", + "fieldName": "previousSigningSecret", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previousSecretUntil", + "fieldName": "previousSecretUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKeyHash", + "fieldName": "apiKeyHash", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKeyLast4", + "fieldName": "apiKeyLast4", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_fk_1", + "columns": [ + "templateItemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_public_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_api_key_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "apiKeyHash" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_block", + "dartName": "PublicationBlock", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_block_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_block_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_block_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_consent", + "dartName": "PublicationConsent", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "consentKey", + "fieldName": "consentKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_consent_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_consent_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_consent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_delivery", + "dartName": "PublicationDelivery", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "webhookId", + "fieldName": "webhookId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "type", + "fieldName": "type", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sequence", + "fieldName": "sequence", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextAttemptAt", + "fieldName": "nextAttemptAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastStatus", + "fieldName": "lastStatus", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastError", + "fieldName": "lastError", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deliveredAt", + "fieldName": "deliveredAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "failedAt", + "fieldName": "failedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_delivery_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_delivery_fk_1", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_webhook_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "webhookId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextAttemptAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_publication_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_moderator", + "dartName": "PublicationModerator", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_moderator_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_moderator_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_moderator_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_moderator_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "rev_file", + "dartName": "RevFile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:RevFileKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "headRevision", + "fieldName": "headRevision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prunedBelow", + "fieldName": "prunedBelow", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "initPending", + "fieldName": "initPending", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "purging", + "fieldName": "purging", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "schemaHash", + "fieldName": "schemaHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stats", + "fieldName": "stats", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentCount", + "fieldName": "contentCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "rev_file_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 2 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_file_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_file_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "rev_hook_state", + "dartName": "RevHookState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cursorsJson", + "fieldName": "cursorsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseOwner", + "fieldName": "leaseOwner", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastError", + "fieldName": "lastError", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextAttemptAt", + "fieldName": "nextAttemptAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "rev_hook_state_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_hook_state_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_hook_state_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextAttemptAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "rev_op", + "dartName": "RevOp", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientOpId", + "fieldName": "clientOpId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "baseRevision", + "fieldName": "baseRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorUuid", + "fieldName": "authorUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionId", + "fieldName": "sessionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "onBehalfOfSessionId", + "fieldName": "onBehalfOfSessionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupId", + "fieldName": "groupId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupIndex", + "fieldName": "groupIndex", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupLast", + "fieldName": "groupLast", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "recordId", + "fieldName": "recordId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "offline", + "fieldName": "offline", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 5, + "isNullable": true, + "dartType": "dart:typed_data:ByteData?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeCount", + "fieldName": "changeCount", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "summaryJson", + "fieldName": "summaryJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "detailJson", + "fieldName": "detailJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outcomeJson", + "fieldName": "outcomeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appliedEqualsSubmitted", + "fieldName": "appliedEqualsSubmitted", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientCreatedAt", + "fieldName": "clientCreatedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "committedAt", + "fieldName": "committedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "rev_op_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_rev_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_client_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "clientOpId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_record_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "recordId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_committed_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "committedAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_authorization", + "dartName": "ScriptAuthorization", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopes", + "fieldName": "scopes", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "grantedAt", + "fieldName": "grantedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revokedAt", + "fieldName": "revokedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_auth_user_sheet_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_build", + "dartName": "ScriptBuild", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "columnDefault": "'ok'", + "dartType": "protocol:ScriptBuildStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceHash", + "fieldName": "sourceHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "bytecodeFileUuid", + "fieldName": "bytecodeFileUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "diagnosticsJson", + "fieldName": "diagnosticsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "exportsJson", + "fieldName": "exportsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiVersion", + "fieldName": "apiVersion", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "compilerVersion", + "fieldName": "compilerVersion", + "columnType": 0, + "isNullable": false, + "columnDefault": "''", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requestedBy", + "fieldName": "requestedBy", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodSourceHash", + "fieldName": "lastGoodSourceHash", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodBytecodeFileUuid", + "fieldName": "lastGoodBytecodeFileUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodExportsJson", + "fieldName": "lastGoodExportsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodBuiltAt", + "fieldName": "lastGoodBuiltAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "positionsFileUuid", + "fieldName": "positionsFileUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "builtAt", + "fieldName": "builtAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_build_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_build_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_build_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_execution", + "dartName": "ScriptExecution", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerId", + "fieldName": "triggerId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runAsUserId", + "fieldName": "runAsUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runtime", + "fieldName": "runtime", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptRuntimeKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "buildSourceHash", + "fieldName": "buildSourceHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "startedAt", + "fieldName": "startedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "durationMs", + "fieldName": "durationMs", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logs", + "fieldName": "logs", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "errorMessage", + "fieldName": "errorMessage", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "errorStackJson", + "fieldName": "errorStackJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cellsRead", + "fieldName": "cellsRead", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cellsWritten", + "fieldName": "cellsWritten", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fetchCalls", + "fieldName": "fetchCalls", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "callCount", + "fieldName": "callCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_exec_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_exec_sheet_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "startedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_exec_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "startedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_file", + "dartName": "ScriptFile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "source", + "fieldName": "source", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentHash", + "fieldName": "contentHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedBy", + "fieldName": "updatedBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_file_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_file_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_file_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_job", + "dartName": "ScriptJob", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemUuid", + "fieldName": "itemUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerId", + "fieldName": "triggerId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runAsUserId", + "fieldName": "runAsUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payloadJson", + "fieldName": "payloadJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enqueuedAt", + "fieldName": "enqueuedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseOwner", + "fieldName": "leaseOwner", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "coalesced", + "fieldName": "coalesced", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "resultJson", + "fieldName": "resultJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "finishedAt", + "fieldName": "finishedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_job_status_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "enqueuedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_job_trigger_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "triggerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_job_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "runAsUserId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_project", + "dartName": "ScriptProject", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetId", + "fieldName": "spreadsheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "settingsJson", + "fieldName": "settingsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_project_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_project_fk_1", + "columns": [ + "spreadsheetId" + ], + "referenceTable": "spreadsheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_project_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_property", + "dartName": "ScriptProperty", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_property_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_property_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_property_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_quota_usage", + "dartName": "ScriptQuotaUsage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "day", + "fieldName": "day", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverRuntimeMs", + "fieldName": "serverRuntimeMs", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientRuntimeMs", + "fieldName": "clientRuntimeMs", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "urlFetchCalls", + "fieldName": "urlFetchCalls", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "urlFetchBytes", + "fieldName": "urlFetchBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerRuns", + "fieldName": "triggerRuns", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_quota_user_day_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_trigger", + "dartName": "ScriptTrigger", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:TriggerKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scheduleJson", + "fieldName": "scheduleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runAsUserId", + "fieldName": "runAsUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "optionsJson", + "fieldName": "optionsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_trigger_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_trigger_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_trigger_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_trigger_state", + "dartName": "ScriptTriggerState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerId", + "fieldName": "triggerId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scheduleJson", + "fieldName": "scheduleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextRunAt", + "fieldName": "nextRunAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastRunAt", + "fieldName": "lastRunAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastStatus", + "fieldName": "lastStatus", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:ScriptExecutionStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "consecutiveFailures", + "fieldName": "consecutiveFailures", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "disabledReason", + "fieldName": "disabledReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runningSince", + "fieldName": "runningSince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastNotifiedAt", + "fieldName": "lastNotifiedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_trigger_state_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "triggerId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_trigger_state_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextRunAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_user_property", + "dartName": "ScriptUserProperty", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_user_property_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_user_property_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "key" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "server_change_record", + "dartName": "ServerChangeRecord", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseJson", + "fieldName": "inverseJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseFileId", + "fieldName": "inverseFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "forwardFileId", + "fieldName": "forwardFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "recordId", + "fieldName": "recordId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cellsAffected", + "fieldName": "cellsAffected", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revertedAt", + "fieldName": "revertedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revertChangeId", + "fieldName": "revertChangeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "server_change_record_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "recordId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "server_change_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "server_change_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "changeId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "share_link", + "dartName": "ShareLink", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "token", + "fieldName": "token", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "role", + "fieldName": "role", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:AccessRole?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "share_link_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "share_link_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "share_link_token_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "token" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheet", + "dartName": "Sheet", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetId", + "fieldName": "spreadsheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "columnDefault": "'grid'", + "dartType": "protocol:SheetKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "tabColor", + "fieldName": "tabColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rightToLeft", + "fieldName": "rightToLeft", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showGridlines", + "fieldName": "showGridlines", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "frozenRows", + "fieldName": "frozenRows", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "frozenColumns", + "fieldName": "frozenColumns", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultRowHeight", + "fieldName": "defaultRowHeight", + "columnType": 3, + "isNullable": false, + "columnDefault": "21.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultColumnWidth", + "fieldName": "defaultColumnWidth", + "columnType": 3, + "isNullable": false, + "columnDefault": "100.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formatJson", + "fieldName": "formatJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "printSettingsJson", + "fieldName": "printSettingsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_fk_1", + "columns": [ + "spreadsheetId" + ], + "referenceTable": "spreadsheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheet_column", + "dartName": "SheetColumn", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "width", + "fieldName": "width", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formatJson", + "fieldName": "formatJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_column_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_column_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_column_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_column_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheet_row", + "dartName": "SheetRow", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "height", + "fieldName": "height", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formatJson", + "fieldName": "formatJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_row_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_row_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_row_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_row_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheets_import_job", + "dartName": "SheetsImportJob", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uploadFileId", + "fieldName": "uploadFileId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileName", + "fieldName": "fileName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "format", + "fieldName": "format", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "optionsJson", + "fieldName": "optionsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "activeSheetId", + "fieldName": "activeSheetId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SheetsImportStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "progressDone", + "fieldName": "progressDone", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "progressTotal", + "fieldName": "progressTotal", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reportJson", + "fieldName": "reportJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetIdsJson", + "fieldName": "sheetIdsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "errorCode", + "fieldName": "errorCode", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cancelRequested", + "fieldName": "cancelRequested", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseOwner", + "fieldName": "leaseOwner", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheets_import_job_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheets_import_job_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheets_snapshot_index", + "dartName": "SheetsSnapshotIndex", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemVersionId", + "fieldName": "itemVersionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetsJson", + "fieldName": "sheetsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changedRangesJson", + "fieldName": "changedRangesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorIds", + "fieldName": "authorIds", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "diffFileId", + "fieldName": "diffFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheets_snapshot_index_fk_0", + "columns": [ + "itemVersionId" + ], + "referenceTable": "item_version", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheets_snapshot_index_version_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemVersionId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide", + "dartName": "Slide", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deckId", + "fieldName": "deckId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupId", + "fieldName": "groupId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "layoutId", + "fieldName": "layoutId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "skipped", + "fieldName": "skipped", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "notes", + "fieldName": "notes", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "transitionJson", + "fieldName": "transitionJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hideMasterElements", + "fieldName": "hideMasterElements", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timingsJson", + "fieldName": "timingsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_fk_1", + "columns": [ + "deckId" + ], + "referenceTable": "deck", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deckId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_build", + "dartName": "SlideBuild", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slideId", + "fieldName": "slideId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BuildKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "effect", + "fieldName": "effect", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trigger", + "fieldName": "trigger", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BuildTrigger" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "delayMs", + "fieldName": "delayMs", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "durationMs", + "fieldName": "durationMs", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "easing", + "fieldName": "easing", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "optionsJson", + "fieldName": "optionsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_build_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_build_fk_1", + "columns": [ + "slideId" + ], + "referenceTable": "slide", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_build_fk_2", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_build_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_build_slide_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "slideId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_build_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_element", + "dartName": "SlideElement", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slideId", + "fieldName": "slideId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "layoutId", + "fieldName": "layoutId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "masterId", + "fieldName": "masterId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "parentId", + "fieldName": "parentId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SlideElementKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "x", + "fieldName": "x", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "y", + "fieldName": "y", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "width", + "fieldName": "width", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "height", + "fieldName": "height", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rotation", + "fieldName": "rotation", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "flipH", + "fieldName": "flipH", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "flipV", + "fieldName": "flipV", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "zKey", + "fieldName": "zKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "readingKey", + "fieldName": "readingKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "locked", + "fieldName": "locked", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "placeholderType", + "fieldName": "placeholderType", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:PlaceholderType?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "placeholderOf", + "fieldName": "placeholderOf", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "matchKey", + "fieldName": "matchKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "text", + "fieldName": "text", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "textStyleJson", + "fieldName": "textStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fillJson", + "fieldName": "fillJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "strokeJson", + "fieldName": "strokeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "effectsJson", + "fieldName": "effectsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "opacity", + "fieldName": "opacity", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dataJson", + "fieldName": "dataJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "linkJson", + "fieldName": "linkJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "altText", + "fieldName": "altText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "decorative", + "fieldName": "decorative", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_1", + "columns": [ + "slideId" + ], + "referenceTable": "slide", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_2", + "columns": [ + "layoutId" + ], + "referenceTable": "slide_layout", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_3", + "columns": [ + "masterId" + ], + "referenceTable": "slide_master", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_4", + "columns": [ + "parentId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_slide_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "slideId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "zKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_layout_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "layoutId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_master_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "masterId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_parent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "parentId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_group", + "dartName": "SlideGroup", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deckId", + "fieldName": "deckId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "parentId", + "fieldName": "parentId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "color", + "fieldName": "color", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "skipped", + "fieldName": "skipped", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_group_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_group_fk_1", + "columns": [ + "deckId" + ], + "referenceTable": "deck", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_group_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_group_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deckId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_layout", + "dartName": "SlideLayout", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "masterId", + "fieldName": "masterId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hideMasterElements", + "fieldName": "hideMasterElements", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_layout_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_layout_fk_1", + "columns": [ + "masterId" + ], + "referenceTable": "slide_master", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_layout_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_layout_master_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "masterId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_master", + "dartName": "SlideMaster", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_master_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_master_fk_1", + "columns": [ + "themeId" + ], + "referenceTable": "deck_theme", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_master_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_master_theme_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "themeId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_table_axis", + "dartName": "SlideTableAxis", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dimension", + "fieldName": "dimension", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:TableDimension" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "size", + "fieldName": "size", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "header", + "fieldName": "header", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_axis_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_axis_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_axis_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_axis_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_table_cell", + "dartName": "SlideTableCell", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowId", + "fieldName": "rowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "columnId", + "fieldName": "columnId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "text", + "fieldName": "text", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fill", + "fieldName": "fill", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderTop", + "fieldName": "borderTop", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderRight", + "fieldName": "borderRight", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderBottom", + "fieldName": "borderBottom", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderLeft", + "fieldName": "borderLeft", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "vAlign", + "fieldName": "vAlign", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "padding", + "fieldName": "padding", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowSpan", + "fieldName": "rowSpan", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "colSpan", + "fieldName": "colSpan", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_2", + "columns": [ + "rowId" + ], + "referenceTable": "slide_table_axis", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_3", + "columns": [ + "columnId" + ], + "referenceTable": "slide_table_axis", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_cell_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_cell_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slides_snapshot_index", + "dartName": "SlidesSnapshotIndex", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemVersionId", + "fieldName": "itemVersionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slidesJson", + "fieldName": "slidesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changesJson", + "fieldName": "changesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorIds", + "fieldName": "authorIds", + "columnType": 8, + "isNullable": false, + "dartType": "List" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slides_snapshot_index_fk_0", + "columns": [ + "itemVersionId" + ], + "referenceTable": "item_version", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slides_snapshot_index_version_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemVersionId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "spreadsheet", + "dartName": "Spreadsheet", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "locale", + "fieldName": "locale", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timeZone", + "fieldName": "timeZone", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "recalcMode", + "fieldName": "recalcMode", + "columnType": 0, + "isNullable": false, + "columnDefault": "'onChange'", + "dartType": "protocol:RecalcMode" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "iterativeCalc", + "fieldName": "iterativeCalc", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "maxIterations", + "fieldName": "maxIterations", + "columnType": 6, + "isNullable": false, + "columnDefault": "50", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "convergenceThreshold", + "fieldName": "convergenceThreshold", + "columnType": 3, + "isNullable": false, + "columnDefault": "0.05", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultFontFamily", + "fieldName": "defaultFontFamily", + "columnType": 0, + "isNullable": false, + "columnDefault": "'Inter'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultFontSize", + "fieldName": "defaultFontSize", + "columnType": 3, + "isNullable": false, + "columnDefault": "10.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeJson", + "fieldName": "themeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayLanguage", + "fieldName": "displayLanguage", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "spreadsheet_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "spreadsheet_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "storage_reservation", + "dartName": "StorageReservation", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "bytes", + "fieldName": "bytes", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "storage_reservation_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "storage_reservation_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "storage_reservation_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "storage_reservation_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "storage_reservation_expiry_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "stored_file", + "dartName": "StoredFile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:StoredFileKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageId", + "fieldName": "storageId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "path", + "fieldName": "path", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileName", + "fieldName": "fileName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mimeType", + "fieldName": "mimeType", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizeBytes", + "fieldName": "sizeBytes", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:StoredFileStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "completedAt", + "fieldName": "completedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "stored_file_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "stored_file_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_expiry_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_owner_kind_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "kind" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_status_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "submission", + "dartName": "Submission", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ref", + "fieldName": "ref", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SubmissionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "statusBeforeSubmit", + "fieldName": "statusBeforeSubmit", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:SubmissionStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "delivery", + "fieldName": "delivery", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:SubmissionDeliveryState?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "values", + "fieldName": "values", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:SubmissionValues" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicUrl", + "fieldName": "publicUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feedbackThreadId", + "fieldName": "feedbackThreadId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "disconnectedAt", + "fieldName": "disconnectedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_publication_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "submission_asset", + "dartName": "SubmissionAsset", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_asset_fk_0", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_asset_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "submissionId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_asset_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "submission_revision", + "dartName": "SubmissionRevision", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sequence", + "fieldName": "sequence", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "versionId", + "fieldName": "versionId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "values", + "fieldName": "values", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:SubmissionValues" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submittedById", + "fieldName": "submittedById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submittedAt", + "fieldName": "submittedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_revision_fk_0", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_revision_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "submissionId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sequence" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_activity_settings", + "dartName": "UserActivitySettings", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showViewHistory", + "fieldName": "showViewHistory", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_activity_settings_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_activity_settings_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_preferences", + "dartName": "UserPreferences", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appTheme", + "fieldName": "appTheme", + "columnType": 0, + "isNullable": false, + "columnDefault": "'system'", + "dartType": "protocol:AppThemeMode" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "accentColor", + "fieldName": "accentColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "density", + "fieldName": "density", + "columnType": 0, + "isNullable": false, + "columnDefault": "'comfortable'", + "dartType": "protocol:UiDensity" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reduceMotion", + "fieldName": "reduceMotion", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "keymapOverrides", + "fieldName": "keymapOverrides", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "writeDefaults", + "fieldName": "writeDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetsDefaults", + "fieldName": "sheetsDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slidesDefaults", + "fieldName": "slidesDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slidesPresenter", + "fieldName": "slidesPresenter", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "driveDefaults", + "fieldName": "driveDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "notificationSettings", + "fieldName": "notificationSettings", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "aiEnabled", + "fieldName": "aiEnabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_preferences_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_preferences_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_profile", + "dartName": "UserProfile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayName", + "fieldName": "displayName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "avatarFileId", + "fieldName": "avatarFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "avatarColor", + "fieldName": "avatarColor", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "locale", + "fieldName": "locale", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timeZone", + "fieldName": "timeZone", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastSeenAt", + "fieldName": "lastSeenAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "welcomeContentAt", + "fieldName": "welcomeContentAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_profile_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_profile_auth_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "authUserId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_profile_email_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_storage", + "dartName": "UserStorage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "usedBytes", + "fieldName": "usedBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reservedBytes", + "fieldName": "reservedBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentsBytes", + "fieldName": "documentsBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetsBytes", + "fieldName": "spreadsheetsBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "presentationsBytes", + "fieldName": "presentationsBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "filesBytes", + "fieldName": "filesBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trashBytes", + "fieldName": "trashBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "quotaBytesOverride", + "fieldName": "quotaBytesOverride", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "overQuotaSince", + "fieldName": "overQuotaSince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reconciledAt", + "fieldName": "reconciledAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_storage_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_storage_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "write_diff_cache", + "dartName": "WriteDiffCache", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fromRevision", + "fieldName": "fromRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toRevision", + "fieldName": "toRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "json", + "fieldName": "json", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "write_diff_cache_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_diff_cache_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fromRevision" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "toRevision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_diff_cache_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "write_theme", + "dartName": "WriteTheme", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "isBuiltin", + "fieldName": "isBuiltin", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "builtinKey", + "fieldName": "builtinKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "description", + "fieldName": "description", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "schemaVersion", + "fieldName": "schemaVersion", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "version", + "fieldName": "version", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "json", + "fieldName": "json", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentHash", + "fieldName": "contentHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "write_theme_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deletedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_builtin_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "builtinKey" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "write_theme_revision", + "dartName": "WriteThemeRevision", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "version", + "fieldName": "version", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "json", + "fieldName": "json", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "savedById", + "fieldName": "savedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "write_theme_revision_fk_0", + "columns": [ + "themeId" + ], + "referenceTable": "write_theme", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_rev_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "themeId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "version" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_cloud_storage", + "dartName": "CloudStorageEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageId", + "fieldName": "storageId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "path", + "fieldName": "path", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "addedTime", + "fieldName": "addedTime", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiration", + "fieldName": "expiration", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "byteData", + "fieldName": "byteData", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verified", + "fieldName": "verified", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentType", + "fieldName": "contentType", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cacheControl", + "fieldName": "cacheControl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentDisposition", + "fieldName": "contentDisposition", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentEncoding", + "fieldName": "contentEncoding", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "customMetadata", + "fieldName": "customMetadata", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_cloud_storage_path_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "storageId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "path" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_cloud_storage_expiration", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiration" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_cloud_storage_direct_download", + "dartName": "CloudStorageDirectDownloadEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageId", + "fieldName": "storageId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "path", + "fieldName": "path", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiration", + "fieldName": "expiration", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authKey", + "fieldName": "authKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "downloadFileName", + "fieldName": "downloadFileName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentType", + "fieldName": "contentType", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_cloud_storage_direct_download_auth_key", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "authKey" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_cloud_storage_direct_download_expiration", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiration" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_cloud_storage_direct_upload", + "dartName": "CloudStorageDirectUploadEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageId", + "fieldName": "storageId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "path", + "fieldName": "path", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiration", + "fieldName": "expiration", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authKey", + "fieldName": "authKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "maxFileSize", + "fieldName": "maxFileSize", + "columnType": 6, + "isNullable": false, + "columnDefault": "10485760", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentLength", + "fieldName": "contentLength", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "preventOverwrite", + "fieldName": "preventOverwrite", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentType", + "fieldName": "contentType", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cacheControl", + "fieldName": "cacheControl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentDisposition", + "fieldName": "contentDisposition", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentEncoding", + "fieldName": "contentEncoding", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "customMetadata", + "fieldName": "customMetadata", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_cloud_storage_direct_upload_storage_path", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "storageId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "path" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_future_call", + "dartName": "FutureCallEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "time", + "fieldName": "time", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serializedObject", + "fieldName": "serializedObject", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "identifier", + "fieldName": "identifier", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scheduling", + "fieldName": "scheduling", + "columnType": 8, + "isNullable": true, + "dartType": "protocol:FutureCallScheduling?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_future_call_time_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "time" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_future_call_serverId_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "serverId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_future_call_identifier_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "identifier" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_future_call_claim", + "dartName": "FutureCallClaimEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "futureCallId", + "fieldName": "futureCallId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastHeartbeatTime", + "fieldName": "lastHeartbeatTime", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_future_call_claim_fk_0", + "columns": [ + "futureCallId" + ], + "referenceTable": "serverpod_future_call", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "future_call_unique_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "futureCallId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_health_connection_info", + "dartName": "ServerHealthConnectionInfo", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timestamp", + "fieldName": "timestamp", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "active", + "fieldName": "active", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "closing", + "fieldName": "closing", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "idle", + "fieldName": "idle", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "granularity", + "fieldName": "granularity", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_health_connection_info_timestamp_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "timestamp" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "serverId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "granularity" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_health_metric", + "dartName": "ServerHealthMetric", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timestamp", + "fieldName": "timestamp", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "isHealthy", + "fieldName": "isHealthy", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 3, + "isNullable": false, + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "granularity", + "fieldName": "granularity", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_health_metric_timestamp_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "timestamp" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "serverId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "name" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "granularity" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_log", + "dartName": "LogEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionLogId", + "fieldName": "sessionLogId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "messageId", + "fieldName": "messageId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reference", + "fieldName": "reference", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "time", + "fieldName": "time", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logLevel", + "fieldName": "logLevel", + "columnType": 6, + "isNullable": false, + "dartType": "protocol:LogLevel" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "message", + "fieldName": "message", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stackTrace", + "fieldName": "stackTrace", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "order", + "fieldName": "order", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_log_fk_0", + "columns": [ + "sessionLogId" + ], + "referenceTable": "serverpod_session_log", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_log_sessionLogId_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sessionLogId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "order" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_message_log", + "dartName": "MessageLogEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionLogId", + "fieldName": "sessionLogId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "messageId", + "fieldName": "messageId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "endpoint", + "fieldName": "endpoint", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "messageName", + "fieldName": "messageName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duration", + "fieldName": "duration", + "columnType": 3, + "isNullable": false, + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stackTrace", + "fieldName": "stackTrace", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slow", + "fieldName": "slow", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "order", + "fieldName": "order", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_message_log_fk_0", + "columns": [ + "sessionLogId" + ], + "referenceTable": "serverpod_session_log", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_message_log_sessionLogId_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sessionLogId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "order" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_method", + "dartName": "MethodInfo", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "endpoint", + "fieldName": "endpoint", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "method", + "fieldName": "method", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_method_endpoint_method_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "endpoint" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "method" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_migrations", + "dartName": "DatabaseMigrationVersion", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "module", + "fieldName": "module", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "version", + "fieldName": "version", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timestamp", + "fieldName": "timestamp", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_migrations_ids", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "module" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_query_log", + "dartName": "QueryLogEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionLogId", + "fieldName": "sessionLogId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "messageId", + "fieldName": "messageId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "query", + "fieldName": "query", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duration", + "fieldName": "duration", + "columnType": 3, + "isNullable": false, + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "numRows", + "fieldName": "numRows", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stackTrace", + "fieldName": "stackTrace", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slow", + "fieldName": "slow", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "order", + "fieldName": "order", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_query_log_fk_0", + "columns": [ + "sessionLogId" + ], + "referenceTable": "serverpod_session_log", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_query_log_sessionLogId_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sessionLogId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "order" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_readwrite_test", + "dartName": "ReadWriteTestEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "number", + "fieldName": "number", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_runtime_settings", + "dartName": "RuntimeSettings", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logSettings", + "fieldName": "logSettings", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:LogSettings" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logSettingsOverrides", + "fieldName": "logSettingsOverrides", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logServiceCalls", + "fieldName": "logServiceCalls", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logMalformedCalls", + "fieldName": "logMalformedCalls", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_session_log", + "dartName": "SessionLogEntry", + "module": "serverpod", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverId", + "fieldName": "serverId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "time", + "fieldName": "time", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "module", + "fieldName": "module", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "endpoint", + "fieldName": "endpoint", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "method", + "fieldName": "method", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duration", + "fieldName": "duration", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "numQueries", + "fieldName": "numQueries", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slow", + "fieldName": "slow", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stackTrace", + "fieldName": "stackTrace", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authenticatedUserId", + "fieldName": "authenticatedUserId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "isOpen", + "fieldName": "isOpen", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "touched", + "fieldName": "touched", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_session_log_serverid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "serverId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_session_log_time_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "time" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_session_log_touched_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "touched" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_session_log_isopen_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "isOpen" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_anonymous_account", + "dartName": "AnonymousAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_anonymous_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_apple_account", + "dartName": "AppleAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userIdentifier", + "fieldName": "userIdentifier", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "refreshToken", + "fieldName": "refreshToken", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "refreshTokenRequestedWithBundleIdentifier", + "fieldName": "refreshTokenRequestedWithBundleIdentifier", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastRefreshedAt", + "fieldName": "lastRefreshedAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "isEmailVerified", + "fieldName": "isEmailVerified", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "isPrivateEmail", + "fieldName": "isPrivateEmail", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "firstName", + "fieldName": "firstName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastName", + "fieldName": "lastName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_apple_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_apple_account_identifier", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userIdentifier" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_email_account", + "dartName": "EmailAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "passwordHash", + "fieldName": "passwordHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_email_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_idp_email_account_email", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_email_account_password_reset_request", + "dartName": "EmailAccountPasswordResetRequest", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "emailAccountId", + "fieldName": "emailAccountId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "challengeId", + "fieldName": "challengeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "setPasswordChallengeId", + "fieldName": "setPasswordChallengeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_email_account_password_reset_request_fk_0", + "columns": [ + "emailAccountId" + ], + "referenceTable": "serverpod_auth_idp_email_account", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_email_account_password_reset_request_fk_1", + "columns": [ + "challengeId" + ], + "referenceTable": "serverpod_auth_idp_secret_challenge", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_email_account_password_reset_request_fk_2", + "columns": [ + "setPasswordChallengeId" + ], + "referenceTable": "serverpod_auth_idp_secret_challenge", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_email_account_request", + "dartName": "EmailAccountRequest", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "challengeId", + "fieldName": "challengeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createAccountChallengeId", + "fieldName": "createAccountChallengeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_email_account_request_fk_0", + "columns": [ + "challengeId" + ], + "referenceTable": "serverpod_auth_idp_secret_challenge", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_email_account_request_fk_1", + "columns": [ + "createAccountChallengeId" + ], + "referenceTable": "serverpod_auth_idp_secret_challenge", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_idp_email_account_request_email", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_facebook_account", + "dartName": "FacebookAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userIdentifier", + "fieldName": "userIdentifier", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fullName", + "fieldName": "fullName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "firstName", + "fieldName": "firstName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastName", + "fieldName": "lastName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_facebook_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_facebook_account_user_identifier", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userIdentifier" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_firebase_account", + "dartName": "FirebaseAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "created", + "fieldName": "created", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "phone", + "fieldName": "phone", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userIdentifier", + "fieldName": "userIdentifier", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_firebase_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_firebase_account_user_identifier", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userIdentifier" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_github_account", + "dartName": "GitHubAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userIdentifier", + "fieldName": "userIdentifier", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "created", + "fieldName": "created", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_github_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_github_account_user_identifier", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userIdentifier" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_google_account", + "dartName": "GoogleAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "created", + "fieldName": "created", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userIdentifier", + "fieldName": "userIdentifier", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_google_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_google_account_user_identifier", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userIdentifier" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_microsoft_account", + "dartName": "MicrosoftAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userIdentifier", + "fieldName": "userIdentifier", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "created", + "fieldName": "created", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_microsoft_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_microsoft_account_user_identifier", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userIdentifier" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_passkey_account", + "dartName": "PasskeyAccount", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "keyId", + "fieldName": "keyId", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "keyIdBase64", + "fieldName": "keyIdBase64", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientDataJSON", + "fieldName": "clientDataJSON", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attestationObject", + "fieldName": "attestationObject", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "originalChallenge", + "fieldName": "originalChallenge", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_idp_passkey_account_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_idp_passkey_account_key_id_base64", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "keyIdBase64" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_passkey_challenge", + "dartName": "PasskeyChallenge", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "challenge", + "fieldName": "challenge", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_rate_limited_request_attempt", + "dartName": "RateLimitedRequestAttempt", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "domain", + "fieldName": "domain", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "source", + "fieldName": "source", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ipAddress", + "fieldName": "ipAddress", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attemptedAt", + "fieldName": "attemptedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "extraData", + "fieldName": "extraData", + "columnType": 8, + "isNullable": true, + "dartType": "Map?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_idp_rate_limited_request_attempt_composite", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "domain" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "source" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "key" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "attemptedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_idp_secret_challenge", + "dartName": "SecretChallenge", + "module": "serverpod_auth_idp", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "challengeCodeHash", + "fieldName": "challengeCodeHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_core_jwt_refresh_token", + "dartName": "RefreshToken", + "module": "serverpod_auth_core", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopeNames", + "fieldName": "scopeNames", + "columnType": 8, + "isNullable": false, + "dartType": "Set" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "extraClaims", + "fieldName": "extraClaims", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "method", + "fieldName": "method", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fixedSecret", + "fieldName": "fixedSecret", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rotatingSecretHash", + "fieldName": "rotatingSecretHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastUpdatedAt", + "fieldName": "lastUpdatedAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_core_jwt_refresh_token_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_core_jwt_refresh_token_last_updated_at", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "lastUpdatedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_core_profile", + "dartName": "UserProfile", + "module": "serverpod_auth_core", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userName", + "fieldName": "userName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fullName", + "fieldName": "fullName", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "imageId", + "fieldName": "imageId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_core_profile_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_core_profile_fk_1", + "columns": [ + "imageId" + ], + "referenceTable": "serverpod_auth_core_profile_image", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 3, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "serverpod_auth_profile_user_profile_email_auth_user_id", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "authUserId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_core_profile_image", + "dartName": "UserProfileImage", + "module": "serverpod_auth_core", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userProfileId", + "fieldName": "userProfileId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageId", + "fieldName": "storageId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "path", + "fieldName": "path", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "url", + "fieldName": "url", + "columnType": 0, + "isNullable": false, + "dartType": "Uri" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_core_profile_image_fk_0", + "columns": [ + "userProfileId" + ], + "referenceTable": "serverpod_auth_core_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_core_session", + "dartName": "ServerSideSession", + "module": "serverpod_auth_core", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopeNames", + "fieldName": "scopeNames", + "columnType": 8, + "isNullable": false, + "dartType": "Set" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastUsedAt", + "fieldName": "lastUsedAt", + "columnType": 4, + "isNullable": false, + "columnDefault": "now", + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expireAfterUnusedFor", + "fieldName": "expireAfterUnusedFor", + "columnType": 6, + "isNullable": true, + "dartType": "Duration?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionKeyHash", + "fieldName": "sessionKeyHash", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionKeySalt", + "fieldName": "sessionKeySalt", + "columnType": 5, + "isNullable": false, + "dartType": "dart:typed_data:ByteData" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "method", + "fieldName": "method", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "serverpod_auth_core_session_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "serverpod_auth_core_user", + "dartName": "AuthUser", + "module": "serverpod_auth_core", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopeNames", + "fieldName": "scopeNames", + "columnType": 8, + "isNullable": false, + "dartType": "Set" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blocked", + "fieldName": "blocked", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + } + ], + "installedModules": [ + { + "__className__": "serverpod.DatabaseMigrationVersionModel", + "module": "wonky", + "version": "20261020084059086-publications" + }, + { + "__className__": "serverpod.DatabaseMigrationVersion", + "module": "serverpod", + "version": "20260824182259319" + }, + { + "__className__": "serverpod.DatabaseMigrationVersion", + "module": "serverpod_auth_idp", + "version": "20260924105404509" + }, + { + "__className__": "serverpod.DatabaseMigrationVersion", + "module": "serverpod_auth_core", + "version": "20260924105232991" + } + ], + "migrationApiVersion": 1 +} \ No newline at end of file diff --git a/wonky_server/migrations/20261020084059086-publications/definition.sql b/wonky_server/migrations/20261020084059086-publications/definition.sql new file mode 100644 index 00000000..9f5c9830 --- /dev/null +++ b/wonky_server/migrations/20261020084059086-publications/definition.sql @@ -0,0 +1,4299 @@ +BEGIN; + +-- +-- Function: gen_random_uuid_v7() +-- Source: https://gist.github.com/kjmph/5bd772b2c2df145aa645b837da7eca74 +-- License: MIT (copyright notice included on the generator source code). +-- +create or replace function gen_random_uuid_v7() +returns uuid +as $$ +begin + -- use random v4 uuid as starting point (which has the same variant we need) + -- then overlay timestamp + -- then set version 7 by flipping the 2 and 1 bit in the version 4 string + return encode( + set_bit( + set_bit( + overlay(uuid_send(gen_random_uuid()) + placing substring(int8send(floor(extract(epoch from clock_timestamp()) * 1000)::bigint) from 3) + from 1 for 6 + ), + 52, 1 + ), + 53, 1 + ), + 'hex')::uuid; +end +$$ +language plpgsql +volatile; + +-- +-- Class AccessRequest as table access_request +-- +CREATE TABLE "access_request" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "requesterId" bigint NOT NULL, + "requestedRole" text NOT NULL, + "message" text, + "createdAt" timestamp without time zone NOT NULL, + "handledAt" timestamp without time zone, + "handledById" bigint, + "outcome" text +); + +-- Indexes +CREATE INDEX "access_request_item_idx" ON "access_request" USING btree ("itemId", "handledAt"); + +-- +-- Class ActivityEvent as table activity_event +-- +CREATE TABLE "activity_event" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "actorId" bigint, + "actorKind" text NOT NULL, + "type" text NOT NULL, + "summary" text NOT NULL, + "at" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "activity_item_idx" ON "activity_event" USING btree ("itemId", "at"); + +-- +-- Class AiFunctionCache as table ai_function_cache +-- +CREATE TABLE "ai_function_cache" ( + "id" bigserial PRIMARY KEY, + "key" text NOT NULL, + "spreadsheetUuid" uuid NOT NULL, + "model" text NOT NULL, + "value" text NOT NULL, + "error" text, + "createdAt" timestamp without time zone NOT NULL, + "hits" bigint NOT NULL DEFAULT 0 +); + +-- Indexes +CREATE UNIQUE INDEX "ai_function_cache_key_idx" ON "ai_function_cache" USING btree ("key"); +CREATE INDEX "ai_function_cache_sheet_idx" ON "ai_function_cache" USING btree ("spreadsheetUuid"); + +-- +-- Class AiPreviewRecord as table ai_preview_record +-- +CREATE TABLE "ai_preview_record" ( + "id" bigserial PRIMARY KEY, + "previewId" text NOT NULL, + "userId" bigint NOT NULL, + "fileUuid" uuid NOT NULL, + "previewJson" text NOT NULL, + "changesJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "expiresAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "ai_preview_id_idx" ON "ai_preview_record" USING btree ("previewId"); +CREATE INDEX "ai_preview_expires_idx" ON "ai_preview_record" USING btree ("expiresAt"); + +-- +-- Class AiUsage as table ai_usage +-- +CREATE TABLE "ai_usage" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "model" text NOT NULL, + "feature" text NOT NULL, + "inputTokens" bigint NOT NULL, + "outputTokens" bigint NOT NULL, + "cacheReadTokens" bigint NOT NULL, + "cacheWriteTokens" bigint NOT NULL, + "at" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "ai_usage_user_at_idx" ON "ai_usage" USING btree ("userId", "at"); + +-- +-- Class AiUserKey as table ai_user_key +-- +CREATE TABLE "ai_user_key" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "provider" text NOT NULL, + "apiKey" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "ai_user_key_user_idx" ON "ai_user_key" USING btree ("userId"); + +-- +-- Class AiUserSetting as table ai_user_setting +-- +CREATE TABLE "ai_user_setting" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "quality" text NOT NULL DEFAULT 'best'::text, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "ai_user_setting_user_idx" ON "ai_user_setting" USING btree ("userId"); + +-- +-- Class AssistantMessage as table assistant_message +-- +CREATE TABLE "assistant_message" ( + "id" bigserial PRIMARY KEY, + "threadId" bigint NOT NULL, + "role" text NOT NULL, + "contentJson" text, + "displayText" text NOT NULL, + "toolCallsJson" text, + "visible" boolean NOT NULL DEFAULT true, + "replay" boolean NOT NULL DEFAULT true, + "runId" text, + "stopReason" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "assistant_message_thread_idx" ON "assistant_message" USING btree ("threadId", "id"); + +-- +-- Class AssistantThread as table assistant_thread +-- +CREATE TABLE "assistant_thread" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "itemId" bigint, + "title" text NOT NULL, + "contextRevision" bigint, + "contextMarkdown" text, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "assistant_thread_user_item_idx" ON "assistant_thread" USING btree ("userId", "itemId", "updatedAt"); + +-- +-- Class Banding as table banding +-- +CREATE TABLE "banding" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "rangeJson" text NOT NULL, + "styleJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "banding_file_idx" ON "banding" USING btree ("fileId", "id"); + +-- +-- Class BasicFilter as table basic_filter +-- +CREATE TABLE "basic_filter" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "rangeJson" text NOT NULL, + "criteriaJson" text NOT NULL, + "sortJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "basic_filter_file_idx" ON "basic_filter" USING btree ("fileId", "id"); + +-- +-- Class BoardAiUsage as table board_ai_usage +-- +CREATE TABLE "board_ai_usage" ( + "id" bigserial PRIMARY KEY, + "day" text NOT NULL, + "provider" text NOT NULL, + "model" text NOT NULL, + "feature" text NOT NULL, + "requests" bigint NOT NULL, + "inputTokens" bigint NOT NULL, + "outputTokens" bigint NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "board_ai_usage_idx" ON "board_ai_usage" USING btree ("day", "provider", "model", "feature"); + +-- +-- Class BoardBundleSuggestion as table board_bundle_suggestion +-- +CREATE TABLE "board_bundle_suggestion" ( + "id" bigserial PRIMARY KEY, + "title" text NOT NULL, + "rationale" text NOT NULL, + "area" text, + "postIds" json NOT NULL, + "state" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- +-- Class BoardComment as table board_comment +-- +CREATE TABLE "board_comment" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "postId" bigint, + "taskId" bigint, + "authorId" bigint, + "body" text NOT NULL, + "systemEvent" text, + "moderation" text NOT NULL, + "moderationReason" text, + "needsCheck" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL, + "editedAt" timestamp without time zone, + "deletedAt" timestamp without time zone, + "removedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "board_comment_uuid_idx" ON "board_comment" USING btree ("uuid"); +CREATE INDEX "board_comment_post_idx" ON "board_comment" USING btree ("postId", "createdAt"); +CREATE INDEX "board_comment_task_idx" ON "board_comment" USING btree ("taskId", "createdAt"); + +-- +-- Class BoardFlag as table board_flag +-- +CREATE TABLE "board_flag" ( + "id" bigserial PRIMARY KEY, + "postId" bigint, + "commentId" bigint, + "userId" bigint NOT NULL, + "reason" text NOT NULL, + "note" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "board_flag_post_idx" ON "board_flag" USING btree ("postId", "userId"); +CREATE INDEX "board_flag_comment_idx" ON "board_flag" USING btree ("commentId", "userId"); + +-- +-- Class BoardGithubDelivery as table board_github_delivery +-- +CREATE TABLE "board_github_delivery" ( + "id" bigserial PRIMARY KEY, + "deliveryId" text NOT NULL, + "event" text NOT NULL, + "receivedAt" timestamp without time zone NOT NULL, + "payload" text, + "processedAt" timestamp without time zone, + "attempts" bigint NOT NULL DEFAULT 0 +); + +-- Indexes +CREATE UNIQUE INDEX "board_github_delivery_idx" ON "board_github_delivery" USING btree ("deliveryId"); + +-- +-- Class BoardModerationLog as table board_moderation_log +-- +CREATE TABLE "board_moderation_log" ( + "id" bigserial PRIMARY KEY, + "adminId" bigint NOT NULL, + "action" text NOT NULL, + "targetKind" text NOT NULL, + "targetId" bigint NOT NULL, + "beforeJson" text, + "afterJson" text, + "reason" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "board_moderation_log_target_idx" ON "board_moderation_log" USING btree ("targetKind", "targetId"); + +-- +-- Class BoardPost as table board_post +-- +CREATE TABLE "board_post" ( + "id" bigserial PRIMARY KEY, + "authorId" bigint, + "kind" text NOT NULL, + "reportedKind" text NOT NULL, + "area" text, + "size" text, + "aiLabels" boolean NOT NULL DEFAULT true, + "title" text NOT NULL, + "body" text NOT NULL, + "contextJson" text, + "appHint" text NOT NULL, + "screenshotFileId" bigint, + "status" text NOT NULL, + "moderation" text NOT NULL, + "moderationReason" text, + "needsCheck" boolean NOT NULL DEFAULT false, + "editedByModerator" boolean NOT NULL DEFAULT false, + "triageState" text NOT NULL, + "triageJson" text, + "triageAttempts" bigint NOT NULL DEFAULT 0, + "suggestedTitle" text, + "summary" text, + "duplicateOfId" bigint, + "possibleDuplicateOfId" bigint, + "duplicateHintDismissed" boolean NOT NULL DEFAULT false, + "declineReason" text, + "taskId" bigint, + "score" bigint NOT NULL DEFAULT 0, + "voteCount" bigint NOT NULL DEFAULT 0, + "commentCount" bigint NOT NULL DEFAULT 0, + "flagCount" bigint NOT NULL DEFAULT 0, + "createdAt" timestamp without time zone NOT NULL, + "editedAt" timestamp without time zone, + "deletedAt" timestamp without time zone, + "removedAt" timestamp without time zone +); + +-- Indexes +CREATE INDEX "board_post_list_idx" ON "board_post" USING btree ("moderation", "kind", "status", "score"); +CREATE INDEX "board_post_author_idx" ON "board_post" USING btree ("authorId"); +CREATE INDEX "board_post_task_idx" ON "board_post" USING btree ("taskId"); + +-- +-- Class BoardPullRequest as table board_pull_request +-- +CREATE TABLE "board_pull_request" ( + "id" bigserial PRIMARY KEY, + "prNumber" bigint NOT NULL, + "taskId" bigint, + "authorLogin" text NOT NULL, + "headSha" text NOT NULL, + "state" text NOT NULL, + "gateState" text NOT NULL, + "gateReason" text, + "gateFirstFailedAt" timestamp without time zone, + "gateCommentId" bigint, + "reviewCommentId" bigint, + "lastReviewSha" text, + "lastReviewJson" text, + "lastReviewAt" timestamp without time zone, + "reviewDay" text, + "reviewCount" bigint NOT NULL DEFAULT 0, + "mergeCommitSha" text, + "reviewPendingSha" text, + "reviewDueAt" timestamp without time zone, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "board_pull_request_number_idx" ON "board_pull_request" USING btree ("prNumber"); + +-- +-- Class BoardTask as table board_task +-- +CREATE TABLE "board_task" ( + "id" bigserial PRIMARY KEY, + "title" text NOT NULL, + "area" text NOT NULL, + "size" text NOT NULL, + "status" text NOT NULL, + "promptBody" text NOT NULL, + "promptGeneratedAt" timestamp without time zone, + "promptRequestedAt" timestamp without time zone, + "promptNote" text, + "promptExcludedCommentIds" json, + "promptEditedById" bigint, + "promptEditedAt" timestamp without time zone, + "createdById" bigint NOT NULL, + "publishedAt" timestamp without time zone, + "claimedById" bigint, + "claimedAt" timestamp without time zone, + "claimExpiresAt" timestamp without time zone, + "claimWarnedAt" timestamp without time zone, + "claimCode" text, + "pullRequestUrl" text, + "prNumber" bigint, + "prAuthorLogin" text, + "mergeCommitSha" text, + "doneAt" timestamp without time zone, + "shippedDeploySha" text, + "shippedAt" timestamp without time zone, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "board_task_status_idx" ON "board_task" USING btree ("status"); +CREATE INDEX "board_task_claim_idx" ON "board_task" USING btree ("claimedById"); + +-- +-- Class BoardUserProfile as table board_user_profile +-- +CREATE TABLE "board_user_profile" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "githubLogin" text, + "blockedAt" timestamp without time zone, + "blockedUntil" timestamp without time zone, + "blockedReason" text, + "blockedById" bigint +); + +-- Indexes +CREATE UNIQUE INDEX "board_user_profile_user_idx" ON "board_user_profile" USING btree ("userId"); + +-- +-- Class BoardVote as table board_vote +-- +CREATE TABLE "board_vote" ( + "id" bigserial PRIMARY KEY, + "postId" bigint NOT NULL, + "userId" bigint NOT NULL, + "value" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "board_vote_unique_idx" ON "board_vote" USING btree ("postId", "userId"); +CREATE INDEX "board_vote_recent_idx" ON "board_vote" USING btree ("postId", "createdAt"); + +-- +-- Class Cell as table cell +-- +CREATE TABLE "cell" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "rowId" uuid NOT NULL, + "columnId" uuid NOT NULL, + "content" text, + "note" text, + "numberFormat" text, + "fontFamily" text, + "fontSize" double precision, + "bold" boolean, + "italic" boolean, + "underline" boolean, + "strikethrough" boolean, + "textColor" text, + "fillColor" text, + "hAlign" text, + "vAlign" text, + "wrap" text, + "rotation" bigint, + "borderTop" text, + "borderRight" text, + "borderBottom" text, + "borderLeft" text, + "linkUrl" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "cell_row_idx" ON "cell" USING btree ("sheetId", "rowId"); +CREATE INDEX "cell_col_idx" ON "cell" USING btree ("sheetId", "columnId"); + +-- +-- Class CellHistory as table cell_history +-- +CREATE TABLE "cell_history" ( + "id" bigserial PRIMARY KEY, + "fileUuid" uuid NOT NULL, + "sheetId" uuid NOT NULL, + "rowId" uuid NOT NULL, + "colId" uuid NOT NULL, + "revision" bigint NOT NULL, + "userUuid" uuid NOT NULL, + "actorKind" text NOT NULL, + "label" text NOT NULL, + "at" timestamp without time zone NOT NULL, + "before" text, + "after" text +); + +-- Indexes +CREATE INDEX "cell_history_cell_idx" ON "cell_history" USING btree ("fileUuid", "sheetId", "rowId", "colId", "at"); +CREATE UNIQUE INDEX "cell_history_change_idx" ON "cell_history" USING btree ("fileUuid", "revision", "rowId", "colId"); + +-- +-- Class ChartLink as table chart_link +-- +CREATE TABLE "chart_link" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "elementId" uuid NOT NULL, + "spreadsheetItemUuid" uuid NOT NULL, + "chartObjectId" uuid NOT NULL, + "sheetId" text, + "sourceSpecJson" text NOT NULL, + "dataSnapshotJson" text NOT NULL, + "sourceVersion" text NOT NULL, + "updatedAt" timestamp without time zone NOT NULL, + "updatedBy" uuid NOT NULL, + "autoUpdate" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "chart_link_file_idx" ON "chart_link" USING btree ("fileId", "id"); +CREATE INDEX "chart_link_element_idx" ON "chart_link" USING btree ("elementId"); + +-- +-- Class CodeState as table code_state +-- +CREATE TABLE "code_state" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "elementId" uuid NOT NULL, + "sortKey" text NOT NULL, + "label" text, + "code" text NOT NULL, + "language" text, + "title" text, + "highlight" text, + "annotationsJson" text, + "transitionJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "code_state_file_idx" ON "code_state" USING btree ("fileId", "id"); +CREATE INDEX "code_state_element_idx" ON "code_state" USING btree ("elementId", "sortKey"); + +-- +-- Class Comment as table comment +-- +CREATE TABLE "comment" ( + "id" bigserial PRIMARY KEY, + "threadId" bigint NOT NULL, + "uuid" uuid, + "authorId" bigint, + "authorKind" text NOT NULL, + "body" text NOT NULL, + "mentions" json NOT NULL, + "reactions" text NOT NULL DEFAULT '{}'::text, + "createdAt" timestamp without time zone NOT NULL, + "editedAt" timestamp without time zone, + "deletedAt" timestamp without time zone, + "systemEvent" text, + "publicationId" bigint +); + +-- Indexes +CREATE INDEX "comment_thread_idx" ON "comment" USING btree ("threadId", "createdAt"); +CREATE UNIQUE INDEX "comment_uuid_idx" ON "comment" USING btree ("uuid"); + +-- +-- Class CommentThread as table comment_thread +-- +CREATE TABLE "comment_thread" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "itemId" bigint NOT NULL, + "anchorKind" text NOT NULL, + "anchorJson" text NOT NULL, + "quotedText" text, + "status" text NOT NULL DEFAULT 'open'::text, + "createdById" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone, + "resolvedById" bigint, + "resolvedAt" timestamp without time zone, + "assigneeId" bigint, + "statusBeforeOrphan" text, + "orphanReasonJson" text, + "suggestionId" text +); + +-- Indexes +CREATE INDEX "comment_thread_item_idx" ON "comment_thread" USING btree ("itemId", "status"); +CREATE UNIQUE INDEX "comment_thread_uuid_idx" ON "comment_thread" USING btree ("uuid"); + +-- +-- Class ConditionalFormatRule as table conditional_format_rule +-- +CREATE TABLE "conditional_format_rule" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "sortKey" text NOT NULL, + "rangesJson" text NOT NULL, + "ruleJson" text NOT NULL, + "enabled" boolean NOT NULL DEFAULT true, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "conditional_format_rule_file_idx" ON "conditional_format_rule" USING btree ("fileId", "id"); + +-- +-- Class DataValidationRule as table data_validation_rule +-- +CREATE TABLE "data_validation_rule" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "rangesJson" text NOT NULL, + "criteriaJson" text NOT NULL, + "strict" boolean NOT NULL DEFAULT false, + "showDropdown" boolean NOT NULL DEFAULT true, + "displayStyle" text, + "helpText" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "data_validation_rule_file_idx" ON "data_validation_rule" USING btree ("fileId", "id"); + +-- +-- Class Deck as table deck +-- +CREATE TABLE "deck" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "title" text NOT NULL, + "width" double precision NOT NULL DEFAULT 1920.0, + "height" double precision NOT NULL DEFAULT 1080.0, + "sizePreset" text NOT NULL DEFAULT 'widescreen16x9'::text, + "themeId" uuid, + "appearance" text NOT NULL DEFAULT 'light'::text, + "language" text, + "showSlideNumbers" boolean NOT NULL DEFAULT false, + "hideNumberOnTitle" boolean NOT NULL DEFAULT true, + "firstSlideNumber" bigint NOT NULL DEFAULT 1, + "footerText" text, + "defaultsJson" text, + "guidesJson" text, + "presentJson" text, + "createdBy" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "deck_file_idx" ON "deck" USING btree ("fileId", "id"); + +-- +-- Class DeckTheme as table deck_theme +-- +CREATE TABLE "deck_theme" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "deckId" uuid NOT NULL, + "name" text NOT NULL, + "sourceKey" text, + "colorsJson" text NOT NULL, + "fontsJson" text NOT NULL, + "textStylesJson" text NOT NULL, + "backgroundJson" text NOT NULL, + "shapeStyleJson" text, + "tableStyleJson" text, + "codeStyleJson" text, + "chartStyleJson" text, + "sortKey" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "deck_theme_file_idx" ON "deck_theme" USING btree ("fileId", "id"); +CREATE INDEX "deck_theme_deck_idx" ON "deck_theme" USING btree ("deckId"); + +-- +-- Class DimensionGroup as table dimension_group +-- +CREATE TABLE "dimension_group" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "dimension" text NOT NULL, + "startId" uuid NOT NULL, + "endId" uuid NOT NULL, + "depth" bigint NOT NULL, + "collapsed" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "dimension_group_file_idx" ON "dimension_group" USING btree ("fileId", "id"); + +-- +-- Class Document as table document +-- +CREATE TABLE "document" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "itemId" bigint NOT NULL, + "headRevision" bigint NOT NULL DEFAULT 0, + "latestSnapshotRevision" bigint NOT NULL DEFAULT 0, + "themeId" uuid, + "pageSetupJson" text NOT NULL DEFAULT '{}'::text, + "language" text, + "frontMatter" text, + "charCount" bigint NOT NULL DEFAULT 0, + "wordCount" bigint NOT NULL DEFAULT 0, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "document_uuid_idx" ON "document" USING btree ("uuid"); +CREATE UNIQUE INDEX "document_item_idx" ON "document" USING btree ("itemId"); + +-- +-- Class DocumentImportReport as table document_import_report +-- +CREATE TABLE "document_import_report" ( + "id" bigserial PRIMARY KEY, + "documentId" bigint NOT NULL, + "userId" bigint NOT NULL, + "warningsJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "seenAt" timestamp without time zone +); + +-- Indexes +CREATE INDEX "document_import_report_idx" ON "document_import_report" USING btree ("documentId", "userId"); + +-- +-- Class DocumentMetaChange as table document_meta_change +-- +CREATE TABLE "document_meta_change" ( + "id" bigserial PRIMARY KEY, + "documentId" bigint NOT NULL, + "field" text NOT NULL, + "clientOpId" uuid, + "beforeJson" text NOT NULL, + "afterJson" text NOT NULL, + "authorId" bigint, + "actorKind" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "document_meta_change_idx" ON "document_meta_change" USING btree ("documentId", "createdAt"); +CREATE UNIQUE INDEX "document_meta_change_client_idx" ON "document_meta_change" USING btree ("documentId", "clientOpId"); + +-- +-- Class DocumentOp as table document_op +-- +CREATE TABLE "document_op" ( + "id" bigserial PRIMARY KEY, + "documentId" bigint NOT NULL, + "revision" bigint NOT NULL, + "clientOpId" uuid NOT NULL, + "authorId" bigint, + "actorKind" text NOT NULL, + "sessionId" text, + "kind" text NOT NULL, + "baseRevision" bigint NOT NULL, + "deltaJson" text NOT NULL, + "inverseJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "document_op_rev_idx" ON "document_op" USING btree ("documentId", "revision"); +CREATE UNIQUE INDEX "document_op_client_idx" ON "document_op" USING btree ("documentId", "clientOpId"); +CREATE INDEX "document_op_created_idx" ON "document_op" USING brin ("createdAt"); + +-- +-- Class DocumentSnapshot as table document_snapshot +-- +CREATE TABLE "document_snapshot" ( + "id" bigserial PRIMARY KEY, + "documentId" bigint NOT NULL, + "revision" bigint NOT NULL, + "deltaJson" text NOT NULL, + "compressed" boolean NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "document_snapshot_idx" ON "document_snapshot" USING btree ("documentId", "revision"); + +-- +-- Class DriveItem as table drive_item +-- +CREATE TABLE "drive_item" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "kind" text NOT NULL, + "name" text NOT NULL, + "ownerId" bigint NOT NULL, + "parentId" bigint, + "description" text, + "contentRef" uuid, + "thumbnailFileId" uuid, + "sizeBytes" bigint NOT NULL DEFAULT 0, + "attachmentBytes" bigint NOT NULL DEFAULT 0, + "kindMask" bigint NOT NULL DEFAULT 0, + "mimeType" text, + "fileCategory" text, + "uploadState" text, + "fileMetaJson" text, + "previewFileId" uuid, + "createdAt" timestamp without time zone NOT NULL, + "createdById" bigint NOT NULL, + "modifiedAt" timestamp without time zone NOT NULL, + "modifiedById" bigint, + "trashedAt" timestamp without time zone, + "trashedById" bigint, + "templateOf" text, + "templateKey" text, + "editorsCanShare" boolean NOT NULL DEFAULT true, + "nonEditorsCanExport" boolean NOT NULL DEFAULT true, + "viewersSeeComments" boolean NOT NULL DEFAULT false, + "searchText" text +); + +-- Indexes +CREATE UNIQUE INDEX "drive_item_uuid_idx" ON "drive_item" USING btree ("uuid"); +CREATE INDEX "drive_item_parent_idx" ON "drive_item" USING btree ("parentId"); +CREATE INDEX "drive_item_owner_idx" ON "drive_item" USING btree ("ownerId", "trashedAt"); +CREATE INDEX "drive_item_content_idx" ON "drive_item" USING btree ("contentRef"); +CREATE INDEX "drive_item_template_idx" ON "drive_item" USING btree ("templateOf"); +CREATE INDEX "drive_item_upload_idx" ON "drive_item" USING btree ("uploadState", "createdAt"); +CREATE INDEX "drive_item_trashed_idx" ON "drive_item" USING btree ("trashedAt"); + +-- +-- Class DriveItemPermission as table drive_item_permission +-- +CREATE TABLE "drive_item_permission" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "userId" bigint, + "invitedEmail" text, + "role" text NOT NULL, + "inheritedFromId" bigint, + "grantedById" bigint NOT NULL, + "grantedAt" timestamp without time zone NOT NULL, + "expiresAt" timestamp without time zone, + "viaPublicationId" bigint +); + +-- Indexes +CREATE UNIQUE INDEX "perm_item_user_idx" ON "drive_item_permission" USING btree ("itemId", "userId", "inheritedFromId", "invitedEmail") NULLS NOT DISTINCT; +CREATE INDEX "perm_user_idx" ON "drive_item_permission" USING btree ("userId"); +CREATE INDEX "perm_email_idx" ON "drive_item_permission" USING btree ("invitedEmail"); +CREATE INDEX "perm_expires_idx" ON "drive_item_permission" USING btree ("expiresAt"); + +-- +-- Class DriveItemUserState as table drive_item_user_state +-- +CREATE TABLE "drive_item_user_state" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "userId" bigint NOT NULL, + "starred" boolean NOT NULL DEFAULT false, + "lastOpenedAt" timestamp without time zone, + "lastEditedAt" timestamp without time zone, + "pinnedOffline" boolean NOT NULL DEFAULT false, + "shortcutParentId" bigint, + "viaLink" boolean NOT NULL DEFAULT false +); + +-- Indexes +CREATE UNIQUE INDEX "drive_item_user_state_idx" ON "drive_item_user_state" USING btree ("itemId", "userId"); +CREATE INDEX "drive_item_user_recent_idx" ON "drive_item_user_state" USING btree ("userId", "lastOpenedAt"); + +-- +-- Class EmbeddedObject as table embedded_object +-- +CREATE TABLE "embedded_object" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "kind" text NOT NULL, + "anchorJson" text NOT NULL, + "specJson" text NOT NULL, + "zIndex" bigint NOT NULL DEFAULT 0, + "title" text, + "altText" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "embedded_object_file_idx" ON "embedded_object" USING btree ("fileId", "id"); + +-- +-- Class FeedbackReport as table feedback_report +-- +CREATE TABLE "feedback_report" ( + "id" bigserial PRIMARY KEY, + "userId" bigint, + "kind" text NOT NULL, + "message" text NOT NULL, + "app" text NOT NULL, + "appVersion" text NOT NULL, + "platform" text NOT NULL, + "route" text, + "stackTrace" text, + "contextJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "feedback_report_created_idx" ON "feedback_report" USING btree ("createdAt"); + +-- +-- Class FilterView as table filter_view +-- +CREATE TABLE "filter_view" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "name" text NOT NULL, + "rangeJson" text NOT NULL, + "criteriaJson" text NOT NULL, + "sortJson" text, + "createdBy" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "filter_view_file_idx" ON "filter_view" USING btree ("fileId", "id"); + +-- +-- Class HeadlessChange as table headless_change +-- +CREATE TABLE "headless_change" ( + "id" bigserial PRIMARY KEY, + "changeId" uuid NOT NULL, + "kind" text NOT NULL, + "itemId" bigint NOT NULL, + "documentId" bigint, + "revision" bigint, + "inverseJson" text, + "metaField" text, + "metaBeforeJson" text, + "metaAfterJson" text, + "userId" bigint NOT NULL, + "actorKind" text NOT NULL, + "label" text, + "toolName" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "revertedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "headless_change_id_idx" ON "headless_change" USING btree ("changeId"); +CREATE INDEX "headless_change_created_idx" ON "headless_change" USING btree ("createdAt"); + +-- +-- Class ItemVersion as table item_version +-- +CREATE TABLE "item_version" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "kind" text NOT NULL, + "name" text, + "createdAt" timestamp without time zone NOT NULL, + "createdById" bigint, + "authors" json NOT NULL, + "storageKind" text NOT NULL, + "revision" bigint, + "snapshotFileId" uuid, + "sizeBytes" bigint NOT NULL DEFAULT 0 +); + +-- Indexes +CREATE INDEX "item_version_item_idx" ON "item_version" USING btree ("itemId", "createdAt"); + +-- +-- Class ItemVersionState as table item_version_state +-- +CREATE TABLE "item_version_state" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "lastEditAt" timestamp without time zone NOT NULL, + "dirtySince" timestamp without time zone, + "lastVersionAt" timestamp without time zone, + "editorsSinceLastVersion" json NOT NULL, + "lastRevision" bigint, + "capturingSince" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "item_version_state_item_idx" ON "item_version_state" USING btree ("itemId"); +CREATE INDEX "item_version_state_dirty_idx" ON "item_version_state" USING btree ("dirtySince"); + +-- +-- Class ItemViewDay as table item_view_day +-- +CREATE TABLE "item_view_day" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "userId" bigint NOT NULL, + "day" timestamp without time zone NOT NULL, + "views" bigint NOT NULL DEFAULT 1, + "lastViewedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "item_view_day_idx" ON "item_view_day" USING btree ("itemId", "userId", "day"); +CREATE INDEX "item_view_day_item_idx" ON "item_view_day" USING btree ("itemId", "day"); + +-- +-- Class Macro as table macro +-- +CREATE TABLE "macro" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "projectId" uuid NOT NULL, + "name" text NOT NULL, + "functionName" text NOT NULL, + "shortcutSlot" bigint, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "macro_file_idx" ON "macro" USING btree ("fileId", "id"); + +-- +-- Class MergedRange as table merged_range +-- +CREATE TABLE "merged_range" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "rangeJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "merged_range_file_idx" ON "merged_range" USING btree ("fileId", "id"); + +-- +-- Class NamedRange as table named_range +-- +CREATE TABLE "named_range" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "spreadsheetId" uuid NOT NULL, + "name" text NOT NULL, + "rangeJson" text, + "formula" text, + "comment" text, + "metaJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "named_range_file_idx" ON "named_range" USING btree ("fileId", "id"); + +-- +-- Class UserNotification as table notification +-- +CREATE TABLE "notification" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "kind" text NOT NULL, + "itemId" bigint, + "actorId" bigint, + "payload" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "readAt" timestamp without time zone, + "emailedAt" timestamp without time zone, + "emailPending" boolean DEFAULT false +); + +-- Indexes +CREATE INDEX "notification_user_idx" ON "notification" USING btree ("userId", "createdAt"); +CREATE INDEX "notification_email_idx" ON "notification" USING btree ("emailPending", "createdAt"); +CREATE INDEX "notification_created_idx" ON "notification" USING brin ("createdAt"); + +-- +-- Class OwnershipTransfer as table ownership_transfer +-- +CREATE TABLE "ownership_transfer" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "fromUserId" bigint NOT NULL, + "toUserId" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "handledAt" timestamp without time zone, + "accepted" boolean +); + +-- Indexes +CREATE INDEX "ownership_transfer_item_idx" ON "ownership_transfer" USING btree ("itemId", "handledAt"); + +-- +-- Class PersonalAccessToken as table personal_access_token +-- +CREATE TABLE "personal_access_token" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "name" text NOT NULL, + "tokenHash" text NOT NULL, + "prefix" text NOT NULL, + "scopes" json NOT NULL, + "expiresAt" timestamp without time zone, + "lastUsedAt" timestamp without time zone, + "createdAt" timestamp without time zone NOT NULL, + "revokedAt" timestamp without time zone +); + +-- Indexes +CREATE INDEX "personal_access_token_user_idx" ON "personal_access_token" USING btree ("userId"); +CREATE UNIQUE INDEX "personal_access_token_hash_idx" ON "personal_access_token" USING btree ("tokenHash"); + +-- +-- Class PivotTable as table pivot_table +-- +CREATE TABLE "pivot_table" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "anchorRowId" uuid NOT NULL, + "anchorColId" uuid NOT NULL, + "sourceRangeJson" text NOT NULL, + "specJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "pivot_table_file_idx" ON "pivot_table" USING btree ("fileId", "id"); + +-- +-- Class ProtectedRange as table protected_range +-- +CREATE TABLE "protected_range" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "rangeJson" text, + "exceptRangesJson" text, + "description" text, + "warningOnly" boolean NOT NULL DEFAULT false, + "editorsJson" text NOT NULL, + "createdBy" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "protected_range_file_idx" ON "protected_range" USING btree ("fileId", "id"); + +-- +-- Class Publication as table publication +-- +CREATE TABLE "publication" ( + "id" bigserial PRIMARY KEY, + "publicId" text NOT NULL, + "ownerId" bigint NOT NULL, + "name" text NOT NULL, + "siteUrl" text NOT NULL, + "webhookUrl" text NOT NULL, + "verifiedHost" text, + "verifiedAt" timestamp without time zone, + "templateItemId" bigint, + "termsUrl" text, + "fields" json NOT NULL, + "signingSecret" text NOT NULL, + "previousSigningSecret" text, + "previousSecretUntil" timestamp without time zone, + "apiKeyHash" text, + "apiKeyLast4" text, + "enabled" boolean NOT NULL DEFAULT true, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_public_idx" ON "publication" USING btree ("publicId"); +CREATE INDEX "publication_owner_idx" ON "publication" USING btree ("ownerId"); +CREATE INDEX "publication_api_key_idx" ON "publication" USING btree ("apiKeyHash"); + +-- +-- Class PublicationBlock as table publication_block +-- +CREATE TABLE "publication_block" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "userId" bigint NOT NULL, + "at" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_block_idx" ON "publication_block" USING btree ("publicationId", "userId"); + +-- +-- Class PublicationConsent as table publication_consent +-- +CREATE TABLE "publication_consent" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "userId" bigint NOT NULL, + "consentKey" text NOT NULL, + "at" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_consent_idx" ON "publication_consent" USING btree ("publicationId", "userId"); + +-- +-- Class PublicationDelivery as table publication_delivery +-- +CREATE TABLE "publication_delivery" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "submissionId" bigint, + "webhookId" text NOT NULL, + "type" text NOT NULL, + "sequence" bigint, + "payload" text NOT NULL, + "attempts" bigint NOT NULL DEFAULT 0, + "nextAttemptAt" timestamp without time zone, + "leaseUntil" timestamp without time zone, + "lastStatus" bigint, + "lastError" text, + "deliveredAt" timestamp without time zone, + "failedAt" timestamp without time zone, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_delivery_webhook_idx" ON "publication_delivery" USING btree ("webhookId"); +CREATE INDEX "publication_delivery_due_idx" ON "publication_delivery" USING btree ("nextAttemptAt"); +CREATE INDEX "publication_delivery_publication_idx" ON "publication_delivery" USING btree ("publicationId", "createdAt"); + +-- +-- Class PublicationModerator as table publication_moderator +-- +CREATE TABLE "publication_moderator" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "userId" bigint, + "email" text NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_moderator_idx" ON "publication_moderator" USING btree ("publicationId", "email"); +CREATE INDEX "publication_moderator_user_idx" ON "publication_moderator" USING btree ("userId"); + +-- +-- Class RevFile as table rev_file +-- +CREATE TABLE "rev_file" ( + "id" bigserial PRIMARY KEY, + "fileUuid" uuid NOT NULL, + "kind" text NOT NULL, + "itemId" bigint NOT NULL, + "headRevision" bigint NOT NULL DEFAULT 0, + "prunedBelow" bigint NOT NULL DEFAULT 0, + "initPending" boolean NOT NULL DEFAULT false, + "purging" boolean NOT NULL DEFAULT false, + "schemaHash" text NOT NULL, + "stats" text NOT NULL DEFAULT '{}'::text, + "contentCount" bigint NOT NULL DEFAULT 0, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "rev_file_uuid_idx" ON "rev_file" USING btree ("fileUuid"); +CREATE UNIQUE INDEX "rev_file_item_idx" ON "rev_file" USING btree ("itemId"); + +-- +-- Class RevHookState as table rev_hook_state +-- +CREATE TABLE "rev_hook_state" ( + "id" bigserial PRIMARY KEY, + "fileId" bigint NOT NULL, + "cursorsJson" text NOT NULL, + "leaseOwner" text, + "leaseUntil" timestamp without time zone, + "attempts" bigint NOT NULL DEFAULT 0, + "lastError" text, + "nextAttemptAt" timestamp without time zone, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "rev_hook_state_file_idx" ON "rev_hook_state" USING btree ("fileId"); +CREATE INDEX "rev_hook_state_due_idx" ON "rev_hook_state" USING btree ("nextAttemptAt"); + +-- +-- Class RevOp as table rev_op +-- +CREATE TABLE "rev_op" ( + "id" bigserial PRIMARY KEY, + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL, + "clientOpId" uuid NOT NULL, + "baseRevision" bigint NOT NULL, + "authorId" bigint, + "authorUuid" uuid, + "sessionId" text, + "onBehalfOfSessionId" text, + "actorKind" text NOT NULL, + "label" text NOT NULL, + "groupId" text, + "groupIndex" bigint NOT NULL DEFAULT 0, + "groupLast" boolean NOT NULL DEFAULT true, + "recordId" uuid, + "offline" boolean NOT NULL DEFAULT false, + "payload" bytea, + "changeCount" bigint NOT NULL, + "summaryJson" text, + "detailJson" text, + "outcomeJson" text, + "appliedEqualsSubmitted" boolean NOT NULL, + "clientCreatedAt" timestamp without time zone, + "committedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "rev_op_rev_idx" ON "rev_op" USING btree ("fileId", "revision"); +CREATE UNIQUE INDEX "rev_op_client_idx" ON "rev_op" USING btree ("fileId", "clientOpId"); +CREATE INDEX "rev_op_record_idx" ON "rev_op" USING btree ("recordId"); +CREATE INDEX "rev_op_committed_idx" ON "rev_op" USING brin ("committedAt"); + +-- +-- Class ScriptAuthorization as table script_authorization +-- +CREATE TABLE "script_authorization" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "spreadsheetUuid" uuid NOT NULL, + "scopes" json NOT NULL, + "grantedAt" timestamp without time zone NOT NULL, + "revokedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "script_auth_user_sheet_idx" ON "script_authorization" USING btree ("userId", "spreadsheetUuid"); + +-- +-- Class ScriptBuild as table script_build +-- +CREATE TABLE "script_build" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "projectId" uuid NOT NULL, + "status" text NOT NULL DEFAULT 'ok'::text, + "sourceHash" text NOT NULL, + "bytecodeFileUuid" uuid, + "diagnosticsJson" text NOT NULL, + "exportsJson" text NOT NULL, + "apiVersion" bigint NOT NULL DEFAULT 1, + "compilerVersion" text NOT NULL DEFAULT ''::text, + "requestedBy" uuid, + "lastGoodSourceHash" text, + "lastGoodBytecodeFileUuid" uuid, + "lastGoodExportsJson" text, + "lastGoodBuiltAt" timestamp without time zone, + "positionsFileUuid" uuid, + "builtAt" timestamp without time zone NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "script_build_file_idx" ON "script_build" USING btree ("fileId", "id"); + +-- +-- Class ScriptExecution as table script_execution +-- +CREATE TABLE "script_execution" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "spreadsheetUuid" uuid NOT NULL, + "projectId" uuid, + "functionName" text NOT NULL, + "kind" text NOT NULL, + "triggerId" uuid, + "userId" bigint NOT NULL, + "runAsUserId" bigint NOT NULL, + "runtime" text NOT NULL, + "status" text NOT NULL, + "buildSourceHash" text NOT NULL, + "startedAt" timestamp without time zone NOT NULL, + "durationMs" bigint NOT NULL, + "logs" text NOT NULL, + "errorMessage" text, + "errorStackJson" text, + "changeId" uuid, + "cellsRead" bigint NOT NULL, + "cellsWritten" bigint NOT NULL, + "fetchCalls" bigint NOT NULL, + "callCount" bigint NOT NULL DEFAULT 1 +); + +-- Indexes +CREATE UNIQUE INDEX "script_exec_uuid_idx" ON "script_execution" USING btree ("uuid"); +CREATE INDEX "script_exec_sheet_idx" ON "script_execution" USING btree ("spreadsheetUuid", "startedAt"); +CREATE INDEX "script_exec_user_idx" ON "script_execution" USING btree ("userId", "startedAt"); + +-- +-- Class ScriptFile as table script_file +-- +CREATE TABLE "script_file" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "projectId" uuid NOT NULL, + "name" text NOT NULL, + "sortKey" text NOT NULL, + "source" text NOT NULL, + "contentHash" text NOT NULL, + "updatedBy" uuid NOT NULL, + "updatedAt" timestamp without time zone NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "script_file_file_idx" ON "script_file" USING btree ("fileId", "id"); + +-- +-- Class ScriptJob as table script_job +-- +CREATE TABLE "script_job" ( + "id" bigserial PRIMARY KEY, + "kind" text NOT NULL, + "spreadsheetUuid" uuid NOT NULL, + "itemUuid" uuid NOT NULL, + "triggerId" uuid, + "runAsUserId" bigint NOT NULL, + "functionName" text NOT NULL, + "payloadJson" text NOT NULL, + "status" text NOT NULL, + "enqueuedAt" timestamp without time zone NOT NULL, + "leaseOwner" text, + "leaseUntil" timestamp without time zone, + "attempts" bigint NOT NULL DEFAULT 0, + "coalesced" bigint NOT NULL DEFAULT 0, + "resultJson" text, + "finishedAt" timestamp without time zone +); + +-- Indexes +CREATE INDEX "script_job_status_idx" ON "script_job" USING btree ("status", "enqueuedAt"); +CREATE INDEX "script_job_trigger_idx" ON "script_job" USING btree ("triggerId", "status"); +CREATE INDEX "script_job_user_idx" ON "script_job" USING btree ("runAsUserId", "status"); + +-- +-- Class ScriptProject as table script_project +-- +CREATE TABLE "script_project" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "spreadsheetId" uuid NOT NULL, + "name" text NOT NULL, + "settingsJson" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "script_project_file_idx" ON "script_project" USING btree ("fileId", "id"); + +-- +-- Class ScriptProperty as table script_property +-- +CREATE TABLE "script_property" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "projectId" uuid NOT NULL, + "key" text NOT NULL, + "value" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "script_property_file_idx" ON "script_property" USING btree ("fileId", "id"); + +-- +-- Class ScriptQuotaUsage as table script_quota_usage +-- +CREATE TABLE "script_quota_usage" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "day" timestamp without time zone NOT NULL, + "serverRuntimeMs" bigint NOT NULL DEFAULT 0, + "clientRuntimeMs" bigint NOT NULL DEFAULT 0, + "urlFetchCalls" bigint NOT NULL DEFAULT 0, + "urlFetchBytes" bigint NOT NULL DEFAULT 0, + "triggerRuns" bigint NOT NULL DEFAULT 0 +); + +-- Indexes +CREATE UNIQUE INDEX "script_quota_user_day_idx" ON "script_quota_usage" USING btree ("userId", "day"); + +-- +-- Class ScriptTrigger as table script_trigger +-- +CREATE TABLE "script_trigger" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "projectId" uuid NOT NULL, + "kind" text NOT NULL, + "functionName" text NOT NULL, + "scheduleJson" text, + "runAsUserId" uuid NOT NULL, + "enabled" boolean NOT NULL DEFAULT true, + "optionsJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "script_trigger_file_idx" ON "script_trigger" USING btree ("fileId", "id"); + +-- +-- Class ScriptTriggerState as table script_trigger_state +-- +CREATE TABLE "script_trigger_state" ( + "id" bigserial PRIMARY KEY, + "triggerId" uuid NOT NULL, + "spreadsheetUuid" uuid NOT NULL, + "scheduleJson" text, + "nextRunAt" timestamp without time zone, + "lastRunAt" timestamp without time zone, + "lastStatus" text, + "consecutiveFailures" bigint NOT NULL DEFAULT 0, + "disabledReason" text, + "runningSince" timestamp without time zone, + "lastNotifiedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "script_trigger_state_id_idx" ON "script_trigger_state" USING btree ("triggerId"); +CREATE INDEX "script_trigger_state_due_idx" ON "script_trigger_state" USING btree ("nextRunAt"); + +-- +-- Class ScriptUserProperty as table script_user_property +-- +CREATE TABLE "script_user_property" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "fileUuid" uuid NOT NULL, + "key" text NOT NULL, + "value" text NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "script_user_property_idx" ON "script_user_property" USING btree ("userId", "fileUuid", "key"); + +-- +-- Class ServerChangeRecord as table server_change_record +-- +CREATE TABLE "server_change_record" ( + "id" bigserial PRIMARY KEY, + "changeId" uuid NOT NULL, + "fileUuid" uuid NOT NULL, + "userId" bigint NOT NULL, + "actorKind" text NOT NULL, + "label" text NOT NULL, + "inverseJson" text, + "inverseFileId" uuid, + "forwardFileId" uuid, + "recordId" uuid, + "cellsAffected" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "expiresAt" timestamp without time zone NOT NULL, + "revertedAt" timestamp without time zone, + "revertChangeId" uuid +); + +-- Indexes +CREATE INDEX "server_change_record_idx" ON "server_change_record" USING btree ("recordId"); +CREATE INDEX "server_change_file_idx" ON "server_change_record" USING btree ("fileUuid", "createdAt"); +CREATE UNIQUE INDEX "server_change_id_idx" ON "server_change_record" USING btree ("changeId"); + +-- +-- Class ShareLink as table share_link +-- +CREATE TABLE "share_link" ( + "id" bigserial PRIMARY KEY, + "itemId" bigint NOT NULL, + "token" text NOT NULL, + "role" text, + "createdById" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "share_link_item_idx" ON "share_link" USING btree ("itemId"); +CREATE UNIQUE INDEX "share_link_token_idx" ON "share_link" USING btree ("token"); + +-- +-- Class Sheet as table sheet +-- +CREATE TABLE "sheet" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "spreadsheetId" uuid NOT NULL, + "name" text NOT NULL, + "sortKey" text NOT NULL, + "kind" text NOT NULL DEFAULT 'grid'::text, + "hidden" boolean NOT NULL DEFAULT false, + "tabColor" text, + "rightToLeft" boolean NOT NULL DEFAULT false, + "showGridlines" boolean NOT NULL DEFAULT true, + "frozenRows" bigint NOT NULL DEFAULT 0, + "frozenColumns" bigint NOT NULL DEFAULT 0, + "defaultRowHeight" double precision NOT NULL DEFAULT 21.0, + "defaultColumnWidth" double precision NOT NULL DEFAULT 100.0, + "formatJson" text, + "printSettingsJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "sheet_file_idx" ON "sheet" USING btree ("fileId", "id"); +CREATE INDEX "sheet_order_idx" ON "sheet" USING btree ("spreadsheetId", "sortKey"); + +-- +-- Class SheetColumn as table sheet_column +-- +CREATE TABLE "sheet_column" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "sortKey" text NOT NULL, + "width" double precision, + "hidden" boolean NOT NULL DEFAULT false, + "formatJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "sheet_column_file_idx" ON "sheet_column" USING btree ("fileId", "id"); +CREATE INDEX "sheet_column_order_idx" ON "sheet_column" USING btree ("sheetId", "sortKey"); + +-- +-- Class SheetRow as table sheet_row +-- +CREATE TABLE "sheet_row" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "sheetId" uuid NOT NULL, + "sortKey" text NOT NULL, + "height" double precision, + "hidden" boolean NOT NULL DEFAULT false, + "formatJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "sheet_row_file_idx" ON "sheet_row" USING btree ("fileId", "id"); +CREATE INDEX "sheet_row_order_idx" ON "sheet_row" USING btree ("sheetId", "sortKey"); + +-- +-- Class SheetsImportJob as table sheets_import_job +-- +CREATE TABLE "sheets_import_job" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "userId" bigint NOT NULL, + "authUserId" uuid NOT NULL, + "spreadsheetUuid" uuid NOT NULL, + "uploadFileId" uuid NOT NULL, + "fileName" text NOT NULL, + "format" text NOT NULL, + "optionsJson" text NOT NULL, + "activeSheetId" text, + "status" text NOT NULL, + "progressDone" bigint NOT NULL, + "progressTotal" bigint NOT NULL, + "reportJson" text, + "sheetIdsJson" text, + "changeId" uuid, + "errorCode" text, + "error" text, + "cancelRequested" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL, + "leaseOwner" text, + "leaseUntil" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "sheets_import_job_uuid_idx" ON "sheets_import_job" USING btree ("uuid"); +CREATE INDEX "sheets_import_job_user_idx" ON "sheets_import_job" USING btree ("userId", "status"); + +-- +-- Class SheetsSnapshotIndex as table sheets_snapshot_index +-- +CREATE TABLE "sheets_snapshot_index" ( + "id" bigserial PRIMARY KEY, + "itemVersionId" bigint NOT NULL, + "sheetsJson" text NOT NULL, + "changedRangesJson" text NOT NULL, + "authorIds" json NOT NULL, + "diffFileId" uuid +); + +-- Indexes +CREATE UNIQUE INDEX "sheets_snapshot_index_version_idx" ON "sheets_snapshot_index" USING btree ("itemVersionId"); + +-- +-- Class Slide as table slide +-- +CREATE TABLE "slide" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "deckId" uuid NOT NULL, + "sortKey" text NOT NULL, + "groupId" uuid, + "layoutId" uuid, + "backgroundJson" text, + "skipped" boolean NOT NULL DEFAULT false, + "notes" text, + "transitionJson" text, + "hideMasterElements" boolean, + "timingsJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_file_idx" ON "slide" USING btree ("fileId", "id"); +CREATE INDEX "slide_order_idx" ON "slide" USING btree ("deckId", "sortKey"); + +-- +-- Class SlideBuild as table slide_build +-- +CREATE TABLE "slide_build" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "slideId" uuid NOT NULL, + "elementId" uuid NOT NULL, + "kind" text NOT NULL, + "effect" text NOT NULL, + "sortKey" text NOT NULL, + "trigger" text NOT NULL, + "delayMs" bigint NOT NULL DEFAULT 0, + "durationMs" bigint NOT NULL, + "easing" text NOT NULL, + "optionsJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_build_file_idx" ON "slide_build" USING btree ("fileId", "id"); +CREATE INDEX "slide_build_slide_idx" ON "slide_build" USING btree ("slideId", "sortKey"); +CREATE INDEX "slide_build_element_idx" ON "slide_build" USING btree ("elementId"); + +-- +-- Class SlideElement as table slide_element +-- +CREATE TABLE "slide_element" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "slideId" uuid, + "layoutId" uuid, + "masterId" uuid, + "parentId" uuid, + "kind" text NOT NULL, + "name" text, + "x" double precision, + "y" double precision, + "width" double precision, + "height" double precision, + "rotation" double precision, + "flipH" boolean NOT NULL DEFAULT false, + "flipV" boolean NOT NULL DEFAULT false, + "zKey" text NOT NULL, + "readingKey" text, + "locked" boolean NOT NULL DEFAULT false, + "hidden" boolean NOT NULL DEFAULT false, + "placeholderType" text, + "placeholderOf" uuid, + "matchKey" text NOT NULL, + "text" text, + "textStyleJson" text, + "fillJson" text, + "strokeJson" text, + "effectsJson" text, + "opacity" double precision, + "dataJson" text, + "linkJson" text, + "altText" text, + "decorative" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_element_file_idx" ON "slide_element" USING btree ("fileId", "id"); +CREATE INDEX "slide_element_slide_idx" ON "slide_element" USING btree ("slideId", "zKey"); +CREATE INDEX "slide_element_layout_idx" ON "slide_element" USING btree ("layoutId"); +CREATE INDEX "slide_element_master_idx" ON "slide_element" USING btree ("masterId"); +CREATE INDEX "slide_element_parent_idx" ON "slide_element" USING btree ("parentId"); + +-- +-- Class SlideGroup as table slide_group +-- +CREATE TABLE "slide_group" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "deckId" uuid NOT NULL, + "title" text NOT NULL, + "sortKey" text NOT NULL, + "parentId" uuid, + "color" text, + "skipped" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_group_file_idx" ON "slide_group" USING btree ("fileId", "id"); +CREATE INDEX "slide_group_order_idx" ON "slide_group" USING btree ("deckId", "sortKey"); + +-- +-- Class SlideLayout as table slide_layout +-- +CREATE TABLE "slide_layout" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "masterId" uuid NOT NULL, + "name" text NOT NULL, + "key" text, + "sortKey" text NOT NULL, + "backgroundJson" text, + "hideMasterElements" boolean NOT NULL DEFAULT false, + "hidden" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_layout_file_idx" ON "slide_layout" USING btree ("fileId", "id"); +CREATE INDEX "slide_layout_master_idx" ON "slide_layout" USING btree ("masterId"); + +-- +-- Class SlideMaster as table slide_master +-- +CREATE TABLE "slide_master" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "themeId" uuid NOT NULL, + "name" text NOT NULL, + "sortKey" text NOT NULL, + "backgroundJson" text, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_master_file_idx" ON "slide_master" USING btree ("fileId", "id"); +CREATE INDEX "slide_master_theme_idx" ON "slide_master" USING btree ("themeId"); + +-- +-- Class SlideTableAxis as table slide_table_axis +-- +CREATE TABLE "slide_table_axis" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "elementId" uuid NOT NULL, + "dimension" text NOT NULL, + "sortKey" text NOT NULL, + "size" double precision, + "header" boolean NOT NULL DEFAULT false, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_table_axis_file_idx" ON "slide_table_axis" USING btree ("fileId", "id"); +CREATE INDEX "slide_table_axis_element_idx" ON "slide_table_axis" USING btree ("elementId", "sortKey"); + +-- +-- Class SlideTableCell as table slide_table_cell +-- +CREATE TABLE "slide_table_cell" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "elementId" uuid NOT NULL, + "rowId" uuid NOT NULL, + "columnId" uuid NOT NULL, + "text" text, + "fill" text, + "borderTop" text, + "borderRight" text, + "borderBottom" text, + "borderLeft" text, + "vAlign" text, + "padding" text, + "rowSpan" bigint, + "colSpan" bigint, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "slide_table_cell_file_idx" ON "slide_table_cell" USING btree ("fileId", "id"); +CREATE INDEX "slide_table_cell_element_idx" ON "slide_table_cell" USING btree ("elementId"); + +-- +-- Class SlidesSnapshotIndex as table slides_snapshot_index +-- +CREATE TABLE "slides_snapshot_index" ( + "id" bigserial PRIMARY KEY, + "itemVersionId" bigint NOT NULL, + "slidesJson" text NOT NULL, + "changesJson" text NOT NULL, + "authorIds" json NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "slides_snapshot_index_version_idx" ON "slides_snapshot_index" USING btree ("itemVersionId"); + +-- +-- Class Spreadsheet as table spreadsheet +-- +CREATE TABLE "spreadsheet" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "fileId" bigint NOT NULL, + "revision" bigint NOT NULL DEFAULT 0, + "title" text NOT NULL, + "locale" text NOT NULL, + "timeZone" text NOT NULL, + "recalcMode" text NOT NULL DEFAULT 'onChange'::text, + "iterativeCalc" boolean NOT NULL DEFAULT false, + "maxIterations" bigint NOT NULL DEFAULT 50, + "convergenceThreshold" double precision NOT NULL DEFAULT 0.05, + "defaultFontFamily" text NOT NULL DEFAULT 'Inter'::text, + "defaultFontSize" double precision NOT NULL DEFAULT 10.0, + "themeJson" text NOT NULL, + "displayLanguage" text, + "createdBy" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "spreadsheet_file_idx" ON "spreadsheet" USING btree ("fileId", "id"); + +-- +-- Class StorageReservation as table storage_reservation +-- +CREATE TABLE "storage_reservation" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "fileUuid" uuid NOT NULL, + "itemId" bigint, + "bytes" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "expiresAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "storage_reservation_file_idx" ON "storage_reservation" USING btree ("fileUuid"); +CREATE INDEX "storage_reservation_user_idx" ON "storage_reservation" USING btree ("userId"); +CREATE INDEX "storage_reservation_expiry_idx" ON "storage_reservation" USING btree ("expiresAt"); + +-- +-- Class StoredFile as table stored_file +-- +CREATE TABLE "stored_file" ( + "id" bigserial PRIMARY KEY, + "fileUuid" uuid NOT NULL, + "ownerId" bigint, + "itemId" bigint, + "kind" text NOT NULL, + "storageId" text NOT NULL, + "path" text NOT NULL, + "fileName" text NOT NULL, + "mimeType" text NOT NULL, + "sizeBytes" bigint NOT NULL, + "status" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "completedAt" timestamp without time zone, + "expiresAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "stored_file_uuid_idx" ON "stored_file" USING btree ("fileUuid"); +CREATE INDEX "stored_file_item_idx" ON "stored_file" USING btree ("itemId"); +CREATE INDEX "stored_file_expiry_idx" ON "stored_file" USING btree ("expiresAt"); +CREATE INDEX "stored_file_owner_kind_idx" ON "stored_file" USING btree ("ownerId", "kind", "createdAt"); +CREATE INDEX "stored_file_status_idx" ON "stored_file" USING btree ("status", "createdAt"); + +-- +-- Class Submission as table submission +-- +CREATE TABLE "submission" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "publicationId" bigint NOT NULL, + "itemId" bigint NOT NULL, + "ref" text, + "status" text NOT NULL, + "statusBeforeSubmit" text, + "delivery" text, + "values" json NOT NULL, + "publicUrl" text, + "feedbackThreadId" bigint, + "createdById" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL, + "disconnectedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "submission_uuid_idx" ON "submission" USING btree ("uuid"); +CREATE UNIQUE INDEX "submission_item_idx" ON "submission" USING btree ("itemId"); +CREATE INDEX "submission_publication_idx" ON "submission" USING btree ("publicationId", "status"); + +-- +-- Class SubmissionAsset as table submission_asset +-- +CREATE TABLE "submission_asset" ( + "id" bigserial PRIMARY KEY, + "submissionId" bigint NOT NULL, + "fileUuid" uuid NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "submission_asset_idx" ON "submission_asset" USING btree ("submissionId", "fileUuid"); +CREATE INDEX "submission_asset_file_idx" ON "submission_asset" USING btree ("fileUuid"); + +-- +-- Class SubmissionRevision as table submission_revision +-- +CREATE TABLE "submission_revision" ( + "id" bigserial PRIMARY KEY, + "submissionId" bigint NOT NULL, + "sequence" bigint NOT NULL, + "revision" bigint NOT NULL, + "versionId" bigint, + "values" json NOT NULL, + "payload" text NOT NULL, + "submittedById" bigint NOT NULL, + "submittedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "submission_revision_idx" ON "submission_revision" USING btree ("submissionId", "sequence"); + +-- +-- Class UserActivitySettings as table user_activity_settings +-- +CREATE TABLE "user_activity_settings" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "showViewHistory" boolean NOT NULL DEFAULT true, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "user_activity_settings_user_idx" ON "user_activity_settings" USING btree ("userId"); + +-- +-- Class UserPreferences as table user_preferences +-- +CREATE TABLE "user_preferences" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "appTheme" text NOT NULL DEFAULT 'system'::text, + "accentColor" text, + "density" text NOT NULL DEFAULT 'comfortable'::text, + "reduceMotion" boolean NOT NULL DEFAULT false, + "keymapOverrides" text NOT NULL DEFAULT '{}'::text, + "writeDefaults" text NOT NULL DEFAULT '{}'::text, + "sheetsDefaults" text NOT NULL DEFAULT '{}'::text, + "slidesDefaults" text NOT NULL DEFAULT '{}'::text, + "slidesPresenter" text NOT NULL DEFAULT '{}'::text, + "driveDefaults" text NOT NULL DEFAULT '{}'::text, + "notificationSettings" text NOT NULL DEFAULT '{}'::text, + "aiEnabled" boolean NOT NULL DEFAULT true, + "updatedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "user_preferences_user_idx" ON "user_preferences" USING btree ("userId"); + +-- +-- Class UserProfile as table user_profile +-- +CREATE TABLE "user_profile" ( + "id" bigserial PRIMARY KEY, + "authUserId" uuid NOT NULL, + "displayName" text NOT NULL, + "email" text NOT NULL, + "avatarFileId" uuid, + "avatarColor" text NOT NULL, + "locale" text, + "timeZone" text, + "createdAt" timestamp without time zone NOT NULL, + "lastSeenAt" timestamp without time zone, + "welcomeContentAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "user_profile_auth_idx" ON "user_profile" USING btree ("authUserId"); +CREATE UNIQUE INDEX "user_profile_email_idx" ON "user_profile" USING btree ("email"); + +-- +-- Class UserStorage as table user_storage +-- +CREATE TABLE "user_storage" ( + "id" bigserial PRIMARY KEY, + "userId" bigint NOT NULL, + "usedBytes" bigint NOT NULL DEFAULT 0, + "reservedBytes" bigint NOT NULL DEFAULT 0, + "documentsBytes" bigint NOT NULL DEFAULT 0, + "spreadsheetsBytes" bigint NOT NULL DEFAULT 0, + "presentationsBytes" bigint NOT NULL DEFAULT 0, + "filesBytes" bigint NOT NULL DEFAULT 0, + "trashBytes" bigint NOT NULL DEFAULT 0, + "quotaBytesOverride" bigint, + "overQuotaSince" timestamp without time zone, + "reconciledAt" timestamp without time zone, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "user_storage_user_idx" ON "user_storage" USING btree ("userId"); + +-- +-- Class WriteDiffCache as table write_diff_cache +-- +CREATE TABLE "write_diff_cache" ( + "id" bigserial PRIMARY KEY, + "documentId" bigint NOT NULL, + "fromRevision" bigint NOT NULL, + "toRevision" bigint NOT NULL, + "json" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "write_diff_cache_idx" ON "write_diff_cache" USING btree ("documentId", "fromRevision", "toRevision"); +CREATE INDEX "write_diff_cache_created_idx" ON "write_diff_cache" USING brin ("createdAt"); + +-- +-- Class WriteTheme as table write_theme +-- +CREATE TABLE "write_theme" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "ownerId" bigint, + "isBuiltin" boolean NOT NULL, + "builtinKey" text, + "name" text NOT NULL, + "description" text, + "schemaVersion" bigint NOT NULL, + "version" bigint NOT NULL, + "json" text NOT NULL, + "contentHash" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL, + "deletedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "write_theme_uuid_idx" ON "write_theme" USING btree ("uuid"); +CREATE INDEX "write_theme_owner_idx" ON "write_theme" USING btree ("ownerId", "deletedAt"); +CREATE UNIQUE INDEX "write_theme_builtin_idx" ON "write_theme" USING btree ("builtinKey"); + +-- +-- Class WriteThemeRevision as table write_theme_revision +-- +CREATE TABLE "write_theme_revision" ( + "id" bigserial PRIMARY KEY, + "themeId" bigint NOT NULL, + "version" bigint NOT NULL, + "json" text NOT NULL, + "savedById" bigint, + "actorKind" text NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "write_theme_rev_idx" ON "write_theme_revision" USING btree ("themeId", "version"); + +-- +-- Class CloudStorageEntry as table serverpod_cloud_storage +-- +CREATE TABLE "serverpod_cloud_storage" ( + "id" bigserial PRIMARY KEY, + "storageId" text NOT NULL, + "path" text NOT NULL, + "addedTime" timestamp without time zone NOT NULL, + "expiration" timestamp without time zone, + "byteData" bytea NOT NULL, + "verified" boolean NOT NULL, + "contentType" text, + "cacheControl" text, + "contentDisposition" text, + "contentEncoding" text, + "customMetadata" text +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_cloud_storage_path_idx" ON "serverpod_cloud_storage" USING btree ("storageId", "path"); +CREATE INDEX "serverpod_cloud_storage_expiration" ON "serverpod_cloud_storage" USING btree ("expiration"); + +-- +-- Class CloudStorageDirectDownloadEntry as table serverpod_cloud_storage_direct_download +-- +CREATE TABLE "serverpod_cloud_storage_direct_download" ( + "id" bigserial PRIMARY KEY, + "storageId" text NOT NULL, + "path" text NOT NULL, + "expiration" timestamp without time zone NOT NULL, + "authKey" text NOT NULL, + "downloadFileName" text, + "contentType" text +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_cloud_storage_direct_download_auth_key" ON "serverpod_cloud_storage_direct_download" USING btree ("authKey"); +CREATE INDEX "serverpod_cloud_storage_direct_download_expiration" ON "serverpod_cloud_storage_direct_download" USING btree ("expiration"); + +-- +-- Class CloudStorageDirectUploadEntry as table serverpod_cloud_storage_direct_upload +-- +CREATE TABLE "serverpod_cloud_storage_direct_upload" ( + "id" bigserial PRIMARY KEY, + "storageId" text NOT NULL, + "path" text NOT NULL, + "expiration" timestamp without time zone NOT NULL, + "authKey" text NOT NULL, + "maxFileSize" bigint NOT NULL DEFAULT 10485760, + "contentLength" bigint, + "preventOverwrite" boolean NOT NULL DEFAULT false, + "contentType" text, + "cacheControl" text, + "contentDisposition" text, + "contentEncoding" text, + "customMetadata" text +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_cloud_storage_direct_upload_storage_path" ON "serverpod_cloud_storage_direct_upload" USING btree ("storageId", "path"); + +-- +-- Class FutureCallEntry as table serverpod_future_call +-- +CREATE TABLE "serverpod_future_call" ( + "id" bigserial PRIMARY KEY, + "name" text NOT NULL, + "time" timestamp without time zone NOT NULL, + "serializedObject" text, + "serverId" text NOT NULL, + "identifier" text, + "scheduling" json +); + +-- Indexes +CREATE INDEX "serverpod_future_call_time_idx" ON "serverpod_future_call" USING btree ("time"); +CREATE INDEX "serverpod_future_call_serverId_idx" ON "serverpod_future_call" USING btree ("serverId"); +CREATE INDEX "serverpod_future_call_identifier_idx" ON "serverpod_future_call" USING btree ("identifier"); + +-- +-- Class FutureCallClaimEntry as table serverpod_future_call_claim +-- +CREATE TABLE "serverpod_future_call_claim" ( + "id" bigserial PRIMARY KEY, + "futureCallId" bigint, + "lastHeartbeatTime" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "future_call_unique_idx" ON "serverpod_future_call_claim" USING btree ("futureCallId"); + +-- +-- Class ServerHealthConnectionInfo as table serverpod_health_connection_info +-- +CREATE TABLE "serverpod_health_connection_info" ( + "id" bigserial PRIMARY KEY, + "serverId" text NOT NULL, + "timestamp" timestamp without time zone NOT NULL, + "active" bigint NOT NULL, + "closing" bigint NOT NULL, + "idle" bigint NOT NULL, + "granularity" bigint NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_health_connection_info_timestamp_idx" ON "serverpod_health_connection_info" USING btree ("timestamp", "serverId", "granularity"); + +-- +-- Class ServerHealthMetric as table serverpod_health_metric +-- +CREATE TABLE "serverpod_health_metric" ( + "id" bigserial PRIMARY KEY, + "name" text NOT NULL, + "serverId" text NOT NULL, + "timestamp" timestamp without time zone NOT NULL, + "isHealthy" boolean NOT NULL, + "value" double precision NOT NULL, + "granularity" bigint NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_health_metric_timestamp_idx" ON "serverpod_health_metric" USING btree ("timestamp", "serverId", "name", "granularity"); + +-- +-- Class LogEntry as table serverpod_log +-- +CREATE TABLE "serverpod_log" ( + "id" bigserial PRIMARY KEY, + "sessionLogId" bigint NOT NULL, + "messageId" bigint, + "reference" text, + "serverId" text NOT NULL, + "time" timestamp without time zone NOT NULL, + "logLevel" bigint NOT NULL, + "message" text NOT NULL, + "error" text, + "stackTrace" text, + "order" bigint NOT NULL +); + +-- Indexes +CREATE INDEX "serverpod_log_sessionLogId_idx" ON "serverpod_log" USING btree ("sessionLogId", "order"); + +-- +-- Class MessageLogEntry as table serverpod_message_log +-- +CREATE TABLE "serverpod_message_log" ( + "id" bigserial PRIMARY KEY, + "sessionLogId" bigint NOT NULL, + "serverId" text NOT NULL, + "messageId" bigint NOT NULL, + "endpoint" text NOT NULL, + "messageName" text NOT NULL, + "duration" double precision NOT NULL, + "error" text, + "stackTrace" text, + "slow" boolean NOT NULL, + "order" bigint NOT NULL +); + +-- Indexes +CREATE INDEX "serverpod_message_log_sessionLogId_idx" ON "serverpod_message_log" USING btree ("sessionLogId", "order"); + +-- +-- Class MethodInfo as table serverpod_method +-- +CREATE TABLE "serverpod_method" ( + "id" bigserial PRIMARY KEY, + "endpoint" text NOT NULL, + "method" text NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_method_endpoint_method_idx" ON "serverpod_method" USING btree ("endpoint", "method"); + +-- +-- Class DatabaseMigrationVersion as table serverpod_migrations +-- +CREATE TABLE "serverpod_migrations" ( + "id" bigserial PRIMARY KEY, + "module" text NOT NULL, + "version" text NOT NULL, + "timestamp" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_migrations_ids" ON "serverpod_migrations" USING btree ("module"); + +-- +-- Class QueryLogEntry as table serverpod_query_log +-- +CREATE TABLE "serverpod_query_log" ( + "id" bigserial PRIMARY KEY, + "serverId" text NOT NULL, + "sessionLogId" bigint NOT NULL, + "messageId" bigint, + "query" text NOT NULL, + "duration" double precision NOT NULL, + "numRows" bigint, + "error" text, + "stackTrace" text, + "slow" boolean NOT NULL, + "order" bigint NOT NULL +); + +-- Indexes +CREATE INDEX "serverpod_query_log_sessionLogId_idx" ON "serverpod_query_log" USING btree ("sessionLogId", "order"); + +-- +-- Class ReadWriteTestEntry as table serverpod_readwrite_test +-- +CREATE TABLE "serverpod_readwrite_test" ( + "id" bigserial PRIMARY KEY, + "number" bigint NOT NULL +); + +-- +-- Class RuntimeSettings as table serverpod_runtime_settings +-- +CREATE TABLE "serverpod_runtime_settings" ( + "id" bigserial PRIMARY KEY, + "logSettings" json NOT NULL, + "logSettingsOverrides" json NOT NULL, + "logServiceCalls" boolean NOT NULL, + "logMalformedCalls" boolean NOT NULL +); + +-- +-- Class SessionLogEntry as table serverpod_session_log +-- +CREATE TABLE "serverpod_session_log" ( + "id" bigserial PRIMARY KEY, + "serverId" text NOT NULL, + "time" timestamp without time zone NOT NULL, + "module" text, + "endpoint" text, + "method" text, + "duration" double precision, + "numQueries" bigint, + "slow" boolean, + "error" text, + "stackTrace" text, + "authenticatedUserId" bigint, + "userId" text, + "isOpen" boolean, + "touched" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE INDEX "serverpod_session_log_serverid_idx" ON "serverpod_session_log" USING btree ("serverId"); +CREATE INDEX "serverpod_session_log_time_idx" ON "serverpod_session_log" USING btree ("time"); +CREATE INDEX "serverpod_session_log_touched_idx" ON "serverpod_session_log" USING btree ("touched"); +CREATE INDEX "serverpod_session_log_isopen_idx" ON "serverpod_session_log" USING btree ("isOpen"); + +-- +-- Class AnonymousAccount as table serverpod_auth_idp_anonymous_account +-- +CREATE TABLE "serverpod_auth_idp_anonymous_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL +); + +-- +-- Class AppleAccount as table serverpod_auth_idp_apple_account +-- +CREATE TABLE "serverpod_auth_idp_apple_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "userIdentifier" text NOT NULL, + "refreshToken" text NOT NULL, + "refreshTokenRequestedWithBundleIdentifier" boolean NOT NULL, + "lastRefreshedAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "authUserId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "email" text, + "isEmailVerified" boolean, + "isPrivateEmail" boolean, + "firstName" text, + "lastName" text +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_apple_account_identifier" ON "serverpod_auth_idp_apple_account" USING btree ("userIdentifier"); + +-- +-- Class EmailAccount as table serverpod_auth_idp_email_account +-- +CREATE TABLE "serverpod_auth_idp_email_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "email" text NOT NULL, + "passwordHash" text NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_idp_email_account_email" ON "serverpod_auth_idp_email_account" USING btree ("email"); + +-- +-- Class EmailAccountPasswordResetRequest as table serverpod_auth_idp_email_account_password_reset_request +-- +CREATE TABLE "serverpod_auth_idp_email_account_password_reset_request" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "emailAccountId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "challengeId" uuid NOT NULL, + "setPasswordChallengeId" uuid +); + +-- +-- Class EmailAccountRequest as table serverpod_auth_idp_email_account_request +-- +CREATE TABLE "serverpod_auth_idp_email_account_request" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "createdAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "email" text NOT NULL, + "challengeId" uuid NOT NULL, + "createAccountChallengeId" uuid +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_idp_email_account_request_email" ON "serverpod_auth_idp_email_account_request" USING btree ("email"); + +-- +-- Class FacebookAccount as table serverpod_auth_idp_facebook_account +-- +CREATE TABLE "serverpod_auth_idp_facebook_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "userIdentifier" text NOT NULL, + "email" text, + "fullName" text, + "firstName" text, + "lastName" text +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_facebook_account_user_identifier" ON "serverpod_auth_idp_facebook_account" USING btree ("userIdentifier"); + +-- +-- Class FirebaseAccount as table serverpod_auth_idp_firebase_account +-- +CREATE TABLE "serverpod_auth_idp_firebase_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "created" timestamp without time zone NOT NULL, + "email" text, + "phone" text, + "userIdentifier" text NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_firebase_account_user_identifier" ON "serverpod_auth_idp_firebase_account" USING btree ("userIdentifier"); + +-- +-- Class GitHubAccount as table serverpod_auth_idp_github_account +-- +CREATE TABLE "serverpod_auth_idp_github_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "userIdentifier" text NOT NULL, + "email" text, + "created" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_github_account_user_identifier" ON "serverpod_auth_idp_github_account" USING btree ("userIdentifier"); + +-- +-- Class GoogleAccount as table serverpod_auth_idp_google_account +-- +CREATE TABLE "serverpod_auth_idp_google_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "created" timestamp without time zone NOT NULL, + "email" text NOT NULL, + "userIdentifier" text NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_google_account_user_identifier" ON "serverpod_auth_idp_google_account" USING btree ("userIdentifier"); + +-- +-- Class MicrosoftAccount as table serverpod_auth_idp_microsoft_account +-- +CREATE TABLE "serverpod_auth_idp_microsoft_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "userIdentifier" text NOT NULL, + "email" text, + "created" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_microsoft_account_user_identifier" ON "serverpod_auth_idp_microsoft_account" USING btree ("userIdentifier"); + +-- +-- Class PasskeyAccount as table serverpod_auth_idp_passkey_account +-- +CREATE TABLE "serverpod_auth_idp_passkey_account" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "keyId" bytea NOT NULL, + "keyIdBase64" text NOT NULL, + "clientDataJSON" bytea NOT NULL, + "attestationObject" bytea NOT NULL, + "originalChallenge" bytea NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_idp_passkey_account_key_id_base64" ON "serverpod_auth_idp_passkey_account" USING btree ("keyIdBase64"); + +-- +-- Class PasskeyChallenge as table serverpod_auth_idp_passkey_challenge +-- +CREATE TABLE "serverpod_auth_idp_passkey_challenge" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "createdAt" timestamp without time zone NOT NULL, + "challenge" bytea NOT NULL +); + +-- +-- Class RateLimitedRequestAttempt as table serverpod_auth_idp_rate_limited_request_attempt +-- +CREATE TABLE "serverpod_auth_idp_rate_limited_request_attempt" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "domain" text NOT NULL, + "source" text NOT NULL, + "key" text NOT NULL, + "ipAddress" text, + "attemptedAt" timestamp without time zone NOT NULL, + "extraData" json +); + +-- Indexes +CREATE INDEX "serverpod_auth_idp_rate_limited_request_attempt_composite" ON "serverpod_auth_idp_rate_limited_request_attempt" USING btree ("domain", "source", "key", "attemptedAt"); + +-- +-- Class SecretChallenge as table serverpod_auth_idp_secret_challenge +-- +CREATE TABLE "serverpod_auth_idp_secret_challenge" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "challengeCodeHash" text NOT NULL +); + +-- +-- Class RefreshToken as table serverpod_auth_core_jwt_refresh_token +-- +CREATE TABLE "serverpod_auth_core_jwt_refresh_token" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "scopeNames" json NOT NULL, + "extraClaims" text, + "method" text NOT NULL, + "fixedSecret" bytea NOT NULL, + "rotatingSecretHash" text NOT NULL, + "lastUpdatedAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "createdAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP +); + +-- Indexes +CREATE INDEX "serverpod_auth_core_jwt_refresh_token_last_updated_at" ON "serverpod_auth_core_jwt_refresh_token" USING btree ("lastUpdatedAt"); + +-- +-- Class UserProfile as table serverpod_auth_core_profile +-- +CREATE TABLE "serverpod_auth_core_profile" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "userName" text, + "fullName" text, + "email" text, + "createdAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "imageId" uuid +); + +-- Indexes +CREATE UNIQUE INDEX "serverpod_auth_profile_user_profile_email_auth_user_id" ON "serverpod_auth_core_profile" USING btree ("authUserId"); + +-- +-- Class UserProfileImage as table serverpod_auth_core_profile_image +-- +CREATE TABLE "serverpod_auth_core_profile_image" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "userProfileId" uuid NOT NULL, + "createdAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "storageId" text NOT NULL, + "path" text NOT NULL, + "url" text NOT NULL +); + +-- +-- Class ServerSideSession as table serverpod_auth_core_session +-- +CREATE TABLE "serverpod_auth_core_session" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "authUserId" uuid NOT NULL, + "scopeNames" json NOT NULL, + "createdAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "lastUsedAt" timestamp without time zone NOT NULL DEFAULT CURRENT_TIMESTAMP, + "expiresAt" timestamp without time zone, + "expireAfterUnusedFor" bigint, + "sessionKeyHash" bytea NOT NULL, + "sessionKeySalt" bytea NOT NULL, + "method" text NOT NULL +); + +-- +-- Class AuthUser as table serverpod_auth_core_user +-- +CREATE TABLE "serverpod_auth_core_user" ( + "id" uuid PRIMARY KEY DEFAULT gen_random_uuid_v7(), + "createdAt" timestamp without time zone NOT NULL, + "scopeNames" json NOT NULL, + "blocked" boolean NOT NULL +); + +-- +-- Foreign relations for "access_request" table +-- +ALTER TABLE ONLY "access_request" + ADD CONSTRAINT "access_request_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "access_request" + ADD CONSTRAINT "access_request_fk_1" + FOREIGN KEY("requesterId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "activity_event" table +-- +ALTER TABLE ONLY "activity_event" + ADD CONSTRAINT "activity_event_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "ai_usage" table +-- +ALTER TABLE ONLY "ai_usage" + ADD CONSTRAINT "ai_usage_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "ai_user_key" table +-- +ALTER TABLE ONLY "ai_user_key" + ADD CONSTRAINT "ai_user_key_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "ai_user_setting" table +-- +ALTER TABLE ONLY "ai_user_setting" + ADD CONSTRAINT "ai_user_setting_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "assistant_message" table +-- +ALTER TABLE ONLY "assistant_message" + ADD CONSTRAINT "assistant_message_fk_0" + FOREIGN KEY("threadId") + REFERENCES "assistant_thread"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "assistant_thread" table +-- +ALTER TABLE ONLY "assistant_thread" + ADD CONSTRAINT "assistant_thread_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "assistant_thread" + ADD CONSTRAINT "assistant_thread_fk_1" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "banding" table +-- +ALTER TABLE ONLY "banding" + ADD CONSTRAINT "banding_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "banding" + ADD CONSTRAINT "banding_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "basic_filter" table +-- +ALTER TABLE ONLY "basic_filter" + ADD CONSTRAINT "basic_filter_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "basic_filter" + ADD CONSTRAINT "basic_filter_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "board_comment" table +-- +ALTER TABLE ONLY "board_comment" + ADD CONSTRAINT "board_comment_fk_0" + FOREIGN KEY("postId") + REFERENCES "board_post"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_comment" + ADD CONSTRAINT "board_comment_fk_1" + FOREIGN KEY("taskId") + REFERENCES "board_task"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_comment" + ADD CONSTRAINT "board_comment_fk_2" + FOREIGN KEY("authorId") + REFERENCES "user_profile"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "board_flag" table +-- +ALTER TABLE ONLY "board_flag" + ADD CONSTRAINT "board_flag_fk_0" + FOREIGN KEY("postId") + REFERENCES "board_post"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_flag" + ADD CONSTRAINT "board_flag_fk_1" + FOREIGN KEY("commentId") + REFERENCES "board_comment"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_flag" + ADD CONSTRAINT "board_flag_fk_2" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "board_post" table +-- +ALTER TABLE ONLY "board_post" + ADD CONSTRAINT "board_post_fk_0" + FOREIGN KEY("authorId") + REFERENCES "user_profile"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_post" + ADD CONSTRAINT "board_post_fk_1" + FOREIGN KEY("screenshotFileId") + REFERENCES "stored_file"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_post" + ADD CONSTRAINT "board_post_fk_2" + FOREIGN KEY("taskId") + REFERENCES "board_task"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "board_pull_request" table +-- +ALTER TABLE ONLY "board_pull_request" + ADD CONSTRAINT "board_pull_request_fk_0" + FOREIGN KEY("taskId") + REFERENCES "board_task"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "board_task" table +-- +ALTER TABLE ONLY "board_task" + ADD CONSTRAINT "board_task_fk_0" + FOREIGN KEY("claimedById") + REFERENCES "user_profile"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "board_user_profile" table +-- +ALTER TABLE ONLY "board_user_profile" + ADD CONSTRAINT "board_user_profile_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "board_vote" table +-- +ALTER TABLE ONLY "board_vote" + ADD CONSTRAINT "board_vote_fk_0" + FOREIGN KEY("postId") + REFERENCES "board_post"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "board_vote" + ADD CONSTRAINT "board_vote_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "cell" table +-- +ALTER TABLE ONLY "cell" + ADD CONSTRAINT "cell_fk_0" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "chart_link" table +-- +ALTER TABLE ONLY "chart_link" + ADD CONSTRAINT "chart_link_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "chart_link" + ADD CONSTRAINT "chart_link_fk_1" + FOREIGN KEY("elementId") + REFERENCES "slide_element"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "code_state" table +-- +ALTER TABLE ONLY "code_state" + ADD CONSTRAINT "code_state_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "code_state" + ADD CONSTRAINT "code_state_fk_1" + FOREIGN KEY("elementId") + REFERENCES "slide_element"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "comment" table +-- +ALTER TABLE ONLY "comment" + ADD CONSTRAINT "comment_fk_0" + FOREIGN KEY("threadId") + REFERENCES "comment_thread"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "comment" + ADD CONSTRAINT "comment_fk_1" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "comment_thread" table +-- +ALTER TABLE ONLY "comment_thread" + ADD CONSTRAINT "comment_thread_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "conditional_format_rule" table +-- +ALTER TABLE ONLY "conditional_format_rule" + ADD CONSTRAINT "conditional_format_rule_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "conditional_format_rule" + ADD CONSTRAINT "conditional_format_rule_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "data_validation_rule" table +-- +ALTER TABLE ONLY "data_validation_rule" + ADD CONSTRAINT "data_validation_rule_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "data_validation_rule" + ADD CONSTRAINT "data_validation_rule_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "deck" table +-- +ALTER TABLE ONLY "deck" + ADD CONSTRAINT "deck_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "deck_theme" table +-- +ALTER TABLE ONLY "deck_theme" + ADD CONSTRAINT "deck_theme_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "deck_theme" + ADD CONSTRAINT "deck_theme_fk_1" + FOREIGN KEY("deckId") + REFERENCES "deck"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "dimension_group" table +-- +ALTER TABLE ONLY "dimension_group" + ADD CONSTRAINT "dimension_group_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "dimension_group" + ADD CONSTRAINT "dimension_group_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "document" table +-- +ALTER TABLE ONLY "document" + ADD CONSTRAINT "document_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "document_import_report" table +-- +ALTER TABLE ONLY "document_import_report" + ADD CONSTRAINT "document_import_report_fk_0" + FOREIGN KEY("documentId") + REFERENCES "document"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "document_meta_change" table +-- +ALTER TABLE ONLY "document_meta_change" + ADD CONSTRAINT "document_meta_change_fk_0" + FOREIGN KEY("documentId") + REFERENCES "document"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "document_op" table +-- +ALTER TABLE ONLY "document_op" + ADD CONSTRAINT "document_op_fk_0" + FOREIGN KEY("documentId") + REFERENCES "document"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "document_snapshot" table +-- +ALTER TABLE ONLY "document_snapshot" + ADD CONSTRAINT "document_snapshot_fk_0" + FOREIGN KEY("documentId") + REFERENCES "document"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "drive_item" table +-- +ALTER TABLE ONLY "drive_item" + ADD CONSTRAINT "drive_item_fk_0" + FOREIGN KEY("ownerId") + REFERENCES "user_profile"("id") + ON DELETE RESTRICT + ON UPDATE NO ACTION; +ALTER TABLE ONLY "drive_item" + ADD CONSTRAINT "drive_item_fk_1" + FOREIGN KEY("parentId") + REFERENCES "drive_item"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "drive_item_permission" table +-- +ALTER TABLE ONLY "drive_item_permission" + ADD CONSTRAINT "drive_item_permission_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "drive_item_permission" + ADD CONSTRAINT "drive_item_permission_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "drive_item_permission" + ADD CONSTRAINT "drive_item_permission_fk_2" + FOREIGN KEY("viaPublicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "drive_item_user_state" table +-- +ALTER TABLE ONLY "drive_item_user_state" + ADD CONSTRAINT "drive_item_user_state_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "drive_item_user_state" + ADD CONSTRAINT "drive_item_user_state_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "embedded_object" table +-- +ALTER TABLE ONLY "embedded_object" + ADD CONSTRAINT "embedded_object_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "embedded_object" + ADD CONSTRAINT "embedded_object_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "filter_view" table +-- +ALTER TABLE ONLY "filter_view" + ADD CONSTRAINT "filter_view_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "filter_view" + ADD CONSTRAINT "filter_view_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "headless_change" table +-- +ALTER TABLE ONLY "headless_change" + ADD CONSTRAINT "headless_change_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "item_version" table +-- +ALTER TABLE ONLY "item_version" + ADD CONSTRAINT "item_version_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "item_version_state" table +-- +ALTER TABLE ONLY "item_version_state" + ADD CONSTRAINT "item_version_state_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "item_view_day" table +-- +ALTER TABLE ONLY "item_view_day" + ADD CONSTRAINT "item_view_day_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "item_view_day" + ADD CONSTRAINT "item_view_day_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "macro" table +-- +ALTER TABLE ONLY "macro" + ADD CONSTRAINT "macro_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "macro" + ADD CONSTRAINT "macro_fk_1" + FOREIGN KEY("projectId") + REFERENCES "script_project"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "merged_range" table +-- +ALTER TABLE ONLY "merged_range" + ADD CONSTRAINT "merged_range_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "merged_range" + ADD CONSTRAINT "merged_range_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "named_range" table +-- +ALTER TABLE ONLY "named_range" + ADD CONSTRAINT "named_range_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "named_range" + ADD CONSTRAINT "named_range_fk_1" + FOREIGN KEY("spreadsheetId") + REFERENCES "spreadsheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "notification" table +-- +ALTER TABLE ONLY "notification" + ADD CONSTRAINT "notification_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "ownership_transfer" table +-- +ALTER TABLE ONLY "ownership_transfer" + ADD CONSTRAINT "ownership_transfer_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "ownership_transfer" + ADD CONSTRAINT "ownership_transfer_fk_1" + FOREIGN KEY("toUserId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "personal_access_token" table +-- +ALTER TABLE ONLY "personal_access_token" + ADD CONSTRAINT "personal_access_token_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "pivot_table" table +-- +ALTER TABLE ONLY "pivot_table" + ADD CONSTRAINT "pivot_table_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "pivot_table" + ADD CONSTRAINT "pivot_table_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "protected_range" table +-- +ALTER TABLE ONLY "protected_range" + ADD CONSTRAINT "protected_range_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "protected_range" + ADD CONSTRAINT "protected_range_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "publication" table +-- +ALTER TABLE ONLY "publication" + ADD CONSTRAINT "publication_fk_0" + FOREIGN KEY("ownerId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication" + ADD CONSTRAINT "publication_fk_1" + FOREIGN KEY("templateItemId") + REFERENCES "drive_item"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "publication_block" table +-- +ALTER TABLE ONLY "publication_block" + ADD CONSTRAINT "publication_block_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_block" + ADD CONSTRAINT "publication_block_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "publication_consent" table +-- +ALTER TABLE ONLY "publication_consent" + ADD CONSTRAINT "publication_consent_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_consent" + ADD CONSTRAINT "publication_consent_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "publication_delivery" table +-- +ALTER TABLE ONLY "publication_delivery" + ADD CONSTRAINT "publication_delivery_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_delivery" + ADD CONSTRAINT "publication_delivery_fk_1" + FOREIGN KEY("submissionId") + REFERENCES "submission"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "publication_moderator" table +-- +ALTER TABLE ONLY "publication_moderator" + ADD CONSTRAINT "publication_moderator_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_moderator" + ADD CONSTRAINT "publication_moderator_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "rev_file" table +-- +ALTER TABLE ONLY "rev_file" + ADD CONSTRAINT "rev_file_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE RESTRICT + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "rev_hook_state" table +-- +ALTER TABLE ONLY "rev_hook_state" + ADD CONSTRAINT "rev_hook_state_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "rev_op" table +-- +ALTER TABLE ONLY "rev_op" + ADD CONSTRAINT "rev_op_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "script_build" table +-- +ALTER TABLE ONLY "script_build" + ADD CONSTRAINT "script_build_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "script_build" + ADD CONSTRAINT "script_build_fk_1" + FOREIGN KEY("projectId") + REFERENCES "script_project"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "script_file" table +-- +ALTER TABLE ONLY "script_file" + ADD CONSTRAINT "script_file_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "script_file" + ADD CONSTRAINT "script_file_fk_1" + FOREIGN KEY("projectId") + REFERENCES "script_project"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "script_project" table +-- +ALTER TABLE ONLY "script_project" + ADD CONSTRAINT "script_project_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "script_project" + ADD CONSTRAINT "script_project_fk_1" + FOREIGN KEY("spreadsheetId") + REFERENCES "spreadsheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "script_property" table +-- +ALTER TABLE ONLY "script_property" + ADD CONSTRAINT "script_property_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "script_property" + ADD CONSTRAINT "script_property_fk_1" + FOREIGN KEY("projectId") + REFERENCES "script_project"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "script_trigger" table +-- +ALTER TABLE ONLY "script_trigger" + ADD CONSTRAINT "script_trigger_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "script_trigger" + ADD CONSTRAINT "script_trigger_fk_1" + FOREIGN KEY("projectId") + REFERENCES "script_project"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "script_user_property" table +-- +ALTER TABLE ONLY "script_user_property" + ADD CONSTRAINT "script_user_property_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "share_link" table +-- +ALTER TABLE ONLY "share_link" + ADD CONSTRAINT "share_link_fk_0" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "sheet" table +-- +ALTER TABLE ONLY "sheet" + ADD CONSTRAINT "sheet_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "sheet" + ADD CONSTRAINT "sheet_fk_1" + FOREIGN KEY("spreadsheetId") + REFERENCES "spreadsheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "sheet_column" table +-- +ALTER TABLE ONLY "sheet_column" + ADD CONSTRAINT "sheet_column_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "sheet_column" + ADD CONSTRAINT "sheet_column_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "sheet_row" table +-- +ALTER TABLE ONLY "sheet_row" + ADD CONSTRAINT "sheet_row_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "sheet_row" + ADD CONSTRAINT "sheet_row_fk_1" + FOREIGN KEY("sheetId") + REFERENCES "sheet"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "sheets_snapshot_index" table +-- +ALTER TABLE ONLY "sheets_snapshot_index" + ADD CONSTRAINT "sheets_snapshot_index_fk_0" + FOREIGN KEY("itemVersionId") + REFERENCES "item_version"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "slide" table +-- +ALTER TABLE ONLY "slide" + ADD CONSTRAINT "slide_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide" + ADD CONSTRAINT "slide_fk_1" + FOREIGN KEY("deckId") + REFERENCES "deck"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_build" table +-- +ALTER TABLE ONLY "slide_build" + ADD CONSTRAINT "slide_build_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_build" + ADD CONSTRAINT "slide_build_fk_1" + FOREIGN KEY("slideId") + REFERENCES "slide"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ONLY "slide_build" + ADD CONSTRAINT "slide_build_fk_2" + FOREIGN KEY("elementId") + REFERENCES "slide_element"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_element" table +-- +ALTER TABLE ONLY "slide_element" + ADD CONSTRAINT "slide_element_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_element" + ADD CONSTRAINT "slide_element_fk_1" + FOREIGN KEY("slideId") + REFERENCES "slide"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ONLY "slide_element" + ADD CONSTRAINT "slide_element_fk_2" + FOREIGN KEY("layoutId") + REFERENCES "slide_layout"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ONLY "slide_element" + ADD CONSTRAINT "slide_element_fk_3" + FOREIGN KEY("masterId") + REFERENCES "slide_master"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ONLY "slide_element" + ADD CONSTRAINT "slide_element_fk_4" + FOREIGN KEY("parentId") + REFERENCES "slide_element"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_group" table +-- +ALTER TABLE ONLY "slide_group" + ADD CONSTRAINT "slide_group_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_group" + ADD CONSTRAINT "slide_group_fk_1" + FOREIGN KEY("deckId") + REFERENCES "deck"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_layout" table +-- +ALTER TABLE ONLY "slide_layout" + ADD CONSTRAINT "slide_layout_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_layout" + ADD CONSTRAINT "slide_layout_fk_1" + FOREIGN KEY("masterId") + REFERENCES "slide_master"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_master" table +-- +ALTER TABLE ONLY "slide_master" + ADD CONSTRAINT "slide_master_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_master" + ADD CONSTRAINT "slide_master_fk_1" + FOREIGN KEY("themeId") + REFERENCES "deck_theme"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_table_axis" table +-- +ALTER TABLE ONLY "slide_table_axis" + ADD CONSTRAINT "slide_table_axis_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_table_axis" + ADD CONSTRAINT "slide_table_axis_fk_1" + FOREIGN KEY("elementId") + REFERENCES "slide_element"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slide_table_cell" table +-- +ALTER TABLE ONLY "slide_table_cell" + ADD CONSTRAINT "slide_table_cell_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "slide_table_cell" + ADD CONSTRAINT "slide_table_cell_fk_1" + FOREIGN KEY("elementId") + REFERENCES "slide_element"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ONLY "slide_table_cell" + ADD CONSTRAINT "slide_table_cell_fk_2" + FOREIGN KEY("rowId") + REFERENCES "slide_table_axis"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; +ALTER TABLE ONLY "slide_table_cell" + ADD CONSTRAINT "slide_table_cell_fk_3" + FOREIGN KEY("columnId") + REFERENCES "slide_table_axis"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "slides_snapshot_index" table +-- +ALTER TABLE ONLY "slides_snapshot_index" + ADD CONSTRAINT "slides_snapshot_index_fk_0" + FOREIGN KEY("itemVersionId") + REFERENCES "item_version"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "spreadsheet" table +-- +ALTER TABLE ONLY "spreadsheet" + ADD CONSTRAINT "spreadsheet_fk_0" + FOREIGN KEY("fileId") + REFERENCES "rev_file"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "storage_reservation" table +-- +ALTER TABLE ONLY "storage_reservation" + ADD CONSTRAINT "storage_reservation_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "storage_reservation" + ADD CONSTRAINT "storage_reservation_fk_1" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "stored_file" table +-- +ALTER TABLE ONLY "stored_file" + ADD CONSTRAINT "stored_file_fk_0" + FOREIGN KEY("ownerId") + REFERENCES "user_profile"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; +ALTER TABLE ONLY "stored_file" + ADD CONSTRAINT "stored_file_fk_1" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "submission" table +-- +ALTER TABLE ONLY "submission" + ADD CONSTRAINT "submission_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "submission" + ADD CONSTRAINT "submission_fk_1" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "submission_asset" table +-- +ALTER TABLE ONLY "submission_asset" + ADD CONSTRAINT "submission_asset_fk_0" + FOREIGN KEY("submissionId") + REFERENCES "submission"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "submission_revision" table +-- +ALTER TABLE ONLY "submission_revision" + ADD CONSTRAINT "submission_revision_fk_0" + FOREIGN KEY("submissionId") + REFERENCES "submission"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "user_activity_settings" table +-- +ALTER TABLE ONLY "user_activity_settings" + ADD CONSTRAINT "user_activity_settings_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "user_preferences" table +-- +ALTER TABLE ONLY "user_preferences" + ADD CONSTRAINT "user_preferences_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "user_profile" table +-- +ALTER TABLE ONLY "user_profile" + ADD CONSTRAINT "user_profile_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "user_storage" table +-- +ALTER TABLE ONLY "user_storage" + ADD CONSTRAINT "user_storage_fk_0" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "write_diff_cache" table +-- +ALTER TABLE ONLY "write_diff_cache" + ADD CONSTRAINT "write_diff_cache_fk_0" + FOREIGN KEY("documentId") + REFERENCES "document"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "write_theme" table +-- +ALTER TABLE ONLY "write_theme" + ADD CONSTRAINT "write_theme_fk_0" + FOREIGN KEY("ownerId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "write_theme_revision" table +-- +ALTER TABLE ONLY "write_theme_revision" + ADD CONSTRAINT "write_theme_revision_fk_0" + FOREIGN KEY("themeId") + REFERENCES "write_theme"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_future_call_claim" table +-- +ALTER TABLE ONLY "serverpod_future_call_claim" + ADD CONSTRAINT "serverpod_future_call_claim_fk_0" + FOREIGN KEY("futureCallId") + REFERENCES "serverpod_future_call"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_log" table +-- +ALTER TABLE ONLY "serverpod_log" + ADD CONSTRAINT "serverpod_log_fk_0" + FOREIGN KEY("sessionLogId") + REFERENCES "serverpod_session_log"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_message_log" table +-- +ALTER TABLE ONLY "serverpod_message_log" + ADD CONSTRAINT "serverpod_message_log_fk_0" + FOREIGN KEY("sessionLogId") + REFERENCES "serverpod_session_log"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_query_log" table +-- +ALTER TABLE ONLY "serverpod_query_log" + ADD CONSTRAINT "serverpod_query_log_fk_0" + FOREIGN KEY("sessionLogId") + REFERENCES "serverpod_session_log"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_anonymous_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_anonymous_account" + ADD CONSTRAINT "serverpod_auth_idp_anonymous_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_apple_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_apple_account" + ADD CONSTRAINT "serverpod_auth_idp_apple_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_email_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_email_account" + ADD CONSTRAINT "serverpod_auth_idp_email_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_email_account_password_reset_request" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_email_account_password_reset_request" + ADD CONSTRAINT "serverpod_auth_idp_email_account_password_reset_request_fk_0" + FOREIGN KEY("emailAccountId") + REFERENCES "serverpod_auth_idp_email_account"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "serverpod_auth_idp_email_account_password_reset_request" + ADD CONSTRAINT "serverpod_auth_idp_email_account_password_reset_request_fk_1" + FOREIGN KEY("challengeId") + REFERENCES "serverpod_auth_idp_secret_challenge"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "serverpod_auth_idp_email_account_password_reset_request" + ADD CONSTRAINT "serverpod_auth_idp_email_account_password_reset_request_fk_2" + FOREIGN KEY("setPasswordChallengeId") + REFERENCES "serverpod_auth_idp_secret_challenge"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_email_account_request" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_email_account_request" + ADD CONSTRAINT "serverpod_auth_idp_email_account_request_fk_0" + FOREIGN KEY("challengeId") + REFERENCES "serverpod_auth_idp_secret_challenge"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "serverpod_auth_idp_email_account_request" + ADD CONSTRAINT "serverpod_auth_idp_email_account_request_fk_1" + FOREIGN KEY("createAccountChallengeId") + REFERENCES "serverpod_auth_idp_secret_challenge"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_facebook_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_facebook_account" + ADD CONSTRAINT "serverpod_auth_idp_facebook_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_firebase_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_firebase_account" + ADD CONSTRAINT "serverpod_auth_idp_firebase_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_github_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_github_account" + ADD CONSTRAINT "serverpod_auth_idp_github_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_google_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_google_account" + ADD CONSTRAINT "serverpod_auth_idp_google_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_microsoft_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_microsoft_account" + ADD CONSTRAINT "serverpod_auth_idp_microsoft_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_idp_passkey_account" table +-- +ALTER TABLE ONLY "serverpod_auth_idp_passkey_account" + ADD CONSTRAINT "serverpod_auth_idp_passkey_account_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_core_jwt_refresh_token" table +-- +ALTER TABLE ONLY "serverpod_auth_core_jwt_refresh_token" + ADD CONSTRAINT "serverpod_auth_core_jwt_refresh_token_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_core_profile" table +-- +ALTER TABLE ONLY "serverpod_auth_core_profile" + ADD CONSTRAINT "serverpod_auth_core_profile_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "serverpod_auth_core_profile" + ADD CONSTRAINT "serverpod_auth_core_profile_fk_1" + FOREIGN KEY("imageId") + REFERENCES "serverpod_auth_core_profile_image"("id") + ON DELETE NO ACTION + ON UPDATE NO ACTION + DEFERRABLE INITIALLY DEFERRED; + +-- +-- Foreign relations for "serverpod_auth_core_profile_image" table +-- +ALTER TABLE ONLY "serverpod_auth_core_profile_image" + ADD CONSTRAINT "serverpod_auth_core_profile_image_fk_0" + FOREIGN KEY("userProfileId") + REFERENCES "serverpod_auth_core_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- Foreign relations for "serverpod_auth_core_session" table +-- +ALTER TABLE ONLY "serverpod_auth_core_session" + ADD CONSTRAINT "serverpod_auth_core_session_fk_0" + FOREIGN KEY("authUserId") + REFERENCES "serverpod_auth_core_user"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + + +-- +-- MIGRATION VERSION FOR wonky +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('wonky', '20261020084059086-publications', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20261020084059086-publications', "timestamp" = now(); + +-- +-- MIGRATION VERSION FOR serverpod +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('serverpod', '20260824182259319', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20260824182259319', "timestamp" = now(); + +-- +-- MIGRATION VERSION FOR serverpod_auth_idp +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('serverpod_auth_idp', '20260924105404509', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20260924105404509', "timestamp" = now(); + +-- +-- MIGRATION VERSION FOR serverpod_auth_core +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('serverpod_auth_core', '20260924105232991', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20260924105232991', "timestamp" = now(); + + +COMMIT; diff --git a/wonky_server/migrations/20261020084059086-publications/definition_project.json b/wonky_server/migrations/20261020084059086-publications/definition_project.json new file mode 100644 index 00000000..5bad606c --- /dev/null +++ b/wonky_server/migrations/20261020084059086-publications/definition_project.json @@ -0,0 +1,16574 @@ +{ + "__className__": "serverpod.DatabaseDefinition", + "schemaVersion": 2, + "moduleName": "wonky", + "tables": [ + { + "__className__": "serverpod.TableDefinition", + "name": "access_request", + "dartName": "AccessRequest", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requesterId", + "fieldName": "requesterId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requestedRole", + "fieldName": "requestedRole", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:AccessRole" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "message", + "fieldName": "message", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "handledAt", + "fieldName": "handledAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "handledById", + "fieldName": "handledById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outcome", + "fieldName": "outcome", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:AccessRequestOutcome?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "access_request_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "access_request_fk_1", + "columns": [ + "requesterId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "access_request_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "handledAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "activity_event", + "dartName": "ActivityEvent", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorId", + "fieldName": "actorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "type", + "fieldName": "type", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActivityType" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "summary", + "fieldName": "summary", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "activity_event_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "activity_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "at" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_function_cache", + "dartName": "AiFunctionCache", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "model", + "fieldName": "model", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hits", + "fieldName": "hits", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_function_cache_key_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "key" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_function_cache_sheet_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetUuid" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_preview_record", + "dartName": "AiPreviewRecord", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previewId", + "fieldName": "previewId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previewJson", + "fieldName": "previewJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changesJson", + "fieldName": "changesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_preview_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "previewId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_preview_expires_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_usage", + "dartName": "AiUsage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "model", + "fieldName": "model", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feature", + "fieldName": "feature", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inputTokens", + "fieldName": "inputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outputTokens", + "fieldName": "outputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cacheReadTokens", + "fieldName": "cacheReadTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cacheWriteTokens", + "fieldName": "cacheWriteTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ai_usage_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_usage_user_at_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "at" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_user_key", + "dartName": "AiUserKey", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "provider", + "fieldName": "provider", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:AiProvider" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKey", + "fieldName": "apiKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ai_user_key_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_user_key_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ai_user_setting", + "dartName": "AiUserSetting", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "quality", + "fieldName": "quality", + "columnType": 0, + "isNullable": false, + "columnDefault": "'best'", + "dartType": "protocol:AiQuality" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ai_user_setting_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ai_user_setting_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "assistant_message", + "dartName": "AssistantMessage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "threadId", + "fieldName": "threadId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "role", + "fieldName": "role", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentJson", + "fieldName": "contentJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayText", + "fieldName": "displayText", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toolCallsJson", + "fieldName": "toolCallsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "visible", + "fieldName": "visible", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "replay", + "fieldName": "replay", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runId", + "fieldName": "runId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stopReason", + "fieldName": "stopReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "assistant_message_fk_0", + "columns": [ + "threadId" + ], + "referenceTable": "assistant_thread", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "assistant_message_thread_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "threadId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "assistant_thread", + "dartName": "AssistantThread", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextRevision", + "fieldName": "contextRevision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextMarkdown", + "fieldName": "contextMarkdown", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "assistant_thread_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "assistant_thread_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "assistant_thread_user_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "updatedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "banding", + "dartName": "Banding", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "styleJson", + "fieldName": "styleJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "banding_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "banding_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "banding_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "basic_filter", + "dartName": "BasicFilter", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "criteriaJson", + "fieldName": "criteriaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortJson", + "fieldName": "sortJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "basic_filter_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "basic_filter_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "basic_filter_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_ai_usage", + "dartName": "BoardAiUsage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "day", + "fieldName": "day", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "provider", + "fieldName": "provider", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "model", + "fieldName": "model", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feature", + "fieldName": "feature", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requests", + "fieldName": "requests", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inputTokens", + "fieldName": "inputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outputTokens", + "fieldName": "outputTokens", + "columnType": 6, + "isNullable": false, + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_ai_usage_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "provider" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "model" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "feature" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_bundle_suggestion", + "dartName": "BoardBundleSuggestion", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rationale", + "fieldName": "rationale", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "area", + "fieldName": "area", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:BoardArea?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postIds", + "fieldName": "postIds", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "state", + "fieldName": "state", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_comment", + "dartName": "BoardComment", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postId", + "fieldName": "postId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "taskId", + "fieldName": "taskId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "body", + "fieldName": "body", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "systemEvent", + "fieldName": "systemEvent", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderation", + "fieldName": "moderation", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardModeration" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderationReason", + "fieldName": "moderationReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "needsCheck", + "fieldName": "needsCheck", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedAt", + "fieldName": "editedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "removedAt", + "fieldName": "removedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_comment_fk_0", + "columns": [ + "postId" + ], + "referenceTable": "board_post", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_comment_fk_1", + "columns": [ + "taskId" + ], + "referenceTable": "board_task", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_comment_fk_2", + "columns": [ + "authorId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_comment_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_comment_post_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_comment_task_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "taskId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_flag", + "dartName": "BoardFlag", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postId", + "fieldName": "postId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "commentId", + "fieldName": "commentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reason", + "fieldName": "reason", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardFlagReason" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "note", + "fieldName": "note", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_flag_fk_0", + "columns": [ + "postId" + ], + "referenceTable": "board_post", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_flag_fk_1", + "columns": [ + "commentId" + ], + "referenceTable": "board_comment", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_flag_fk_2", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_flag_post_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_flag_comment_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "commentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_github_delivery", + "dartName": "BoardGithubDelivery", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deliveryId", + "fieldName": "deliveryId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "event", + "fieldName": "event", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "receivedAt", + "fieldName": "receivedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "processedAt", + "fieldName": "processedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_github_delivery_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deliveryId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_moderation_log", + "dartName": "BoardModerationLog", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "adminId", + "fieldName": "adminId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "action", + "fieldName": "action", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "targetKind", + "fieldName": "targetKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardTargetKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "targetId", + "fieldName": "targetId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "beforeJson", + "fieldName": "beforeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "afterJson", + "fieldName": "afterJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reason", + "fieldName": "reason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_moderation_log_target_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "targetKind" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "targetId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_post", + "dartName": "BoardPost", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardPostKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reportedKind", + "fieldName": "reportedKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardPostKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "area", + "fieldName": "area", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:BoardArea?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "size", + "fieldName": "size", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:BoardSize?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "aiLabels", + "fieldName": "aiLabels", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "body", + "fieldName": "body", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextJson", + "fieldName": "contextJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appHint", + "fieldName": "appHint", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "screenshotFileId", + "fieldName": "screenshotFileId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardPostStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderation", + "fieldName": "moderation", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardModeration" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "moderationReason", + "fieldName": "moderationReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "needsCheck", + "fieldName": "needsCheck", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedByModerator", + "fieldName": "editedByModerator", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triageState", + "fieldName": "triageState", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardTriageState" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triageJson", + "fieldName": "triageJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triageAttempts", + "fieldName": "triageAttempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "suggestedTitle", + "fieldName": "suggestedTitle", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "summary", + "fieldName": "summary", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duplicateOfId", + "fieldName": "duplicateOfId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "possibleDuplicateOfId", + "fieldName": "possibleDuplicateOfId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "duplicateHintDismissed", + "fieldName": "duplicateHintDismissed", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "declineReason", + "fieldName": "declineReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "taskId", + "fieldName": "taskId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "score", + "fieldName": "score", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "voteCount", + "fieldName": "voteCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "commentCount", + "fieldName": "commentCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "flagCount", + "fieldName": "flagCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedAt", + "fieldName": "editedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "removedAt", + "fieldName": "removedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_post_fk_0", + "columns": [ + "authorId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_post_fk_1", + "columns": [ + "screenshotFileId" + ], + "referenceTable": "stored_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_post_fk_2", + "columns": [ + "taskId" + ], + "referenceTable": "board_task", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_post_list_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "moderation" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "kind" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "score" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_post_author_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "authorId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_post_task_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "taskId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_pull_request", + "dartName": "BoardPullRequest", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prNumber", + "fieldName": "prNumber", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "taskId", + "fieldName": "taskId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorLogin", + "fieldName": "authorLogin", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "headSha", + "fieldName": "headSha", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "state", + "fieldName": "state", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateState", + "fieldName": "gateState", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateReason", + "fieldName": "gateReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateFirstFailedAt", + "fieldName": "gateFirstFailedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "gateCommentId", + "fieldName": "gateCommentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewCommentId", + "fieldName": "reviewCommentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastReviewSha", + "fieldName": "lastReviewSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastReviewJson", + "fieldName": "lastReviewJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastReviewAt", + "fieldName": "lastReviewAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewDay", + "fieldName": "reviewDay", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewCount", + "fieldName": "reviewCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mergeCommitSha", + "fieldName": "mergeCommitSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewPendingSha", + "fieldName": "reviewPendingSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reviewDueAt", + "fieldName": "reviewDueAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_pull_request_fk_0", + "columns": [ + "taskId" + ], + "referenceTable": "board_task", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_pull_request_number_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "prNumber" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_task", + "dartName": "BoardTask", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "area", + "fieldName": "area", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardArea" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "size", + "fieldName": "size", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardSize" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BoardTaskStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptBody", + "fieldName": "promptBody", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptGeneratedAt", + "fieldName": "promptGeneratedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptRequestedAt", + "fieldName": "promptRequestedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptNote", + "fieldName": "promptNote", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptExcludedCommentIds", + "fieldName": "promptExcludedCommentIds", + "columnType": 8, + "isNullable": true, + "dartType": "List?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptEditedById", + "fieldName": "promptEditedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "promptEditedAt", + "fieldName": "promptEditedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publishedAt", + "fieldName": "publishedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimedById", + "fieldName": "claimedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimedAt", + "fieldName": "claimedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimExpiresAt", + "fieldName": "claimExpiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimWarnedAt", + "fieldName": "claimWarnedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "claimCode", + "fieldName": "claimCode", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "pullRequestUrl", + "fieldName": "pullRequestUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prNumber", + "fieldName": "prNumber", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prAuthorLogin", + "fieldName": "prAuthorLogin", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mergeCommitSha", + "fieldName": "mergeCommitSha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "doneAt", + "fieldName": "doneAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shippedDeploySha", + "fieldName": "shippedDeploySha", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shippedAt", + "fieldName": "shippedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_task_fk_0", + "columns": [ + "claimedById" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_task_status_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_task_claim_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "claimedById" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_user_profile", + "dartName": "BoardUserProfile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "githubLogin", + "fieldName": "githubLogin", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedAt", + "fieldName": "blockedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedUntil", + "fieldName": "blockedUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedReason", + "fieldName": "blockedReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "blockedById", + "fieldName": "blockedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_user_profile_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_user_profile_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "board_vote", + "dartName": "BoardVote", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "postId", + "fieldName": "postId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_vote_fk_0", + "columns": [ + "postId" + ], + "referenceTable": "board_post", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "board_vote_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_vote_unique_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "board_vote_recent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "postId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "cell", + "dartName": "Cell", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowId", + "fieldName": "rowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "columnId", + "fieldName": "columnId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "content", + "fieldName": "content", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "note", + "fieldName": "note", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "numberFormat", + "fieldName": "numberFormat", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fontFamily", + "fieldName": "fontFamily", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fontSize", + "fieldName": "fontSize", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "bold", + "fieldName": "bold", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "italic", + "fieldName": "italic", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "underline", + "fieldName": "underline", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "strikethrough", + "fieldName": "strikethrough", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "textColor", + "fieldName": "textColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fillColor", + "fieldName": "fillColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hAlign", + "fieldName": "hAlign", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:HorizontalAlign?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "vAlign", + "fieldName": "vAlign", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:VerticalAlign?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "wrap", + "fieldName": "wrap", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:WrapStrategy?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rotation", + "fieldName": "rotation", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderTop", + "fieldName": "borderTop", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderRight", + "fieldName": "borderRight", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderBottom", + "fieldName": "borderBottom", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderLeft", + "fieldName": "borderLeft", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "linkUrl", + "fieldName": "linkUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "cell_fk_0", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_row_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "rowId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_col_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "columnId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "cell_history", + "dartName": "CellHistory", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowId", + "fieldName": "rowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "colId", + "fieldName": "colId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userUuid", + "fieldName": "userUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "before", + "fieldName": "before", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "after", + "fieldName": "after", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_history_cell_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "rowId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "colId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "at" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "cell_history_change_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "rowId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "colId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "chart_link", + "dartName": "ChartLink", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetItemUuid", + "fieldName": "spreadsheetItemUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "chartObjectId", + "fieldName": "chartObjectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceSpecJson", + "fieldName": "sourceSpecJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dataSnapshotJson", + "fieldName": "dataSnapshotJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceVersion", + "fieldName": "sourceVersion", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedBy", + "fieldName": "updatedBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "autoUpdate", + "fieldName": "autoUpdate", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "chart_link_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "chart_link_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "chart_link_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "chart_link_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "code_state", + "dartName": "CodeState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "code", + "fieldName": "code", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "language", + "fieldName": "language", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "highlight", + "fieldName": "highlight", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "annotationsJson", + "fieldName": "annotationsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "transitionJson", + "fieldName": "transitionJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "code_state_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "code_state_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "code_state_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "code_state_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "comment", + "dartName": "Comment", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "threadId", + "fieldName": "threadId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorKind", + "fieldName": "authorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "body", + "fieldName": "body", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mentions", + "fieldName": "mentions", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reactions", + "fieldName": "reactions", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editedAt", + "fieldName": "editedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "systemEvent", + "fieldName": "systemEvent", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:CommentSystemEvent?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_fk_0", + "columns": [ + "threadId" + ], + "referenceTable": "comment_thread", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_fk_1", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_thread_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "threadId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "comment_thread", + "dartName": "CommentThread", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorKind", + "fieldName": "anchorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:CommentAnchorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorJson", + "fieldName": "anchorJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "quotedText", + "fieldName": "quotedText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "columnDefault": "'open'", + "dartType": "protocol:CommentStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "resolvedById", + "fieldName": "resolvedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "resolvedAt", + "fieldName": "resolvedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "assigneeId", + "fieldName": "assigneeId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "statusBeforeOrphan", + "fieldName": "statusBeforeOrphan", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:CommentStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "orphanReasonJson", + "fieldName": "orphanReasonJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "suggestionId", + "fieldName": "suggestionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_thread_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_thread_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "comment_thread_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "conditional_format_rule", + "dartName": "ConditionalFormatRule", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangesJson", + "fieldName": "rangesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ruleJson", + "fieldName": "ruleJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "conditional_format_rule_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "conditional_format_rule_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "conditional_format_rule_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "data_validation_rule", + "dartName": "DataValidationRule", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangesJson", + "fieldName": "rangesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "criteriaJson", + "fieldName": "criteriaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "strict", + "fieldName": "strict", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showDropdown", + "fieldName": "showDropdown", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayStyle", + "fieldName": "displayStyle", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "helpText", + "fieldName": "helpText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "data_validation_rule_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "data_validation_rule_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "data_validation_rule_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "deck", + "dartName": "Deck", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "width", + "fieldName": "width", + "columnType": 3, + "isNullable": false, + "columnDefault": "1920.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "height", + "fieldName": "height", + "columnType": 3, + "isNullable": false, + "columnDefault": "1080.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizePreset", + "fieldName": "sizePreset", + "columnType": 0, + "isNullable": false, + "columnDefault": "'widescreen16x9'", + "dartType": "protocol:SlideSizePreset" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appearance", + "fieldName": "appearance", + "columnType": 0, + "isNullable": false, + "columnDefault": "'light'", + "dartType": "protocol:DeckAppearance" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "language", + "fieldName": "language", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showSlideNumbers", + "fieldName": "showSlideNumbers", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hideNumberOnTitle", + "fieldName": "hideNumberOnTitle", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "firstSlideNumber", + "fieldName": "firstSlideNumber", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "footerText", + "fieldName": "footerText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultsJson", + "fieldName": "defaultsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "guidesJson", + "fieldName": "guidesJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "presentJson", + "fieldName": "presentJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "deck_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "deck_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "deck_theme", + "dartName": "DeckTheme", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deckId", + "fieldName": "deckId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceKey", + "fieldName": "sourceKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "colorsJson", + "fieldName": "colorsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fontsJson", + "fieldName": "fontsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "textStylesJson", + "fieldName": "textStylesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shapeStyleJson", + "fieldName": "shapeStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "tableStyleJson", + "fieldName": "tableStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "codeStyleJson", + "fieldName": "codeStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "chartStyleJson", + "fieldName": "chartStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "deck_theme_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "deck_theme_fk_1", + "columns": [ + "deckId" + ], + "referenceTable": "deck", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "deck_theme_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "deck_theme_deck_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deckId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "dimension_group", + "dartName": "DimensionGroup", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dimension", + "fieldName": "dimension", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:Dimension" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "startId", + "fieldName": "startId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "endId", + "fieldName": "endId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "depth", + "fieldName": "depth", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "collapsed", + "fieldName": "collapsed", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "dimension_group_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "dimension_group_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "dimension_group_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document", + "dartName": "Document", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "headRevision", + "fieldName": "headRevision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "latestSnapshotRevision", + "fieldName": "latestSnapshotRevision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "pageSetupJson", + "fieldName": "pageSetupJson", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "language", + "fieldName": "language", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "frontMatter", + "fieldName": "frontMatter", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "charCount", + "fieldName": "charCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "wordCount", + "fieldName": "wordCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_import_report", + "dartName": "DocumentImportReport", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "warningsJson", + "fieldName": "warningsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "seenAt", + "fieldName": "seenAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_import_report_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_import_report_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_meta_change", + "dartName": "DocumentMetaChange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "field", + "fieldName": "field", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientOpId", + "fieldName": "clientOpId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "beforeJson", + "fieldName": "beforeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "afterJson", + "fieldName": "afterJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_meta_change_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_meta_change_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_meta_change_client_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "clientOpId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_op", + "dartName": "DocumentOp", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientOpId", + "fieldName": "clientOpId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionId", + "fieldName": "sessionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:DocumentOpKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "baseRevision", + "fieldName": "baseRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deltaJson", + "fieldName": "deltaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseJson", + "fieldName": "inverseJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_op_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_op_rev_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_op_client_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "clientOpId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_op_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "document_snapshot", + "dartName": "DocumentSnapshot", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deltaJson", + "fieldName": "deltaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "compressed", + "fieldName": "compressed", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "document_snapshot_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "document_snapshot_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "drive_item", + "dartName": "DriveItem", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:DriveItemKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "parentId", + "fieldName": "parentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "description", + "fieldName": "description", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentRef", + "fieldName": "contentRef", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "thumbnailFileId", + "fieldName": "thumbnailFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizeBytes", + "fieldName": "sizeBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attachmentBytes", + "fieldName": "attachmentBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kindMask", + "fieldName": "kindMask", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mimeType", + "fieldName": "mimeType", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileCategory", + "fieldName": "fileCategory", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:FileCategory?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uploadState", + "fieldName": "uploadState", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:FileUploadState?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileMetaJson", + "fieldName": "fileMetaJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previewFileId", + "fieldName": "previewFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "modifiedAt", + "fieldName": "modifiedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "modifiedById", + "fieldName": "modifiedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trashedAt", + "fieldName": "trashedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trashedById", + "fieldName": "trashedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateOf", + "fieldName": "templateOf", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:TemplateCategory?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateKey", + "fieldName": "templateKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editorsCanShare", + "fieldName": "editorsCanShare", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nonEditorsCanExport", + "fieldName": "nonEditorsCanExport", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "viewersSeeComments", + "fieldName": "viewersSeeComments", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "searchText", + "fieldName": "searchText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 2 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_fk_1", + "columns": [ + "parentId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_parent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "parentId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "trashedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_content_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "contentRef" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_template_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "templateOf" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_upload_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uploadState" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_trashed_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "trashedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "drive_item_permission", + "dartName": "DriveItemPermission", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "invitedEmail", + "fieldName": "invitedEmail", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "role", + "fieldName": "role", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:AccessRole" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inheritedFromId", + "fieldName": "inheritedFromId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "grantedById", + "fieldName": "grantedById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "grantedAt", + "fieldName": "grantedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "viaPublicationId", + "fieldName": "viaPublicationId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_2", + "columns": [ + "viaPublicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_item_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "inheritedFromId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "invitedEmail" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false, + "nullsDistinct": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_email_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "invitedEmail" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "perm_expires_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "drive_item_user_state", + "dartName": "DriveItemUserState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "starred", + "fieldName": "starred", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastOpenedAt", + "fieldName": "lastOpenedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastEditedAt", + "fieldName": "lastEditedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "pinnedOffline", + "fieldName": "pinnedOffline", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shortcutParentId", + "fieldName": "shortcutParentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "viaLink", + "fieldName": "viaLink", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_user_state_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_user_state_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_user_state_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "drive_item_user_recent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "lastOpenedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "embedded_object", + "dartName": "EmbeddedObject", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:EmbeddedObjectKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorJson", + "fieldName": "anchorJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "specJson", + "fieldName": "specJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "zIndex", + "fieldName": "zIndex", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "altText", + "fieldName": "altText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "embedded_object_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "embedded_object_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "embedded_object_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "feedback_report", + "dartName": "FeedbackReport", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:FeedbackKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "message", + "fieldName": "message", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "app", + "fieldName": "app", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appVersion", + "fieldName": "appVersion", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "platform", + "fieldName": "platform", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "route", + "fieldName": "route", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stackTrace", + "fieldName": "stackTrace", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contextJson", + "fieldName": "contextJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "feedback_report_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "filter_view", + "dartName": "FilterView", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "criteriaJson", + "fieldName": "criteriaJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortJson", + "fieldName": "sortJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "filter_view_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "filter_view_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "filter_view_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "headless_change", + "dartName": "HeadlessChange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseJson", + "fieldName": "inverseJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaField", + "fieldName": "metaField", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaBeforeJson", + "fieldName": "metaBeforeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaAfterJson", + "fieldName": "metaAfterJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toolName", + "fieldName": "toolName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revertedAt", + "fieldName": "revertedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "headless_change_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "headless_change_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "changeId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "headless_change_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "item_version", + "dartName": "ItemVersion", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:VersionKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authors", + "fieldName": "authors", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageKind", + "fieldName": "storageKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:VersionStorage" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "snapshotFileId", + "fieldName": "snapshotFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizeBytes", + "fieldName": "sizeBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_version_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_version_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "item_version_state", + "dartName": "ItemVersionState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastEditAt", + "fieldName": "lastEditAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dirtySince", + "fieldName": "dirtySince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastVersionAt", + "fieldName": "lastVersionAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editorsSinceLastVersion", + "fieldName": "editorsSinceLastVersion", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastRevision", + "fieldName": "lastRevision", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "capturingSince", + "fieldName": "capturingSince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_version_state_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_version_state_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_version_state_dirty_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "dirtySince" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "item_view_day", + "dartName": "ItemViewDay", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "day", + "fieldName": "day", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "views", + "fieldName": "views", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastViewedAt", + "fieldName": "lastViewedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_view_day_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "item_view_day_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_view_day_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "item_view_day_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "macro", + "dartName": "Macro", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "shortcutSlot", + "fieldName": "shortcutSlot", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "macro_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "macro_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "macro_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "merged_range", + "dartName": "MergedRange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "merged_range_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "merged_range_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "merged_range_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "named_range", + "dartName": "NamedRange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetId", + "fieldName": "spreadsheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formula", + "fieldName": "formula", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "comment", + "fieldName": "comment", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "metaJson", + "fieldName": "metaJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "named_range_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "named_range_fk_1", + "columns": [ + "spreadsheetId" + ], + "referenceTable": "spreadsheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "named_range_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "notification", + "dartName": "UserNotification", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:NotificationKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorId", + "fieldName": "actorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "readAt", + "fieldName": "readAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "emailedAt", + "fieldName": "emailedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "emailPending", + "fieldName": "emailPending", + "columnType": 1, + "isNullable": true, + "columnDefault": "false", + "dartType": "bool?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "notification_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "notification_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "notification_email_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "emailPending" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "notification_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "ownership_transfer", + "dartName": "OwnershipTransfer", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fromUserId", + "fieldName": "fromUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toUserId", + "fieldName": "toUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "handledAt", + "fieldName": "handledAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "accepted", + "fieldName": "accepted", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ownership_transfer_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "ownership_transfer_fk_1", + "columns": [ + "toUserId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "ownership_transfer_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "handledAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "personal_access_token", + "dartName": "PersonalAccessToken", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "tokenHash", + "fieldName": "tokenHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prefix", + "fieldName": "prefix", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopes", + "fieldName": "scopes", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastUsedAt", + "fieldName": "lastUsedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revokedAt", + "fieldName": "revokedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "personal_access_token_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "personal_access_token_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "personal_access_token_hash_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "tokenHash" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "pivot_table", + "dartName": "PivotTable", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorRowId", + "fieldName": "anchorRowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "anchorColId", + "fieldName": "anchorColId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceRangeJson", + "fieldName": "sourceRangeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "specJson", + "fieldName": "specJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "pivot_table_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "pivot_table_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "pivot_table_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "protected_range", + "dartName": "ProtectedRange", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rangeJson", + "fieldName": "rangeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "exceptRangesJson", + "fieldName": "exceptRangesJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "description", + "fieldName": "description", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "warningOnly", + "fieldName": "warningOnly", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "editorsJson", + "fieldName": "editorsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "protected_range_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "protected_range_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "protected_range_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication", + "dartName": "Publication", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicId", + "fieldName": "publicId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "siteUrl", + "fieldName": "siteUrl", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "webhookUrl", + "fieldName": "webhookUrl", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verifiedHost", + "fieldName": "verifiedHost", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verifiedAt", + "fieldName": "verifiedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateItemId", + "fieldName": "templateItemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "termsUrl", + "fieldName": "termsUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fields", + "fieldName": "fields", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:PublicationFields" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "signingSecret", + "fieldName": "signingSecret", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previousSigningSecret", + "fieldName": "previousSigningSecret", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previousSecretUntil", + "fieldName": "previousSecretUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKeyHash", + "fieldName": "apiKeyHash", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKeyLast4", + "fieldName": "apiKeyLast4", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_fk_1", + "columns": [ + "templateItemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_public_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_api_key_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "apiKeyHash" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_block", + "dartName": "PublicationBlock", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_block_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_block_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_block_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_consent", + "dartName": "PublicationConsent", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "consentKey", + "fieldName": "consentKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_consent_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_consent_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_consent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_delivery", + "dartName": "PublicationDelivery", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "webhookId", + "fieldName": "webhookId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "type", + "fieldName": "type", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sequence", + "fieldName": "sequence", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextAttemptAt", + "fieldName": "nextAttemptAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastStatus", + "fieldName": "lastStatus", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastError", + "fieldName": "lastError", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deliveredAt", + "fieldName": "deliveredAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "failedAt", + "fieldName": "failedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_delivery_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_delivery_fk_1", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_webhook_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "webhookId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextAttemptAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_publication_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "publication_moderator", + "dartName": "PublicationModerator", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_moderator_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_moderator_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_moderator_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_moderator_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "rev_file", + "dartName": "RevFile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:RevFileKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "headRevision", + "fieldName": "headRevision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "prunedBelow", + "fieldName": "prunedBelow", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "initPending", + "fieldName": "initPending", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "purging", + "fieldName": "purging", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "schemaHash", + "fieldName": "schemaHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "stats", + "fieldName": "stats", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentCount", + "fieldName": "contentCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "rev_file_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 2 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_file_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_file_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "rev_hook_state", + "dartName": "RevHookState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cursorsJson", + "fieldName": "cursorsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseOwner", + "fieldName": "leaseOwner", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastError", + "fieldName": "lastError", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextAttemptAt", + "fieldName": "nextAttemptAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "rev_hook_state_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_hook_state_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_hook_state_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextAttemptAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "rev_op", + "dartName": "RevOp", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientOpId", + "fieldName": "clientOpId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "baseRevision", + "fieldName": "baseRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorId", + "fieldName": "authorId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorUuid", + "fieldName": "authorUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sessionId", + "fieldName": "sessionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "onBehalfOfSessionId", + "fieldName": "onBehalfOfSessionId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupId", + "fieldName": "groupId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupIndex", + "fieldName": "groupIndex", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupLast", + "fieldName": "groupLast", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "recordId", + "fieldName": "recordId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "offline", + "fieldName": "offline", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 5, + "isNullable": true, + "dartType": "dart:typed_data:ByteData?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeCount", + "fieldName": "changeCount", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "summaryJson", + "fieldName": "summaryJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "detailJson", + "fieldName": "detailJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "outcomeJson", + "fieldName": "outcomeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appliedEqualsSubmitted", + "fieldName": "appliedEqualsSubmitted", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientCreatedAt", + "fieldName": "clientCreatedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "committedAt", + "fieldName": "committedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "rev_op_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_rev_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "revision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_client_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "clientOpId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_record_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "recordId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "rev_op_committed_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "committedAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_authorization", + "dartName": "ScriptAuthorization", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scopes", + "fieldName": "scopes", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "grantedAt", + "fieldName": "grantedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revokedAt", + "fieldName": "revokedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_auth_user_sheet_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_build", + "dartName": "ScriptBuild", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "columnDefault": "'ok'", + "dartType": "protocol:ScriptBuildStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sourceHash", + "fieldName": "sourceHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "bytecodeFileUuid", + "fieldName": "bytecodeFileUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "diagnosticsJson", + "fieldName": "diagnosticsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "exportsJson", + "fieldName": "exportsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiVersion", + "fieldName": "apiVersion", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "compilerVersion", + "fieldName": "compilerVersion", + "columnType": 0, + "isNullable": false, + "columnDefault": "''", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "requestedBy", + "fieldName": "requestedBy", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodSourceHash", + "fieldName": "lastGoodSourceHash", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodBytecodeFileUuid", + "fieldName": "lastGoodBytecodeFileUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodExportsJson", + "fieldName": "lastGoodExportsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastGoodBuiltAt", + "fieldName": "lastGoodBuiltAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "positionsFileUuid", + "fieldName": "positionsFileUuid", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "builtAt", + "fieldName": "builtAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_build_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_build_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_build_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_execution", + "dartName": "ScriptExecution", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerId", + "fieldName": "triggerId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runAsUserId", + "fieldName": "runAsUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runtime", + "fieldName": "runtime", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptRuntimeKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "buildSourceHash", + "fieldName": "buildSourceHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "startedAt", + "fieldName": "startedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "durationMs", + "fieldName": "durationMs", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "logs", + "fieldName": "logs", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "errorMessage", + "fieldName": "errorMessage", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "errorStackJson", + "fieldName": "errorStackJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cellsRead", + "fieldName": "cellsRead", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cellsWritten", + "fieldName": "cellsWritten", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fetchCalls", + "fieldName": "fetchCalls", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "callCount", + "fieldName": "callCount", + "columnType": 6, + "isNullable": false, + "columnDefault": "1", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_exec_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_exec_sheet_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "startedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_exec_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "startedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_file", + "dartName": "ScriptFile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "source", + "fieldName": "source", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentHash", + "fieldName": "contentHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedBy", + "fieldName": "updatedBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_file_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_file_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_file_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_job", + "dartName": "ScriptJob", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemUuid", + "fieldName": "itemUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerId", + "fieldName": "triggerId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runAsUserId", + "fieldName": "runAsUserId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payloadJson", + "fieldName": "payloadJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ScriptExecutionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enqueuedAt", + "fieldName": "enqueuedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseOwner", + "fieldName": "leaseOwner", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "coalesced", + "fieldName": "coalesced", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "resultJson", + "fieldName": "resultJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "finishedAt", + "fieldName": "finishedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_job_status_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "enqueuedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_job_trigger_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "triggerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_job_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "runAsUserId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_project", + "dartName": "ScriptProject", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetId", + "fieldName": "spreadsheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "settingsJson", + "fieldName": "settingsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_project_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_project_fk_1", + "columns": [ + "spreadsheetId" + ], + "referenceTable": "spreadsheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_project_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_property", + "dartName": "ScriptProperty", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_property_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_property_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_property_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_quota_usage", + "dartName": "ScriptQuotaUsage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "day", + "fieldName": "day", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "serverRuntimeMs", + "fieldName": "serverRuntimeMs", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "clientRuntimeMs", + "fieldName": "clientRuntimeMs", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "urlFetchCalls", + "fieldName": "urlFetchCalls", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "urlFetchBytes", + "fieldName": "urlFetchBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerRuns", + "fieldName": "triggerRuns", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_quota_user_day_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "day" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_trigger", + "dartName": "ScriptTrigger", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "projectId", + "fieldName": "projectId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:TriggerKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "functionName", + "fieldName": "functionName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scheduleJson", + "fieldName": "scheduleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runAsUserId", + "fieldName": "runAsUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "optionsJson", + "fieldName": "optionsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_trigger_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_trigger_fk_1", + "columns": [ + "projectId" + ], + "referenceTable": "script_project", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_trigger_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_trigger_state", + "dartName": "ScriptTriggerState", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "triggerId", + "fieldName": "triggerId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "scheduleJson", + "fieldName": "scheduleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextRunAt", + "fieldName": "nextRunAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastRunAt", + "fieldName": "lastRunAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastStatus", + "fieldName": "lastStatus", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:ScriptExecutionStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "consecutiveFailures", + "fieldName": "consecutiveFailures", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "disabledReason", + "fieldName": "disabledReason", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "runningSince", + "fieldName": "runningSince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastNotifiedAt", + "fieldName": "lastNotifiedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_trigger_state_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "triggerId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_trigger_state_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextRunAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "script_user_property", + "dartName": "ScriptUserProperty", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "value", + "fieldName": "value", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "script_user_property_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "script_user_property_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "key" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "server_change_record", + "dartName": "ServerChangeRecord", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "label", + "fieldName": "label", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseJson", + "fieldName": "inverseJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "inverseFileId", + "fieldName": "inverseFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "forwardFileId", + "fieldName": "forwardFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "recordId", + "fieldName": "recordId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cellsAffected", + "fieldName": "cellsAffected", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revertedAt", + "fieldName": "revertedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revertChangeId", + "fieldName": "revertChangeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "server_change_record_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "recordId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "server_change_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "server_change_id_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "changeId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "share_link", + "dartName": "ShareLink", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "token", + "fieldName": "token", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "role", + "fieldName": "role", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:AccessRole?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "share_link_fk_0", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "share_link_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "share_link_token_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "token" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheet", + "dartName": "Sheet", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetId", + "fieldName": "spreadsheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "columnDefault": "'grid'", + "dartType": "protocol:SheetKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "tabColor", + "fieldName": "tabColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rightToLeft", + "fieldName": "rightToLeft", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showGridlines", + "fieldName": "showGridlines", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "frozenRows", + "fieldName": "frozenRows", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "frozenColumns", + "fieldName": "frozenColumns", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultRowHeight", + "fieldName": "defaultRowHeight", + "columnType": 3, + "isNullable": false, + "columnDefault": "21.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultColumnWidth", + "fieldName": "defaultColumnWidth", + "columnType": 3, + "isNullable": false, + "columnDefault": "100.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formatJson", + "fieldName": "formatJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "printSettingsJson", + "fieldName": "printSettingsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_fk_1", + "columns": [ + "spreadsheetId" + ], + "referenceTable": "spreadsheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "spreadsheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheet_column", + "dartName": "SheetColumn", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "width", + "fieldName": "width", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formatJson", + "fieldName": "formatJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_column_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_column_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_column_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_column_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheet_row", + "dartName": "SheetRow", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetId", + "fieldName": "sheetId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "height", + "fieldName": "height", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "formatJson", + "fieldName": "formatJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_row_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheet_row_fk_1", + "columns": [ + "sheetId" + ], + "referenceTable": "sheet", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_row_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheet_row_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sheetId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheets_import_job", + "dartName": "SheetsImportJob", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetUuid", + "fieldName": "spreadsheetUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uploadFileId", + "fieldName": "uploadFileId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileName", + "fieldName": "fileName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "format", + "fieldName": "format", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "optionsJson", + "fieldName": "optionsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "activeSheetId", + "fieldName": "activeSheetId", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SheetsImportStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "progressDone", + "fieldName": "progressDone", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "progressTotal", + "fieldName": "progressTotal", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reportJson", + "fieldName": "reportJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetIdsJson", + "fieldName": "sheetIdsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changeId", + "fieldName": "changeId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "errorCode", + "fieldName": "errorCode", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "error", + "fieldName": "error", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "cancelRequested", + "fieldName": "cancelRequested", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseOwner", + "fieldName": "leaseOwner", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheets_import_job_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheets_import_job_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "sheets_snapshot_index", + "dartName": "SheetsSnapshotIndex", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemVersionId", + "fieldName": "itemVersionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetsJson", + "fieldName": "sheetsJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changedRangesJson", + "fieldName": "changedRangesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorIds", + "fieldName": "authorIds", + "columnType": 8, + "isNullable": false, + "dartType": "List" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "diffFileId", + "fieldName": "diffFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "sheets_snapshot_index_fk_0", + "columns": [ + "itemVersionId" + ], + "referenceTable": "item_version", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "sheets_snapshot_index_version_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemVersionId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide", + "dartName": "Slide", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deckId", + "fieldName": "deckId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "groupId", + "fieldName": "groupId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "layoutId", + "fieldName": "layoutId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "skipped", + "fieldName": "skipped", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "notes", + "fieldName": "notes", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "transitionJson", + "fieldName": "transitionJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hideMasterElements", + "fieldName": "hideMasterElements", + "columnType": 1, + "isNullable": true, + "dartType": "bool?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timingsJson", + "fieldName": "timingsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_fk_1", + "columns": [ + "deckId" + ], + "referenceTable": "deck", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deckId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_build", + "dartName": "SlideBuild", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slideId", + "fieldName": "slideId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BuildKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "effect", + "fieldName": "effect", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trigger", + "fieldName": "trigger", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:BuildTrigger" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "delayMs", + "fieldName": "delayMs", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "durationMs", + "fieldName": "durationMs", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "easing", + "fieldName": "easing", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "optionsJson", + "fieldName": "optionsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_build_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_build_fk_1", + "columns": [ + "slideId" + ], + "referenceTable": "slide", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_build_fk_2", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_build_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_build_slide_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "slideId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_build_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_element", + "dartName": "SlideElement", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slideId", + "fieldName": "slideId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "layoutId", + "fieldName": "layoutId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "masterId", + "fieldName": "masterId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "parentId", + "fieldName": "parentId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SlideElementKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "x", + "fieldName": "x", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "y", + "fieldName": "y", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "width", + "fieldName": "width", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "height", + "fieldName": "height", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rotation", + "fieldName": "rotation", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "flipH", + "fieldName": "flipH", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "flipV", + "fieldName": "flipV", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "zKey", + "fieldName": "zKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "readingKey", + "fieldName": "readingKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "locked", + "fieldName": "locked", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "placeholderType", + "fieldName": "placeholderType", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:PlaceholderType?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "placeholderOf", + "fieldName": "placeholderOf", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "matchKey", + "fieldName": "matchKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "text", + "fieldName": "text", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "textStyleJson", + "fieldName": "textStyleJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fillJson", + "fieldName": "fillJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "strokeJson", + "fieldName": "strokeJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "effectsJson", + "fieldName": "effectsJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "opacity", + "fieldName": "opacity", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dataJson", + "fieldName": "dataJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "linkJson", + "fieldName": "linkJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "altText", + "fieldName": "altText", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "decorative", + "fieldName": "decorative", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_1", + "columns": [ + "slideId" + ], + "referenceTable": "slide", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_2", + "columns": [ + "layoutId" + ], + "referenceTable": "slide_layout", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_3", + "columns": [ + "masterId" + ], + "referenceTable": "slide_master", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_element_fk_4", + "columns": [ + "parentId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_slide_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "slideId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "zKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_layout_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "layoutId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_master_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "masterId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_element_parent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "parentId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_group", + "dartName": "SlideGroup", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deckId", + "fieldName": "deckId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "parentId", + "fieldName": "parentId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "color", + "fieldName": "color", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "skipped", + "fieldName": "skipped", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_group_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_group_fk_1", + "columns": [ + "deckId" + ], + "referenceTable": "deck", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_group_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_group_order_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deckId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_layout", + "dartName": "SlideLayout", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "masterId", + "fieldName": "masterId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "key", + "fieldName": "key", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hideMasterElements", + "fieldName": "hideMasterElements", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "hidden", + "fieldName": "hidden", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_layout_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_layout_fk_1", + "columns": [ + "masterId" + ], + "referenceTable": "slide_master", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_layout_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_layout_master_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "masterId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_master", + "dartName": "SlideMaster", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "backgroundJson", + "fieldName": "backgroundJson", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_master_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_master_fk_1", + "columns": [ + "themeId" + ], + "referenceTable": "deck_theme", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_master_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_master_theme_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "themeId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_table_axis", + "dartName": "SlideTableAxis", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "dimension", + "fieldName": "dimension", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:TableDimension" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sortKey", + "fieldName": "sortKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "size", + "fieldName": "size", + "columnType": 3, + "isNullable": true, + "dartType": "double?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "header", + "fieldName": "header", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_axis_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_axis_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_axis_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_axis_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sortKey" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slide_table_cell", + "dartName": "SlideTableCell", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "elementId", + "fieldName": "elementId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowId", + "fieldName": "rowId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "columnId", + "fieldName": "columnId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "text", + "fieldName": "text", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fill", + "fieldName": "fill", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderTop", + "fieldName": "borderTop", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderRight", + "fieldName": "borderRight", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderBottom", + "fieldName": "borderBottom", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "borderLeft", + "fieldName": "borderLeft", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "vAlign", + "fieldName": "vAlign", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "padding", + "fieldName": "padding", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "rowSpan", + "fieldName": "rowSpan", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "colSpan", + "fieldName": "colSpan", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_1", + "columns": [ + "elementId" + ], + "referenceTable": "slide_element", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_2", + "columns": [ + "rowId" + ], + "referenceTable": "slide_table_axis", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slide_table_cell_fk_3", + "columns": [ + "columnId" + ], + "referenceTable": "slide_table_axis", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4, + "deferrable": "initiallyDeferred" + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_cell_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slide_table_cell_element_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "elementId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "slides_snapshot_index", + "dartName": "SlidesSnapshotIndex", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemVersionId", + "fieldName": "itemVersionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slidesJson", + "fieldName": "slidesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "changesJson", + "fieldName": "changesJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authorIds", + "fieldName": "authorIds", + "columnType": 8, + "isNullable": false, + "dartType": "List" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "slides_snapshot_index_fk_0", + "columns": [ + "itemVersionId" + ], + "referenceTable": "item_version", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "slides_snapshot_index_version_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemVersionId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "spreadsheet", + "dartName": "Spreadsheet", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 7, + "isNullable": false, + "columnDefault": "random_v7", + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileId", + "fieldName": "fileId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "title", + "fieldName": "title", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "locale", + "fieldName": "locale", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timeZone", + "fieldName": "timeZone", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "recalcMode", + "fieldName": "recalcMode", + "columnType": 0, + "isNullable": false, + "columnDefault": "'onChange'", + "dartType": "protocol:RecalcMode" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "iterativeCalc", + "fieldName": "iterativeCalc", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "maxIterations", + "fieldName": "maxIterations", + "columnType": 6, + "isNullable": false, + "columnDefault": "50", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "convergenceThreshold", + "fieldName": "convergenceThreshold", + "columnType": 3, + "isNullable": false, + "columnDefault": "0.05", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultFontFamily", + "fieldName": "defaultFontFamily", + "columnType": 0, + "isNullable": false, + "columnDefault": "'Inter'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "defaultFontSize", + "fieldName": "defaultFontSize", + "columnType": 3, + "isNullable": false, + "columnDefault": "10.0", + "dartType": "double" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeJson", + "fieldName": "themeJson", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayLanguage", + "fieldName": "displayLanguage", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdBy", + "fieldName": "createdBy", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "spreadsheet_fk_0", + "columns": [ + "fileId" + ], + "referenceTable": "rev_file", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "spreadsheet_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "id" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "storage_reservation", + "dartName": "StorageReservation", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "bytes", + "fieldName": "bytes", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "storage_reservation_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "storage_reservation_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "storage_reservation_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "storage_reservation_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "storage_reservation_expiry_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "stored_file", + "dartName": "StoredFile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "kind", + "fieldName": "kind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:StoredFileKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "storageId", + "fieldName": "storageId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "path", + "fieldName": "path", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileName", + "fieldName": "fileName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "mimeType", + "fieldName": "mimeType", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sizeBytes", + "fieldName": "sizeBytes", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:StoredFileStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "completedAt", + "fieldName": "completedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "expiresAt", + "fieldName": "expiresAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "stored_file_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "stored_file_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_expiry_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "expiresAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_owner_kind_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "kind" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "stored_file_status_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "submission", + "dartName": "Submission", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ref", + "fieldName": "ref", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SubmissionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "statusBeforeSubmit", + "fieldName": "statusBeforeSubmit", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:SubmissionStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "delivery", + "fieldName": "delivery", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:SubmissionDeliveryState?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "values", + "fieldName": "values", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:SubmissionValues" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicUrl", + "fieldName": "publicUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feedbackThreadId", + "fieldName": "feedbackThreadId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "disconnectedAt", + "fieldName": "disconnectedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_publication_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "submission_asset", + "dartName": "SubmissionAsset", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_asset_fk_0", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_asset_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "submissionId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_asset_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "submission_revision", + "dartName": "SubmissionRevision", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sequence", + "fieldName": "sequence", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "versionId", + "fieldName": "versionId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "values", + "fieldName": "values", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:SubmissionValues" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submittedById", + "fieldName": "submittedById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submittedAt", + "fieldName": "submittedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_revision_fk_0", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_revision_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "submissionId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sequence" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_activity_settings", + "dartName": "UserActivitySettings", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "showViewHistory", + "fieldName": "showViewHistory", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_activity_settings_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_activity_settings_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_preferences", + "dartName": "UserPreferences", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "appTheme", + "fieldName": "appTheme", + "columnType": 0, + "isNullable": false, + "columnDefault": "'system'", + "dartType": "protocol:AppThemeMode" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "accentColor", + "fieldName": "accentColor", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "density", + "fieldName": "density", + "columnType": 0, + "isNullable": false, + "columnDefault": "'comfortable'", + "dartType": "protocol:UiDensity" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reduceMotion", + "fieldName": "reduceMotion", + "columnType": 1, + "isNullable": false, + "columnDefault": "false", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "keymapOverrides", + "fieldName": "keymapOverrides", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "writeDefaults", + "fieldName": "writeDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sheetsDefaults", + "fieldName": "sheetsDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slidesDefaults", + "fieldName": "slidesDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "slidesPresenter", + "fieldName": "slidesPresenter", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "driveDefaults", + "fieldName": "driveDefaults", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "notificationSettings", + "fieldName": "notificationSettings", + "columnType": 0, + "isNullable": false, + "columnDefault": "'{}'", + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "aiEnabled", + "fieldName": "aiEnabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_preferences_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_preferences_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_profile", + "dartName": "UserProfile", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "authUserId", + "fieldName": "authUserId", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "displayName", + "fieldName": "displayName", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "avatarFileId", + "fieldName": "avatarFileId", + "columnType": 7, + "isNullable": true, + "dartType": "UuidValue?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "avatarColor", + "fieldName": "avatarColor", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "locale", + "fieldName": "locale", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "timeZone", + "fieldName": "timeZone", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastSeenAt", + "fieldName": "lastSeenAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "welcomeContentAt", + "fieldName": "welcomeContentAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_profile_fk_0", + "columns": [ + "authUserId" + ], + "referenceTable": "serverpod_auth_core_user", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_profile_auth_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "authUserId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_profile_email_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "user_storage", + "dartName": "UserStorage", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "usedBytes", + "fieldName": "usedBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reservedBytes", + "fieldName": "reservedBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentsBytes", + "fieldName": "documentsBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "spreadsheetsBytes", + "fieldName": "spreadsheetsBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "presentationsBytes", + "fieldName": "presentationsBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "filesBytes", + "fieldName": "filesBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "trashBytes", + "fieldName": "trashBytes", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "quotaBytesOverride", + "fieldName": "quotaBytesOverride", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "overQuotaSince", + "fieldName": "overQuotaSince", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "reconciledAt", + "fieldName": "reconciledAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "user_storage_fk_0", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "user_storage_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "write_diff_cache", + "dartName": "WriteDiffCache", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "documentId", + "fieldName": "documentId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fromRevision", + "fieldName": "fromRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "toRevision", + "fieldName": "toRevision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "json", + "fieldName": "json", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "write_diff_cache_fk_0", + "columns": [ + "documentId" + ], + "referenceTable": "document", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_diff_cache_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "documentId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fromRevision" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "toRevision" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_diff_cache_created_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "brin", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "write_theme", + "dartName": "WriteTheme", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "isBuiltin", + "fieldName": "isBuiltin", + "columnType": 1, + "isNullable": false, + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "builtinKey", + "fieldName": "builtinKey", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "description", + "fieldName": "description", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "schemaVersion", + "fieldName": "schemaVersion", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "version", + "fieldName": "version", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "json", + "fieldName": "json", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "contentHash", + "fieldName": "contentHash", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deletedAt", + "fieldName": "deletedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "write_theme_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "deletedAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_builtin_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "builtinKey" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + }, + { + "__className__": "serverpod.TableDefinition", + "name": "write_theme_revision", + "dartName": "WriteThemeRevision", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "themeId", + "fieldName": "themeId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "version", + "fieldName": "version", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "json", + "fieldName": "json", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "savedById", + "fieldName": "savedById", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "actorKind", + "fieldName": "actorKind", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:ActorKind" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "write_theme_revision_fk_0", + "columns": [ + "themeId" + ], + "referenceTable": "write_theme", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "write_theme_rev_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "themeId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "version" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + } + ], + "installedModules": [ + { + "__className__": "serverpod.DatabaseMigrationVersion", + "module": "serverpod", + "version": "20260824182259319" + }, + { + "__className__": "serverpod.DatabaseMigrationVersion", + "module": "serverpod_auth_idp", + "version": "20260924105404509" + }, + { + "__className__": "serverpod.DatabaseMigrationVersion", + "module": "serverpod_auth_core", + "version": "20260924105232991" + } + ], + "migrationApiVersion": 1 +} \ No newline at end of file diff --git a/wonky_server/migrations/20261020084059086-publications/migration.json b/wonky_server/migrations/20261020084059086-publications/migration.json new file mode 100644 index 00000000..7b2287ea --- /dev/null +++ b/wonky_server/migrations/20261020084059086-publications/migration.json @@ -0,0 +1,1290 @@ +{ + "__className__": "serverpod.DatabaseMigration", + "actions": [ + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "alterTable", + "alterTable": { + "__className__": "serverpod.TableMigration", + "name": "comment", + "schema": "public", + "addColumns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "deleteColumns": [], + "modifyColumns": [], + "addIndexes": [], + "deleteIndexes": [], + "addForeignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "comment_fk_1", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "deleteForeignKeys": [], + "warnings": [] + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "alterTable", + "alterTable": { + "__className__": "serverpod.TableMigration", + "name": "drive_item_permission", + "schema": "public", + "addColumns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "viaPublicationId", + "fieldName": "viaPublicationId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + } + ], + "deleteColumns": [], + "modifyColumns": [], + "addIndexes": [], + "deleteIndexes": [], + "addForeignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "drive_item_permission_fk_2", + "columns": [ + "viaPublicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "deleteForeignKeys": [], + "warnings": [] + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "publication", + "dartName": "Publication", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicId", + "fieldName": "publicId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ownerId", + "fieldName": "ownerId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "name", + "fieldName": "name", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "siteUrl", + "fieldName": "siteUrl", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "webhookUrl", + "fieldName": "webhookUrl", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verifiedHost", + "fieldName": "verifiedHost", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "verifiedAt", + "fieldName": "verifiedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "templateItemId", + "fieldName": "templateItemId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "termsUrl", + "fieldName": "termsUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fields", + "fieldName": "fields", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:PublicationFields" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "signingSecret", + "fieldName": "signingSecret", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previousSigningSecret", + "fieldName": "previousSigningSecret", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "previousSecretUntil", + "fieldName": "previousSecretUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKeyHash", + "fieldName": "apiKeyHash", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "apiKeyLast4", + "fieldName": "apiKeyLast4", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "enabled", + "fieldName": "enabled", + "columnType": 1, + "isNullable": false, + "columnDefault": "true", + "dartType": "bool" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_fk_0", + "columns": [ + "ownerId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_fk_1", + "columns": [ + "templateItemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_public_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_owner_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "ownerId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_api_key_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "apiKeyHash" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "publication_block", + "dartName": "PublicationBlock", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_block_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_block_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_block_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "publication_consent", + "dartName": "PublicationConsent", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "consentKey", + "fieldName": "consentKey", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "at", + "fieldName": "at", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_consent_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_consent_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_consent_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "publication_delivery", + "dartName": "PublicationDelivery", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "webhookId", + "fieldName": "webhookId", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "type", + "fieldName": "type", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sequence", + "fieldName": "sequence", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "attempts", + "fieldName": "attempts", + "columnType": 6, + "isNullable": false, + "columnDefault": "0", + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "nextAttemptAt", + "fieldName": "nextAttemptAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "leaseUntil", + "fieldName": "leaseUntil", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastStatus", + "fieldName": "lastStatus", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "lastError", + "fieldName": "lastError", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "deliveredAt", + "fieldName": "deliveredAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "failedAt", + "fieldName": "failedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_delivery_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_delivery_fk_1", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 0 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_webhook_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "webhookId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_due_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "nextAttemptAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_delivery_publication_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "createdAt" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "publication_moderator", + "dartName": "PublicationModerator", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "userId", + "fieldName": "userId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "email", + "fieldName": "email", + "columnType": 0, + "isNullable": false, + "dartType": "String" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_moderator_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "publication_moderator_fk_1", + "columns": [ + "userId" + ], + "referenceTable": "user_profile", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_moderator_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "email" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "publication_moderator_user_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "userId" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "submission", + "dartName": "Submission", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "uuid", + "fieldName": "uuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicationId", + "fieldName": "publicationId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "itemId", + "fieldName": "itemId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "ref", + "fieldName": "ref", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "status", + "fieldName": "status", + "columnType": 0, + "isNullable": false, + "dartType": "protocol:SubmissionStatus" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "statusBeforeSubmit", + "fieldName": "statusBeforeSubmit", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:SubmissionStatus?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "delivery", + "fieldName": "delivery", + "columnType": 0, + "isNullable": true, + "dartType": "protocol:SubmissionDeliveryState?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "values", + "fieldName": "values", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:SubmissionValues" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "publicUrl", + "fieldName": "publicUrl", + "columnType": 0, + "isNullable": true, + "dartType": "String?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "feedbackThreadId", + "fieldName": "feedbackThreadId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdById", + "fieldName": "createdById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "createdAt", + "fieldName": "createdAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "updatedAt", + "fieldName": "updatedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "disconnectedAt", + "fieldName": "disconnectedAt", + "columnType": 4, + "isNullable": true, + "dartType": "DateTime?" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_fk_0", + "columns": [ + "publicationId" + ], + "referenceTable": "publication", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + }, + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_fk_1", + "columns": [ + "itemId" + ], + "referenceTable": "drive_item", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_uuid_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "uuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_item_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "itemId" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_publication_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "publicationId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "status" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "submission_asset", + "dartName": "SubmissionAsset", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "fileUuid", + "fieldName": "fileUuid", + "columnType": 7, + "isNullable": false, + "dartType": "UuidValue" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_asset_fk_0", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_asset_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "submissionId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + }, + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_asset_file_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "fileUuid" + } + ], + "type": "btree", + "isUnique": false, + "isPrimary": false + } + ], + "managed": true + } + }, + { + "__className__": "serverpod.DatabaseMigrationAction", + "type": "createTable", + "createTable": { + "__className__": "serverpod.TableDefinition", + "name": "submission_revision", + "dartName": "SubmissionRevision", + "module": "wonky", + "schema": "public", + "columns": [ + { + "__className__": "serverpod.ColumnDefinition", + "name": "id", + "fieldName": "id", + "columnType": 6, + "isNullable": false, + "columnDefault": "serial", + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submissionId", + "fieldName": "submissionId", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "sequence", + "fieldName": "sequence", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "revision", + "fieldName": "revision", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "versionId", + "fieldName": "versionId", + "columnType": 6, + "isNullable": true, + "dartType": "int?" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "values", + "fieldName": "values", + "columnType": 8, + "isNullable": false, + "dartType": "protocol:SubmissionValues" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "payload", + "fieldName": "payload", + "columnType": 0, + "isNullable": false, + "dartType": "String" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submittedById", + "fieldName": "submittedById", + "columnType": 6, + "isNullable": false, + "dartType": "int" + }, + { + "__className__": "serverpod.ColumnDefinition", + "name": "submittedAt", + "fieldName": "submittedAt", + "columnType": 4, + "isNullable": false, + "dartType": "DateTime" + } + ], + "foreignKeys": [ + { + "__className__": "serverpod.ForeignKeyDefinition", + "constraintName": "submission_revision_fk_0", + "columns": [ + "submissionId" + ], + "referenceTable": "submission", + "referenceTableSchema": "public", + "referenceColumns": [ + "id" + ], + "onUpdate": 3, + "onDelete": 4 + } + ], + "indexes": [ + { + "__className__": "serverpod.IndexDefinition", + "indexName": "submission_revision_idx", + "elements": [ + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "submissionId" + }, + { + "__className__": "serverpod.IndexElementDefinition", + "type": 0, + "definition": "sequence" + } + ], + "type": "btree", + "isUnique": true, + "isPrimary": false + } + ], + "managed": true + } + } + ], + "warnings": [], + "migrationApiVersion": 1 +} \ No newline at end of file diff --git a/wonky_server/migrations/20261020084059086-publications/migration.sql b/wonky_server/migrations/20261020084059086-publications/migration.sql new file mode 100644 index 00000000..a7cd17cb --- /dev/null +++ b/wonky_server/migrations/20261020084059086-publications/migration.sql @@ -0,0 +1,333 @@ +BEGIN; + +-- +-- ACTION ALTER TABLE +-- +ALTER TABLE "comment" ADD COLUMN "publicationId" bigint; +-- +-- ACTION ALTER TABLE +-- +ALTER TABLE "drive_item_permission" ADD COLUMN "viaPublicationId" bigint; +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "publication" ( + "id" bigserial PRIMARY KEY, + "publicId" text NOT NULL, + "ownerId" bigint NOT NULL, + "name" text NOT NULL, + "siteUrl" text NOT NULL, + "webhookUrl" text NOT NULL, + "verifiedHost" text, + "verifiedAt" timestamp without time zone, + "templateItemId" bigint, + "termsUrl" text, + "fields" json NOT NULL, + "signingSecret" text NOT NULL, + "previousSigningSecret" text, + "previousSecretUntil" timestamp without time zone, + "apiKeyHash" text, + "apiKeyLast4" text, + "enabled" boolean NOT NULL DEFAULT true, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_public_idx" ON "publication" USING btree ("publicId"); +CREATE INDEX "publication_owner_idx" ON "publication" USING btree ("ownerId"); +CREATE INDEX "publication_api_key_idx" ON "publication" USING btree ("apiKeyHash"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "publication_block" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "userId" bigint NOT NULL, + "at" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_block_idx" ON "publication_block" USING btree ("publicationId", "userId"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "publication_consent" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "userId" bigint NOT NULL, + "consentKey" text NOT NULL, + "at" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_consent_idx" ON "publication_consent" USING btree ("publicationId", "userId"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "publication_delivery" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "submissionId" bigint, + "webhookId" text NOT NULL, + "type" text NOT NULL, + "sequence" bigint, + "payload" text NOT NULL, + "attempts" bigint NOT NULL DEFAULT 0, + "nextAttemptAt" timestamp without time zone, + "leaseUntil" timestamp without time zone, + "lastStatus" bigint, + "lastError" text, + "deliveredAt" timestamp without time zone, + "failedAt" timestamp without time zone, + "createdAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_delivery_webhook_idx" ON "publication_delivery" USING btree ("webhookId"); +CREATE INDEX "publication_delivery_due_idx" ON "publication_delivery" USING btree ("nextAttemptAt"); +CREATE INDEX "publication_delivery_publication_idx" ON "publication_delivery" USING btree ("publicationId", "createdAt"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "publication_moderator" ( + "id" bigserial PRIMARY KEY, + "publicationId" bigint NOT NULL, + "userId" bigint, + "email" text NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "publication_moderator_idx" ON "publication_moderator" USING btree ("publicationId", "email"); +CREATE INDEX "publication_moderator_user_idx" ON "publication_moderator" USING btree ("userId"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "submission" ( + "id" bigserial PRIMARY KEY, + "uuid" uuid NOT NULL, + "publicationId" bigint NOT NULL, + "itemId" bigint NOT NULL, + "ref" text, + "status" text NOT NULL, + "statusBeforeSubmit" text, + "delivery" text, + "values" json NOT NULL, + "publicUrl" text, + "feedbackThreadId" bigint, + "createdById" bigint NOT NULL, + "createdAt" timestamp without time zone NOT NULL, + "updatedAt" timestamp without time zone NOT NULL, + "disconnectedAt" timestamp without time zone +); + +-- Indexes +CREATE UNIQUE INDEX "submission_uuid_idx" ON "submission" USING btree ("uuid"); +CREATE UNIQUE INDEX "submission_item_idx" ON "submission" USING btree ("itemId"); +CREATE INDEX "submission_publication_idx" ON "submission" USING btree ("publicationId", "status"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "submission_asset" ( + "id" bigserial PRIMARY KEY, + "submissionId" bigint NOT NULL, + "fileUuid" uuid NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "submission_asset_idx" ON "submission_asset" USING btree ("submissionId", "fileUuid"); +CREATE INDEX "submission_asset_file_idx" ON "submission_asset" USING btree ("fileUuid"); + +-- +-- ACTION CREATE TABLE +-- +CREATE TABLE "submission_revision" ( + "id" bigserial PRIMARY KEY, + "submissionId" bigint NOT NULL, + "sequence" bigint NOT NULL, + "revision" bigint NOT NULL, + "versionId" bigint, + "values" json NOT NULL, + "payload" text NOT NULL, + "submittedById" bigint NOT NULL, + "submittedAt" timestamp without time zone NOT NULL +); + +-- Indexes +CREATE UNIQUE INDEX "submission_revision_idx" ON "submission_revision" USING btree ("submissionId", "sequence"); + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "comment" + ADD CONSTRAINT "comment_fk_1" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "drive_item_permission" + ADD CONSTRAINT "drive_item_permission_fk_2" + FOREIGN KEY("viaPublicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "publication" + ADD CONSTRAINT "publication_fk_0" + FOREIGN KEY("ownerId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication" + ADD CONSTRAINT "publication_fk_1" + FOREIGN KEY("templateItemId") + REFERENCES "drive_item"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "publication_block" + ADD CONSTRAINT "publication_block_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_block" + ADD CONSTRAINT "publication_block_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "publication_consent" + ADD CONSTRAINT "publication_consent_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_consent" + ADD CONSTRAINT "publication_consent_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "publication_delivery" + ADD CONSTRAINT "publication_delivery_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_delivery" + ADD CONSTRAINT "publication_delivery_fk_1" + FOREIGN KEY("submissionId") + REFERENCES "submission"("id") + ON DELETE SET NULL + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "publication_moderator" + ADD CONSTRAINT "publication_moderator_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "publication_moderator" + ADD CONSTRAINT "publication_moderator_fk_1" + FOREIGN KEY("userId") + REFERENCES "user_profile"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "submission" + ADD CONSTRAINT "submission_fk_0" + FOREIGN KEY("publicationId") + REFERENCES "publication"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; +ALTER TABLE ONLY "submission" + ADD CONSTRAINT "submission_fk_1" + FOREIGN KEY("itemId") + REFERENCES "drive_item"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "submission_asset" + ADD CONSTRAINT "submission_asset_fk_0" + FOREIGN KEY("submissionId") + REFERENCES "submission"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + +-- +-- ACTION CREATE FOREIGN KEY +-- +ALTER TABLE ONLY "submission_revision" + ADD CONSTRAINT "submission_revision_fk_0" + FOREIGN KEY("submissionId") + REFERENCES "submission"("id") + ON DELETE CASCADE + ON UPDATE NO ACTION; + + +-- +-- MIGRATION VERSION FOR wonky +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('wonky', '20261020084059086-publications', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20261020084059086-publications', "timestamp" = now(); + +-- +-- MIGRATION VERSION FOR serverpod +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('serverpod', '20260824182259319', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20260824182259319', "timestamp" = now(); + +-- +-- MIGRATION VERSION FOR serverpod_auth_idp +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('serverpod_auth_idp', '20260924105404509', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20260924105404509', "timestamp" = now(); + +-- +-- MIGRATION VERSION FOR serverpod_auth_core +-- +INSERT INTO "serverpod_migrations" ("module", "version", "timestamp") + VALUES ('serverpod_auth_core', '20260924105232991', now()) + ON CONFLICT ("module") + DO UPDATE SET "version" = '20260924105232991', "timestamp" = now(); + + +COMMIT; diff --git a/wonky_server/migrations/migration_registry.txt b/wonky_server/migrations/migration_registry.txt index 83178021..02d7a1f7 100644 --- a/wonky_server/migrations/migration_registry.txt +++ b/wonky_server/migrations/migration_registry.txt @@ -29,3 +29,4 @@ 20261018123013739-quality-wave1-server 20261018144655713-neutral-record-names 20261019202955634-board-claim-limits +20261020084059086-publications diff --git a/wonky_server/test/integration/platform/publications/publication_api_test.dart b/wonky_server/test/integration/platform/publications/publication_api_test.dart new file mode 100644 index 00000000..2536981a --- /dev/null +++ b/wonky_server/test/integration/platform/publications/publication_api_test.dart @@ -0,0 +1,399 @@ +@Tags(['integration']) +library; + +import 'dart:convert'; +import 'dart:io'; + +import 'package:serverpod/serverpod.dart'; +import 'package:test/test.dart'; +import 'package:wonky_server/src/platform/common/models.dart'; +import 'package:wonky_server/src/web/routes/publication_api_route.dart'; + +import '../../../support/publications/publication_harness.dart'; +import '../../../support/test_users.dart'; +import '../../../support/wonky_serverpod.dart'; + +void main() { + withWonkyServerpod('Given a submitted story and the publication API', ( + sessionBuilder, + endpoints, + ) { + final h = PublicationHarness(); + final client = HttpClient(); + late Uri base; + late TestUser owner; + late TestUser anna; + late TestPublication pub; + late UuidValue doc; + late String submissionId; + + setUpAll(() async { + final pod = sessionBuilder.build().serverpod; + pod.webServer.addRoute(PublicationApiRoute(pod: pod), '/api/pub/v1/**'); + if (!pod.webServer.running) await pod.webServer.start(); + base = Uri.parse('http://localhost:${pod.webServer.port}/api/pub/v1/'); + }); + tearDownAll(() => client.close(force: true)); + + setUp(() async { + h.install(); + owner = await TestUsers.create(sessionBuilder, name: 'Owner'); + anna = await TestUsers.create(sessionBuilder, name: 'Anna'); + pub = await h.create(endpoints, owner); + doc = await h.start(endpoints, anna, pub); + final view = await endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(title: 'Faster CI'), + false, + ); + submissionId = view.id; + h.blog.received.clear(); + }); + tearDown(h.uninstall); + + Future<(int, Map)> call( + String method, + String path, { + Object? body, + String? key, + }) async { + final req = await client.openUrl(method, base.resolve(path)); + final k = key ?? pub.apiKey; + if (k.isNotEmpty) req.headers.set('authorization', 'Bearer $k'); + if (body != null) { + req.headers.contentType = ContentType.json; + req.write(jsonEncode(body)); + } + final res = await req.close(); + final text = await utf8.decodeStream(res); + final json = text.isEmpty ? {} : jsonDecode(text); + return ( + res.statusCode, + json is Map ? json.cast() : {}, + ); + } + + test( + 'when calling without a key or with a wrong one then it is 401', + () async { + final (none, _) = await call('GET', 'submissions', key: ''); + final (wrong, body) = await call( + 'GET', + 'submissions', + key: 'wpk_${'a' * 40}', + ); + + expect(none, 401); + expect(wrong, 401); + expect(body['error'], 'unauthorized'); + }, + ); + + test('when listing then the submission is there in review', () async { + final (status, body) = await call('GET', 'submissions'); + + final list = body['submissions']! as List; + expect(status, 200); + expect((list.single as Map)['id'], submissionId); + expect((list.single as Map)['status'], 'inReview'); + expect((list.single as Map)['title'], 'Faster CI'); + expect(body['next'], isNull); + }); + + test('when reading the content then it is the webhook body', () async { + final (status, body) = await call( + 'GET', + 'submissions/$submissionId/content?sequence=1', + ); + + expect(status, 200); + expect(body['type'], 'submission.submitted'); + expect(body['sequence'], 1); + }); + + test( + 'when requesting changes with a message then the contributor sees ' + 'it in a thread under the publication\'s name and is notified', + () async { + final (status, body) = await call( + 'POST', + 'submissions/$submissionId/status', + body: {'status': 'changesRequested', 'message': 'Add an intro.'}, + ); + + final view = await endpoints.submission.get(anna.endpointSession, doc); + final threads = await endpoints.comment.listThreads( + anna.endpointSession, + doc, + CommentFilter.all, + ); + final notes = await UserNotification.db.find( + sessionBuilder.build(), + where: (t) => + t.userId.equals(anna.id) & + t.kind.equals(NotificationKind.submission), + ); + expect(status, 200); + expect(body['status'], 'changesRequested'); + expect(view!.status, SubmissionStatus.changesRequested); + expect(view.lastMessage, contains('Add an intro.')); + final thread = threads.singleWhere( + (t) => t.uuid == view.feedbackThreadUuid, + ); + expect(thread.comments.single.authorLabel, 'Serverpod blog'); + expect(thread.comments.single.body, contains('**Changes requested**')); + expect(notes, hasLength(1)); + }, + ); + + test('when the contributor replies in the thread then the blog gets ' + 'comment.created', () async { + await call( + 'POST', + 'submissions/$submissionId/messages', + body: {'body': 'Thanks, reading it now.'}, + ); + final view = await endpoints.submission.get(anna.endpointSession, doc); + + await endpoints.comment.reply( + anna.endpointSession, + view!.feedbackThreadUuid!, + 'Great, thanks!', + [], + ); + await h.deliverScheduled(sessionBuilder); + + final hook = h.blog.ofType('comment.created').single; + final comment = hook.json['comment']! as Map; + expect(pub.signed(hook), isTrue); + expect(comment['body'], 'Great, thanks!'); + expect((comment['author']! as Map)['isModerator'], isFalse); + }); + + test('when publishing without a URL then it is 400, with one 200 and the ' + 'URL is shown', () async { + final (bad, _) = await call( + 'POST', + 'submissions/$submissionId/status', + body: {'status': 'published'}, + ); + final (ok, body) = await call( + 'POST', + 'submissions/$submissionId/status', + body: { + 'status': 'published', + 'publicUrl': 'https://blog.example.com/posts/faster-ci', + }, + ); + + final view = await endpoints.submission.get(anna.endpointSession, doc); + expect(bad, 400); + expect(ok, 200); + expect(body['publicUrl'], 'https://blog.example.com/posts/faster-ci'); + expect(view!.publicUrl, 'https://blog.example.com/posts/faster-ci'); + }); + + test('when changing a declined story then it is 409', () async { + await call( + 'POST', + 'submissions/$submissionId/status', + body: {'status': 'declined'}, + ); + + final (status, body) = await call( + 'POST', + 'submissions/$submissionId/status', + body: {'status': 'changesRequested'}, + ); + + expect(status, 409); + expect(body['error'], 'invalidTransition'); + }); + + test('when the story was withdrawn then a status call is 410', () async { + await endpoints.submission.withdraw(anna.endpointSession, doc); + + final (status, _) = await call( + 'POST', + 'submissions/$submissionId/status', + body: {'status': 'declined'}, + ); + + expect(status, 410); + }); + + test('when another publication\'s key is used then the submission is ' + 'not found', () async { + final other = await h.create( + endpoints, + owner, + input: PublicationHarness.input(name: 'Other blog'), + ); + + final (status, _) = await call( + 'GET', + 'submissions/$submissionId', + key: other.apiKey, + ); + + expect(status, 404); + }); + + test('when an asset was never submitted then it is 404', () async { + final (status, _) = await call( + 'GET', + 'assets/ast_${const Uuid().v7()}', + ); + + expect(status, 404); + }); + + test( + 'when the contributor is blocked then submitting is refused', + () async { + final (status, _) = await call( + 'POST', + 'blocks', + body: {'wonkyUserId': anna.authUserId.uuid}, + ); + + expect(status, 200); + await expectLater( + endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(), + false, + ), + throwsA(isA()), + ); + }, + ); + + test('when the API key is rotated then the old key is refused', () async { + await endpoints.publication.createApiKey( + owner.endpointSession, + pub.publicId, + ); + + final (status, _) = await call('GET', 'submissions'); + + expect(status, 401); + }); + }); + + withWonkyServerpod('Given a publication owner', (sessionBuilder, endpoints) { + final h = PublicationHarness(); + late TestUser owner; + late TestUser bo; + late TestPublication pub; + + setUp(() async { + h.install(); + owner = await TestUsers.create(sessionBuilder, name: 'Owner'); + bo = await TestUsers.create(sessionBuilder, name: 'Bo'); + pub = await h.create(endpoints, owner); + }); + tearDown(h.uninstall); + + test('when creating with an http webhook then it is refused', () async { + await expectLater( + endpoints.publication.create( + owner.endpointSession, + PublicationHarness.input(webhookUrl: 'http://blog.example.com/hook'), + ), + throwsA(isA()), + ); + }); + + test('when someone else updates it then it is not found', () async { + await expectLater( + endpoints.publication.update( + bo.endpointSession, + pub.publicId, + PublicationHarness.input(), + ), + throwsA( + isA().having( + (e) => e.code, + 'code', + WonkyErrorCode.notFound, + ), + ), + ); + }); + + test('when the site lists the publication then verify marks it verified ' + 'and contributors see the site host', () async { + h.blog.pages['https://blog.example.com/.well-known/wonky-publications.json'] = + jsonEncode({ + 'publications': [pub.publicId], + }); + + final result = await endpoints.publication.verify( + owner.endpointSession, + pub.publicId, + ); + final card = await endpoints.publication.resolve( + bo.endpointSession, + pub.publicId, + ); + + expect(result.ok, isTrue); + expect(result.settings.verifiedHost, 'blog.example.com'); + expect(card.verified, isTrue); + }); + + test('when the site doesn\'t list it then verify explains why', () async { + final result = await endpoints.publication.verify( + owner.endpointSession, + pub.publicId, + ); + + expect(result.ok, isFalse); + expect(result.message, contains('404')); + }); + + test( + 'when the secret is rotated then webhooks carry both signatures', + () async { + final rotated = await endpoints.publication.rotateSecret( + owner.endpointSession, + pub.publicId, + ); + + final test = await endpoints.publication.sendTest( + owner.endpointSession, + pub.publicId, + ); + + final hook = h.blog.ofType('publication.ping').last; + expect(test.ok, isTrue); + expect(pub.signed(hook), isTrue); + expect( + TestPublication(pub.publicId, rotated.secret, '').signed(hook), + isTrue, + ); + }, + ); + + test('when the blog answers 500 then send test reports it and the ' + 'delivery is listed', () async { + h.blog.status = 500; + + final result = await endpoints.publication.sendTest( + owner.endpointSession, + pub.publicId, + ); + final deliveries = await endpoints.publication.deliveries( + owner.endpointSession, + pub.publicId, + ); + + expect(result.ok, isFalse); + expect(result.message, 'HTTP 500'); + expect(deliveries.first.lastStatus, 500); + }); + }); +} diff --git a/wonky_server/test/integration/platform/publications/submission_flow_test.dart b/wonky_server/test/integration/platform/publications/submission_flow_test.dart new file mode 100644 index 00000000..896743cd --- /dev/null +++ b/wonky_server/test/integration/platform/publications/submission_flow_test.dart @@ -0,0 +1,326 @@ +@Tags(['integration']) +library; + +import 'package:serverpod/serverpod.dart'; +import 'package:test/test.dart'; +import 'package:wonky_server/src/platform/common/models.dart'; +import 'package:wonky_server/src/platform/publications/publication_webhooks.dart'; +import 'package:wonky_server/src/write/content/write_content.dart'; +import 'package:wonky_server/src/write/ot/document_store.dart'; + +import '../../../support/publications/publication_harness.dart'; +import '../../../support/test_drive.dart'; +import '../../../support/test_users.dart'; +import '../../../support/wonky_serverpod.dart'; + +void main() { + withWonkyServerpod('Given a publication with a moderator', ( + sessionBuilder, + endpoints, + ) { + final h = PublicationHarness(); + late TestUser owner; + late TestUser mod; + late TestUser anna; + late TestPublication pub; + + setUp(() async { + h.install(); + owner = await TestUsers.create(sessionBuilder, name: 'Owner'); + mod = await TestUsers.create(sessionBuilder, name: 'Mod'); + anna = await TestUsers.create(sessionBuilder, name: 'Anna'); + pub = await h.create(endpoints, owner, moderators: [mod]); + }); + tearDown(h.uninstall); + + test('when a contributor resolves the link then consent is needed and ' + 'the unverified card shows the webhook host', () async { + final card = await endpoints.publication.resolve( + anna.endpointSession, + pub.publicId, + ); + + expect(card.name, 'Serverpod blog'); + expect(card.consentNeeded, isTrue); + expect(card.verified, isFalse); + expect(card.shownHost, 'blog.example.com'); + expect(card.openSubmissions, isEmpty); + }); + + test('when starting without agreeing then it is refused', () async { + await expectLater( + endpoints.publication.startSubmission( + anna.endpointSession, + pub.publicId, + null, + false, + ), + throwsA(isA()), + ); + }); + + test('when starting a story then a document in the contributor\'s drive ' + 'has a draft submission and the card lists it', () async { + final uuid = await h.start(endpoints, anna, pub, ref: 'cfp-2026'); + + final item = await endpoints.drive.get(anna.endpointSession, uuid); + final view = await endpoints.submission.get(anna.endpointSession, uuid); + final card = await endpoints.publication.resolve( + anna.endpointSession, + pub.publicId, + ); + expect(item.role, AccessRole.owner); + expect(view!.status, SubmissionStatus.draft); + expect(view.consentNeeded, isFalse); + expect(card.consentNeeded, isFalse); + expect(card.openSubmissions.single.itemUuid, uuid); + expect(h.blog.received, isEmpty); + }); + + group('and a submitted story', () { + late UuidValue doc; + late SubmissionView submitted; + + setUp(() async { + final tpl = await TestDrive.document( + endpoints, + owner, + name: 'Template', + markdown: '# Faster CI\n\nWe made it **three** times faster.', + ); + await endpoints.publication.update( + owner.endpointSession, + pub.publicId, + PublicationHarness.input(templateItemUuid: tpl.uuid), + ); + doc = await h.start(endpoints, anna, pub, ref: 'cfp-2026'); + submitted = await endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(title: 'Faster CI'), + false, + ); + }); + + test('then the blog received one signed submission.submitted with the ' + 'Markdown and fields', () { + final hook = h.blog.ofType('submission.submitted').single; + final json = hook.json; + final submission = json['submission']! as Map; + + expect(pub.signed(hook), isTrue); + expect(hook.headers['webhook-id'], startsWith('msg_')); + expect(json['publicationId'], pub.publicId); + expect(submission['ref'], 'cfp-2026'); + expect(submission['status'], 'inReview'); + expect(submission['documentUrl'], endsWith('/write/d/${doc.uuid}')); + expect(json['sequence'], 1); + expect((json['fields']! as Map)['title'], 'Faster CI'); + expect(json['markdown'], contains('three')); + expect((json['submittedBy']! as Map)['name'], 'Anna'); + }); + + test('then the submission is in review with a named version', () { + expect(submitted.status, SubmissionStatus.inReview); + expect(submitted.delivery, isNull); + expect(submitted.revisions.single.versionId, isNotNull); + }); + + test('then the moderator has comment access', () async { + final item = await endpoints.drive.get(mod.endpointSession, doc); + final sharing = await endpoints.sharing.getSharing( + anna.endpointSession, + doc, + ); + + expect(item.role, AccessRole.commenter); + expect( + sharing.permissions + .singleWhere((p) => p.user?.id == mod.id) + .viaPublication, + 'Serverpod blog', + ); + }); + + test( + 'when submitting again without changes then the sequence grows', + () async { + await endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(title: 'Faster CI'), + false, + ); + + final hooks = h.blog.ofType('submission.submitted'); + expect([for (final hk in hooks) hk.json['sequence']], [1, 2]); + }, + ); + + test('when withdrawing then the blog is told and the moderator loses ' + 'access', () async { + final view = await endpoints.submission.withdraw( + anna.endpointSession, + doc, + ); + await h.deliverScheduled(sessionBuilder); + + expect(view.status, SubmissionStatus.withdrawn); + expect( + h.blog.ofType('submission.withdrawn').single.json['reason'], + 'author', + ); + await expectLater( + endpoints.drive.get(mod.endpointSession, doc), + throwsA(isA()), + ); + }); + + test( + 'when the document is trashed then the submission is withdrawn', + () async { + await endpoints.drive.trash(anna.endpointSession, [doc]); + await h.deliverScheduled(sessionBuilder); + + expect( + h.blog.ofType('submission.withdrawn').single.json['reason'], + 'trashed', + ); + }, + ); + + test('when a commenter tries to submit then it is refused', () async { + await expectLater( + endpoints.submission.submit( + mod.endpointSession, + doc, + PublicationHarness.values(), + false, + ), + throwsA(isA()), + ); + }); + + test('when disconnecting while in review then it is refused', () async { + await expectLater( + endpoints.submission.disconnect(anna.endpointSession, doc), + throwsA(isA()), + ); + }); + }); + + group('and a blog that is down', () { + late UuidValue doc; + + setUp(() async { + doc = await h.start(endpoints, anna, pub); + h.blog.status = 503; + }); + + test('when submitting then the delivery is pending', () async { + final view = await endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(), + false, + ); + + expect(view.status, SubmissionStatus.inReview); + expect(view.delivery, SubmissionDeliveryState.pending); + }); + + test('when every retry fails then the status goes back to draft and ' + 'the submitter is notified', () async { + await endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(), + false, + ); + final session = sessionBuilder.build(); + final d = await PublicationDelivery.db.findFirstRow( + session, + where: (t) => t.type.equals('submission.submitted'), + orderBy: (t) => t.createdAt.desc(), + ); + for (var i = 0; i < PublicationWebhooks.retryDelays.length; i++) { + await PublicationDelivery.db.updateRow( + session, + (await PublicationDelivery.db.findById( + session, + d!.id!, + ))!.copyWith(leaseUntil: null), + columns: (t) => [t.leaseUntil], + ); + await PublicationWebhooks.attempt(session, d.id!); + } + + final view = await endpoints.submission.get(anna.endpointSession, doc); + final notes = await UserNotification.db.find( + session, + where: (t) => + t.userId.equals(anna.id) & + t.kind.equals(NotificationKind.submission), + ); + expect(view!.status, SubmissionStatus.draft); + expect(view.delivery, SubmissionDeliveryState.failed); + expect(notes, hasLength(1)); + }); + + test('when the blog comes back then the sweep delivers it', () async { + await endpoints.submission.submit( + anna.endpointSession, + doc, + PublicationHarness.values(), + false, + ); + h.blog.status = 200; + final session = sessionBuilder.build(); + await PublicationDelivery.db.updateWhere( + session, + columnValues: (t) => [t.nextAttemptAt(DateTime.utc(2000))], + where: (t) => t.deliveredAt.equals(null), + ); + + await PublicationWebhooks.sweep(session); + + final view = await endpoints.submission.get(anna.endpointSession, doc); + expect(view!.delivery, isNull); + expect(view.status, SubmissionStatus.inReview); + }); + }); + + group('and a template document', () { + test( + 'when starting a story then it starts with the template text', + () async { + final tpl = await TestDrive.document( + endpoints, + owner, + name: 'Template', + markdown: '# Your title\n\nWrite here.', + ); + await endpoints.publication.update( + owner.endpointSession, + pub.publicId, + PublicationHarness.input(templateItemUuid: tpl.uuid), + ); + + final doc = await h.start(endpoints, anna, pub); + + final session = sessionBuilder.build(); + final item = await DriveItem.db.findFirstRow( + session, + where: (t) => t.uuid.equals(doc), + ); + final content = await DocumentStore.head( + session, + (await DocumentStore.byItem(session, item!.id!))!, + ); + expect(WriteContent.toMarkdown(content), contains('Write here.')); + expect(item.ownerId, anna.id); + }, + ); + }); + }); +} diff --git a/wonky_server/test/integration/server_test.dart b/wonky_server/test/integration/server_test.dart index e49d4cf0..c2bf6523 100644 --- a/wonky_server/test/integration/server_test.dart +++ b/wonky_server/test/integration/server_test.dart @@ -34,7 +34,7 @@ void main() { } test('when listing the recurring jobs then the maintenance, RevLog, ' - 'script, storage and board jobs are there', () { + 'script, storage, board and publication jobs are there', () { expect( jobs, containsAll([ @@ -44,6 +44,7 @@ void main() { 'wonky.scriptsTick', 'wonky.storageReconcile', 'wonky.boardSweep', + 'wonky.publicationSweep', ]), ); }); diff --git a/wonky_server/test/integration/test_tools/serverpod_test_tools.dart b/wonky_server/test/integration/test_tools/serverpod_test_tools.dart index a15c21fd..86e90d17 100644 --- a/wonky_server/test/integration/test_tools/serverpod_test_tools.dart +++ b/wonky_server/test/integration/test_tools/serverpod_test_tools.dart @@ -36,6 +36,8 @@ import 'package:wonky_server/src/generated/future_calls_generated_models/file_pr as _ikj8bo9l; import 'package:wonky_server/src/generated/future_calls_generated_models/notification_email_future_call_send_model.dart' as _iuw2rc8h; +import 'package:wonky_server/src/generated/future_calls_generated_models/publications_future_call_deliver_model.dart' + as _in0nsjwu; import 'package:wonky_server/src/generated/future_calls_generated_models/storage_future_call_refresh_item_size_model.dart' as _i5g4dkd6; import 'package:wonky_server/src/generated/platform/activity/activity_dashboard.dart' @@ -170,6 +172,24 @@ import 'package:wonky_server/src/generated/platform/presence/presence_event.dart as _in8u6dfh; import 'package:wonky_server/src/generated/platform/presence/presence_update.dart' as _ipd65of1; +import 'package:wonky_server/src/generated/platform/publications/models/publication_card.dart' + as _iywwc4sf; +import 'package:wonky_server/src/generated/platform/publications/models/publication_check_result.dart' + as _i1amkxf0; +import 'package:wonky_server/src/generated/platform/publications/models/publication_delivery_view.dart' + as _idovycpn; +import 'package:wonky_server/src/generated/platform/publications/models/publication_input.dart' + as _iy7hmxv3; +import 'package:wonky_server/src/generated/platform/publications/models/publication_secret.dart' + as _i1thvjiu; +import 'package:wonky_server/src/generated/platform/publications/models/publication_settings.dart' + as _i9ilkmgj; +import 'package:wonky_server/src/generated/platform/publications/models/submission_started.dart' + as _ighe7owc; +import 'package:wonky_server/src/generated/platform/publications/models/submission_values.dart' + as _iwukrrmj; +import 'package:wonky_server/src/generated/platform/publications/models/submission_view.dart' + as _ij8gnfyr; import 'package:wonky_server/src/generated/platform/revlog/messages/rev_client_message.dart' as _iv4mnr49; import 'package:wonky_server/src/generated/platform/revlog/messages/rev_server_message.dart' @@ -463,6 +483,10 @@ class TestEndpoints { late final _PresenceEndpoint presence; + late final _PublicationEndpoint publication; + + late final _SubmissionEndpoint submission; + late final _SharingEndpoint sharing; late final _AccessTokenEndpoint accessToken; @@ -573,6 +597,14 @@ class _InternalTestEndpoints extends TestEndpoints endpoints, serializationManager, ); + publication = _PublicationEndpoint( + endpoints, + serializationManager, + ); + submission = _SubmissionEndpoint( + endpoints, + serializationManager, + ); sharing = _SharingEndpoint( endpoints, serializationManager, @@ -679,6 +711,8 @@ class _FutureCalls { late final notificationEmail = _NotificationEmailFutureCall(); + late final publications = _PublicationsFutureCall(); + late final acl = _AclFutureCall(); late final storage = _StorageFutureCall(); @@ -5897,6 +5931,609 @@ class _PresenceEndpoint { } } +class _PublicationEndpoint { + _PublicationEndpoint( + this._endpointDispatch, + this._serializationManager, + ); + + final _is.EndpointDispatch _endpointDispatch; + + final _is.SerializationManager _serializationManager; + + _ida.Future<_iywwc4sf.PublicationCard> resolve( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'resolve', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'resolve', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_iywwc4sf.PublicationCard>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_ighe7owc.SubmissionStarted> startSubmission( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + String? ref, + bool agreed, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'startSubmission', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'startSubmission', + parameters: _ist.testObjectToJson({ + 'publicId': publicId, + 'ref': ref, + 'agreed': agreed, + }), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_ighe7owc.SubmissionStarted>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future> list( + _ist.TestSessionBuilder sessionBuilder, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'list', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'list', + parameters: _ist.testObjectToJson({}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i1thvjiu.PublicationSecret> create( + _ist.TestSessionBuilder sessionBuilder, + _iy7hmxv3.PublicationInput input, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'create', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'create', + parameters: _ist.testObjectToJson({'input': input}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i1thvjiu.PublicationSecret>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i9ilkmgj.PublicationSettings> update( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + _iy7hmxv3.PublicationInput input, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'update', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'update', + parameters: _ist.testObjectToJson({ + 'publicId': publicId, + 'input': input, + }), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i9ilkmgj.PublicationSettings>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future delete( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'delete', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'delete', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i1amkxf0.PublicationCheckResult> verify( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'verify', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'verify', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i1amkxf0.PublicationCheckResult>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i1thvjiu.PublicationSecret> rotateSecret( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'rotateSecret', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'rotateSecret', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i1thvjiu.PublicationSecret>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i1thvjiu.PublicationSecret> createApiKey( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'createApiKey', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'createApiKey', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i1thvjiu.PublicationSecret>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i9ilkmgj.PublicationSettings> setModerators( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + List emails, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'setModerators', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'setModerators', + parameters: _ist.testObjectToJson({ + 'publicId': publicId, + 'emails': emails, + }), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i9ilkmgj.PublicationSettings>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future> deliveries( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'deliveries', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'deliveries', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_idovycpn.PublicationDeliveryView> resend( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + String webhookId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'resend', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'resend', + parameters: _ist.testObjectToJson({ + 'publicId': publicId, + 'webhookId': webhookId, + }), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_idovycpn.PublicationDeliveryView>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_i1amkxf0.PublicationCheckResult> sendTest( + _ist.TestSessionBuilder sessionBuilder, + String publicId, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'publication', + method: 'sendTest', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'publication', + methodName: 'sendTest', + parameters: _ist.testObjectToJson({'publicId': publicId}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_i1amkxf0.PublicationCheckResult>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } +} + +class _SubmissionEndpoint { + _SubmissionEndpoint( + this._endpointDispatch, + this._serializationManager, + ); + + final _is.EndpointDispatch _endpointDispatch; + + final _is.SerializationManager _serializationManager; + + _ida.Future<_ij8gnfyr.SubmissionView?> get( + _ist.TestSessionBuilder sessionBuilder, + _is.UuidValue itemUuid, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'submission', + method: 'get', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'submission', + methodName: 'get', + parameters: _ist.testObjectToJson({'itemUuid': itemUuid}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_ij8gnfyr.SubmissionView?>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_ij8gnfyr.SubmissionView> submit( + _ist.TestSessionBuilder sessionBuilder, + _is.UuidValue itemUuid, + _iwukrrmj.SubmissionValues values, + bool agreed, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'submission', + method: 'submit', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'submission', + methodName: 'submit', + parameters: _ist.testObjectToJson({ + 'itemUuid': itemUuid, + 'values': values, + 'agreed': agreed, + }), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_ij8gnfyr.SubmissionView>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_ij8gnfyr.SubmissionView> withdraw( + _ist.TestSessionBuilder sessionBuilder, + _is.UuidValue itemUuid, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'submission', + method: 'withdraw', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'submission', + methodName: 'withdraw', + parameters: _ist.testObjectToJson({'itemUuid': itemUuid}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_ij8gnfyr.SubmissionView>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future disconnect( + _ist.TestSessionBuilder sessionBuilder, + _is.UuidValue itemUuid, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'submission', + method: 'disconnect', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'submission', + methodName: 'disconnect', + parameters: _ist.testObjectToJson({'itemUuid': itemUuid}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } + + _ida.Future<_ij8gnfyr.SubmissionView?> reconnect( + _ist.TestSessionBuilder sessionBuilder, + _is.UuidValue itemUuid, + ) async { + return _ist.callAwaitableFunctionAndHandleExceptions(() async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild( + endpoint: 'submission', + method: 'reconnect', + ); + try { + var _localCallContext = await _endpointDispatch.getMethodCallContext( + createSessionCallback: (_) => _localUniqueSession, + endpointPath: 'submission', + methodName: 'reconnect', + parameters: _ist.testObjectToJson({'itemUuid': itemUuid}), + serializationManager: _serializationManager, + ); + var _localReturnValue = + await (_localCallContext.method.call( + _localUniqueSession, + _localCallContext.arguments, + ) + as _ida.Future<_ij8gnfyr.SubmissionView?>); + return _localReturnValue; + } finally { + await _localUniqueSession.close(); + } + }); + } +} + class _SharingEndpoint { _SharingEndpoint( this._endpointDispatch, @@ -10875,6 +11512,40 @@ class _NotificationEmailFutureCall { } } +class _PublicationsFutureCall { + Future deliver( + _ist.TestSessionBuilder sessionBuilder, + int deliveryId, + ) async { + var object = _in0nsjwu.PublicationsFutureCallDeliverModel( + deliveryId: deliveryId, + ); + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild(); + try { + await _iwslocjr.PublicationsDeliverFutureCall().invoke( + _localUniqueSession, + object, + ); + } finally { + await _localUniqueSession.close(); + } + } + + Future sweep(_ist.TestSessionBuilder sessionBuilder) async { + var _localUniqueSession = + (sessionBuilder as _ist.InternalTestSessionBuilder).internalBuild(); + try { + await _iwslocjr.PublicationsSweepFutureCall().invoke( + _localUniqueSession, + null, + ); + } finally { + await _localUniqueSession.close(); + } + } +} + class _AclFutureCall { Future fanOut( _ist.TestSessionBuilder sessionBuilder, diff --git a/wonky_server/test/support/publications/publication_harness.dart b/wonky_server/test/support/publications/publication_harness.dart new file mode 100644 index 00000000..5c791570 --- /dev/null +++ b/wonky_server/test/support/publications/publication_harness.dart @@ -0,0 +1,176 @@ +import 'dart:convert'; + +import 'package:serverpod/serverpod.dart' show UuidValue; + +import 'package:wonky_server/src/platform/common/models.dart'; +import 'package:wonky_server/src/platform/publications/publication_common.dart'; +import 'package:wonky_server/src/platform/publications/publication_http.dart'; +import 'package:wonky_server/src/platform/publications/publication_keys.dart'; +import 'package:wonky_server/src/platform/publications/publication_rules.dart'; +import 'package:wonky_server/src/platform/publications/publication_webhooks.dart'; + +import '../test_users.dart'; +import '../wonky_serverpod.dart'; + +/// One webhook the fake blog received. +class ReceivedWebhook { + ReceivedWebhook(this.url, this.headers, this.body); + + final String url; + final Map headers; + final String body; + + Map get json => + (jsonDecode(body) as Map).cast(); + + String get type => json['type'] as String; +} + +/// The blog's server: records webhooks and answers with [status]; answers +/// GETs from [pages] (404 otherwise). Never touches the network. +class FakeBlog implements PublicationHttp { + final received = []; + final pages = {}; + int status = 200; + + List ofType(String type) => [ + for (final r in received) + if (r.type == type) r, + ]; + + @override + Future post( + String url, { + required Map headers, + required String body, + }) async { + received.add(ReceivedWebhook(url, headers, body)); + return PublicationHttpResult(status); + } + + @override + Future get(String url) async { + final page = pages[url]; + return page == null + ? const PublicationHttpResult(404) + : PublicationHttpResult(200, body: page); + } +} + +/// Installs a [FakeBlog] and records scheduled deliveries instead of +/// running future calls (specs/15 §6). +class PublicationHarness { + final blog = FakeBlog(); + final scheduled = []; + + void install() { + blog + ..received.clear() + ..pages.clear() + ..status = 200; + scheduled.clear(); + PublicationHttp.override = blog; + PublicationWebhooks.scheduler = (session, id) async => scheduled.add(id); + Publications.startLimiter.reset(); + Publications.submitLimiter.reset(); + Publications.apiLimiter.reset(); + } + + void uninstall() { + PublicationHttp.override = null; + PublicationWebhooks.scheduler = (session, id) async {}; + } + + /// Sends every scheduled delivery now. + Future deliverScheduled(TestSessionBuilder sessionBuilder) async { + final ids = [...scheduled]; + scheduled.clear(); + for (final id in ids) { + await PublicationWebhooks.attempt(sessionBuilder.build(), id); + } + } + + static PublicationInput input({ + String name = 'Serverpod blog', + String siteUrl = 'https://blog.example.com', + String webhookUrl = 'https://blog.example.com/api/wonky', + String? termsUrl, + UuidValue? templateItemUuid, + PublicationFields? fields, + bool enabled = true, + }) => PublicationInput( + name: name, + siteUrl: siteUrl, + webhookUrl: webhookUrl, + termsUrl: termsUrl, + templateItemUuid: templateItemUuid, + fields: fields ?? PublicationRules.defaultFields(), + enabled: enabled, + ); + + /// A publication of [owner] with an API key and [moderators]. + Future create( + TestEndpoints endpoints, + TestUser owner, { + List moderators = const [], + PublicationInput? input, + }) async { + final created = await endpoints.publication.create( + owner.endpointSession, + input ?? PublicationHarness.input(), + ); + final key = await endpoints.publication.createApiKey( + owner.endpointSession, + created.settings.publicId, + ); + if (moderators.isNotEmpty) { + await endpoints.publication.setModerators( + owner.endpointSession, + created.settings.publicId, + [for (final m in moderators) m.email], + ); + } + blog.received.clear(); + scheduled.clear(); + return TestPublication( + created.settings.publicId, + created.secret, + key.secret, + ); + } + + /// A story of [author] for [p], started and agreed to. + Future start( + TestEndpoints endpoints, + TestUser author, + TestPublication p, { + String? ref, + }) async => (await endpoints.publication.startSubmission( + author.endpointSession, + p.publicId, + ref, + true, + )).itemUuid; + + static SubmissionValues values({String title = 'My story'}) => + SubmissionValues(title: title, tags: ['dart']); +} + +class TestPublication { + TestPublication(this.publicId, this.signingSecret, this.apiKey); + + final String publicId; + final String signingSecret; + final String apiKey; + + /// Whether [hook] carries a valid signature of this publication. + bool signed(ReceivedWebhook hook) { + final expected = PublicationKeys.sign( + secret: signingSecret, + webhookId: hook.headers['webhook-id']!, + timestamp: int.parse(hook.headers['webhook-timestamp']!), + body: hook.body, + ); + return hook.headers['webhook-signature']!.split(' ').contains(expected); + } +} diff --git a/wonky_server/test/unit/publications/publication_keys_test.dart b/wonky_server/test/unit/publications/publication_keys_test.dart new file mode 100644 index 00000000..1ff6cd94 --- /dev/null +++ b/wonky_server/test/unit/publications/publication_keys_test.dart @@ -0,0 +1,63 @@ +import 'package:test/test.dart'; +import 'package:wonky_server/src/platform/publications/publication_keys.dart'; + +void main() { + group('Given the signing test vector of the blog integration guide', () { + const secret = 'whsec_MfKQ9r8GKYqrTwjUPD8ILPZIo2LaLaSw'; + const id = 'msg_2KWPBgLlAfxdpx2AI54pPJ85f4W'; + const timestamp = 1674087231; + const body = + '{"type":"publication.ping","createdAt":"2023-01-19T00:13:51Z",' + '"publicationId":"pub_7Hk2xQ9mR4tLwP0aZc3VbN"}'; + + test('when signing it then the signature matches the guide', () { + expect( + PublicationKeys.sign( + secret: secret, + webhookId: id, + timestamp: timestamp, + body: body, + ), + 'v1,4+meITVYE+3sv8v+3Jl0/CXDGdczBRF7SOHoZxKwobQ=', + ); + }); + + test('when signing with two secrets then the header has both, space ' + 'separated', () { + final header = PublicationKeys.signatureHeader( + secrets: [secret, PublicationKeys.newSigningSecret()], + webhookId: id, + timestamp: timestamp, + body: body, + ); + + expect(header.split(' '), hasLength(2)); + expect( + header.split(' ').first, + 'v1,4+meITVYE+3sv8v+3Jl0/CXDGdczBRF7SOHoZxKwobQ=', + ); + }); + }); + + group('Given new ids and keys', () { + test('when creating a public id then it matches the link pattern', () { + expect( + PublicationKeys.publicIdPattern.hasMatch(PublicationKeys.newPublicId()), + isTrue, + ); + }); + + test('when creating an API key then it matches the key pattern and its ' + 'hash is stable', () { + final key = PublicationKeys.newApiKey(); + + expect(PublicationKeys.apiKeyPattern.hasMatch(key), isTrue); + expect(PublicationKeys.hashApiKey(key), PublicationKeys.hashApiKey(key)); + expect(PublicationKeys.hashApiKey(key), hasLength(64)); + }); + + test('when creating a signing secret then it has the whsec_ prefix', () { + expect(PublicationKeys.newSigningSecret(), startsWith('whsec_')); + }); + }); +} diff --git a/wonky_server/test/unit/publications/publication_rules_test.dart b/wonky_server/test/unit/publications/publication_rules_test.dart new file mode 100644 index 00000000..4551e038 --- /dev/null +++ b/wonky_server/test/unit/publications/publication_rules_test.dart @@ -0,0 +1,117 @@ +import 'package:test/test.dart'; +import 'package:wonky_server/src/platform/common/models.dart'; +import 'package:wonky_server/src/platform/publications/publication_rules.dart'; + +void main() { + group('Given the status transitions of the blog', () { + const s = SubmissionStatus.values; + final allowed = <(SubmissionStatus, SubmissionStatus)>{ + for (final from in [ + SubmissionStatus.inReview, + SubmissionStatus.changesRequested, + ]) + for (final to in [ + SubmissionStatus.inReview, + SubmissionStatus.changesRequested, + SubmissionStatus.declined, + SubmissionStatus.published, + ]) + (from, to), + (SubmissionStatus.published, SubmissionStatus.published), + }; + for (final from in s) { + for (final to in s) { + final ok = allowed.contains((from, to)); + test('when moving from ${from.name} to ${to.name} then it is ' + '${ok ? 'allowed' : 'refused'}', () { + expect(PublicationRules.blogMayMove(from, to), ok); + }); + } + } + }); + + group('Given URLs of a publication', () { + final cases = <(String, bool)>[ + ('https://blog.example.com', true), + ('https://blog.example.com/', true), + ('http://blog.example.com', false), + ('https://blog.example.com:8443', false), + ('https://user:pw@blog.example.com', false), + ('https://blog.example.com/path', false), + ('ftp://blog.example.com', false), + ]; + for (final (url, ok) in cases) { + test('when "$url" is the site URL then it is ' + '${ok ? 'accepted' : 'refused'}', () { + expect( + () => PublicationRules.httpsUrl(url, 'site URL', originOnly: true), + ok ? returnsNormally : throwsA(isA()), + ); + }); + } + + test('when a webhook URL has a path then it is accepted', () { + expect( + PublicationRules.httpsUrl( + 'https://blog.example.com/api/wonky?x=1', + 'webhook URL', + ).path, + '/api/wonky', + ); + }); + }); + + group('Given the fields of a publication with required tags from a list', () { + final fields = PublicationRules.defaultFields().copyWith( + tags: PublicationFieldMode.required, + allowedTags: ['Dart', 'Flutter'], + summary: PublicationFieldMode.off, + ); + + test('when the values have duplicate tags in other cases then they are ' + 'kept once and the summary is dropped', () { + final v = PublicationRules.values( + SubmissionValues( + title: ' Title ', + summary: 'dropped', + tags: ['dart', 'Dart', ' flutter '], + ), + fields, + ); + + expect(v.title, 'Title'); + expect(v.summary, isNull); + expect(v.tags, ['dart', 'flutter']); + }); + + test('when a tag is not in the list then it is refused', () { + expect( + () => PublicationRules.values( + SubmissionValues(title: 'T', tags: ['go']), + fields, + ), + throwsA(isA()), + ); + }); + + test('when there are no tags then it is refused', () { + expect( + () => PublicationRules.values( + SubmissionValues(title: 'T', tags: []), + fields, + ), + throwsA(isA()), + ); + }); + + test('when the title is empty then it is refused', () { + expect( + () => PublicationRules.values( + SubmissionValues(title: ' ', tags: ['Dart']), + fields, + ), + throwsA(isA()), + ); + }); + }); +} diff --git a/wonky_write/lib/config/write_app_config.dart b/wonky_write/lib/config/write_app_config.dart index fa1dacf0..2cea0ce7 100644 --- a/wonky_write/lib/config/write_app_config.dart +++ b/wonky_write/lib/config/write_app_config.dart @@ -10,6 +10,7 @@ import '../features/ai/ai_commands.dart'; import '../commands/theme_commands.dart'; import '../features/document/write_collab_commands.dart'; import '../features/history/write_version_renderer.dart'; +import '../features/publish/submission_commands.dart'; import '../features/import/import_route.dart'; import '../features/import/import_service.dart'; import '../features/print/print_preview_screen.dart'; @@ -124,6 +125,7 @@ class WriteAppConfig extends WonkyAppConfig { ...writeCollabCommands(services), ...writeAiCommands(services), ...writeSettingsCommands(services), + ...writeSubmissionCommands(services), ]; /// Installs the AI assistant (suite 10) after sign-in. diff --git a/wonky_write/lib/config/write_menus.dart b/wonky_write/lib/config/write_menus.dart index ec7ecc87..ce49dbab 100644 --- a/wonky_write/lib/config/write_menus.dart +++ b/wonky_write/lib/config/write_menus.dart @@ -31,6 +31,13 @@ MenuRoot writeMenus(ShellMenus shell, {WriteLocalizations? l10n}) { .insertAfter('shell.file.import', [ _c('write.insert.fromFile', label: l.cmdInsertFromFile), ]) + // (M14) A story for a publication (specs/18 §4.4); disabled for + // documents without a submission. + .insertAfter(ShellMenuIds.fileShare, [ + _c('write.submission.submit', label: l.cmdSubmissionSubmit), + _c('write.submission.showStatus', label: l.cmdSubmissionStatus), + _c('write.submission.withdraw', label: l.cmdSubmissionWithdraw), + ]) .replace('shell.file.details', [ _c('write.doc.properties', label: l.cmdDocProperties), ]) diff --git a/wonky_write/lib/features/publish/submission_commands.dart b/wonky_write/lib/features/publish/submission_commands.dart new file mode 100644 index 00000000..b5f32ad2 --- /dev/null +++ b/wonky_write/lib/features/publish/submission_commands.dart @@ -0,0 +1,120 @@ +import 'package:shad/shad.dart' show LucideIcons; +import 'package:wonky_app/wonky_app.dart'; +import 'package:wonky_client/wonky_client.dart' + show SubmissionDeliveryState, SubmissionStatus; +import 'package:wonky_core/wonky_core.dart'; + +import '../../commands/write_command.dart'; +import '../../l10n/write_l10n.dart'; +import '../screen/write_document_controller.dart'; +import 'submit_dialog.dart'; + +/// The commands of a document's submission to a publication (specs/18 +/// §4.4). Submitting and withdrawing reach the blog and are not undoable; +/// disconnecting is. +List> writeSubmissionCommands(ShellServices services) { + String? reason(WriteLocalizations l, WriteDocumentController doc) { + final c = doc.submission; + final v = c.view; + if (v == null) return l.submitReasonNone; + if (!c.online) return l.submitReasonOffline; + if (!v.accepting) return l.submitReasonClosed(v.publicationName); + if (v.status == SubmissionStatus.declined) { + return l.submitReasonDeclined(v.publicationName); + } + if (!c.canSubmit) return l.submitReasonNoChanges; + return null; + } + + return [ + WriteCommand( + 'write.submission.submit', + label: (l) => l.cmdSubmissionSubmit, + icon: LucideIcons.send, + categoryName: (l) => l.categoryFile, + requiredRole: Role.editor, + enabled: (doc, _) => doc.submission.canSubmit, + reason: (l, doc, _) => reason(l, doc), + run: (ctx, doc, _) async { + final c = ctx.dialogContext; + if (c == null || !c.mounted) return const CommandResult.cancelled(); + final view = await showSubmitDialog(c, services, doc); + if (view == null) return const CommandResult.cancelled(); + final l = writeL10nOf(services); + services.toasts.show( + view.delivery == SubmissionDeliveryState.pending + ? l.submitPending(view.publicationName) + : l.submitDone(view.publicationName), + ); + return CommandResult.ok({'status': view.status.name}); + }, + ), + WriteCommand( + 'write.submission.withdraw', + label: (l) => l.cmdSubmissionWithdraw, + icon: LucideIcons.undo2, + categoryName: (l) => l.categoryFile, + requiredRole: Role.editor, + enabled: (doc, _) => doc.submission.canWithdraw, + reason: (l, doc, _) => doc.submission.online + ? l.submitReasonNotInReview + : l.submitReasonOffline, + run: (ctx, doc, _) async { + final v = doc.submission.view; + final c = ctx.dialogContext; + if (v == null) return const CommandResult.cancelled(); + final l = writeL10nOf(services); + if (c != null && c.mounted && !ctx.source.isAgent) { + final ok = await confirmDialog( + c, + title: l.withdrawTitle(v.publicationName), + description: l.withdrawBody(v.publicationName), + confirmLabel: l.withdrawButton, + destructive: true, + ); + if (!ok) return const CommandResult.cancelled(); + } + await doc.submission.withdraw(); + return const CommandResult.ok(); + }, + ), + WriteCommand( + 'write.submission.disconnect', + label: (l) => l.cmdSubmissionDisconnect, + icon: LucideIcons.unlink, + categoryName: (l) => l.categoryFile, + requiredRole: Role.editor, + isUndoable: true, + enabled: (doc, _) => doc.submission.canDisconnect, + reason: (l, doc, _) => doc.submission.online + ? l.submitReasonWithdrawFirst + : l.submitReasonOffline, + undoLabelOf: (l, _) => l.cmdSubmissionDisconnect, + run: (ctx, doc, _) async { + await doc.submission.disconnect(); + ctx.record(SubmissionUndoEntry(itemUuid: doc.itemUuid.uuid)); + return const CommandResult.ok(); + }, + ), + WriteCommand( + 'write.submission.showStatus', + label: (l) => l.cmdSubmissionStatus, + icon: LucideIcons.newspaper, + categoryName: (l) => l.categoryFile, + enabled: (doc, _) => doc.submission.hasSubmission, + reason: (l, _, _) => l.submitReasonNone, + run: (ctx, doc, _) async { + final v = doc.submission.view; + if (v == null) return const CommandResult.cancelled(); + // The popover opens from the title row; agents get the status. + doc.submission.requestPopover(); + return CommandResult.ok({ + 'publication': v.publicationName, + 'status': v.status.name, + 'publicUrl': v.publicUrl, + 'lastMessage': v.lastMessage, + }); + }, + ), + ]; +} diff --git a/wonky_write/lib/features/publish/submission_controller.dart b/wonky_write/lib/features/publish/submission_controller.dart new file mode 100644 index 00000000..9ad37bb3 --- /dev/null +++ b/wonky_write/lib/features/publish/submission_controller.dart @@ -0,0 +1,156 @@ +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:wonky_app/wonky_app.dart'; +import 'package:wonky_client/wonky_client.dart'; + +/// The document's submission to a publication (specs/18 §4): loaded once +/// the document is open and again whenever the item changes (the server +/// signals submission changes as item updates), so the title row's chip +/// and *Submit* button follow the blog's decisions live. +class SubmissionController extends ChangeNotifier { + SubmissionController({ + required this.services, + required this.itemUuid, + required this.revision, + }); + + final ShellServices services; + final UuidValue itemUuid; + + /// The document's current revision (to tell whether it changed since the + /// last submit). + final int Function() revision; + + SubmissionView? _view; + bool _started = false; + bool _busy = false; + bool _disposed = false; + StreamSubscription? _changes; + + /// The submission, or null when the document has none. + SubmissionView? get view => _view; + bool get hasSubmission => _view != null; + + /// A submit, withdraw or disconnect is running. + bool get busy => _busy; + + bool get online => services.connectivity.online; + + PublicationRepository? get _repo => services.repositories.hasPublications + ? services.repositories.publications + : null; + + /// Starts loading and following the submission (idempotent). + void start() { + if (_started || _repo == null) return; + _started = true; + _changes = services.driveChanges.listen((c) { + if (c.itemUuid == itemUuid) unawaited(refresh()); + }); + services.connectivity.addListener(_onConnectivity); + unawaited(refresh()); + } + + void _onConnectivity() { + if (online) unawaited(refresh()); + _notify(); + } + + Future refresh() async { + final repo = _repo; + if (repo == null) return; + try { + final v = await repo.submission(itemUuid); + if (_disposed) return; + _view = v; + _notify(); + } catch (_) { + // Offline or no access: keep what is shown. + } + } + + /// Whether the document changed since the last submit. + bool get changedSinceSubmit { + final last = _view?.lastSubmittedRevision; + return last == null || revision() > last; + } + + /// Whether the editor may press *Submit* now (specs/18 §4.1). + bool get canSubmit { + final v = _view; + if (v == null || !online || _busy || !v.accepting) return false; + if (v.status == SubmissionStatus.declined) return false; + if (v.status == SubmissionStatus.draft || + v.status == SubmissionStatus.withdrawn) { + return true; + } + return changedSinceSubmit; + } + + /// Whether the story can be withdrawn. + bool get canWithdraw { + final s = _view?.status; + return online && + !_busy && + (s == SubmissionStatus.inReview || + s == SubmissionStatus.changesRequested); + } + + /// Whether the document can be disconnected (not while in review). + bool get canDisconnect => online && !_busy && hasSubmission && !canWithdraw; + + Future _run( + Future Function(PublicationRepository repo) action, + ) async { + _busy = true; + _notify(); + try { + return await action(_repo!); + } finally { + _busy = false; + _notify(); + } + } + + Future submit( + SubmissionValues values, { + required bool agreed, + }) => _run((repo) async { + final v = await repo.submit(itemUuid, values, agreed: agreed); + _view = v; + return v; + }); + + Future withdraw() => _run((repo) async { + _view = await repo.withdraw(itemUuid); + }); + + Future disconnect() => _run((repo) async { + await repo.disconnect(itemUuid); + _view = null; + }); + + Future reconnect() => _run((repo) async { + _view = await repo.reconnect(itemUuid); + }); + + /// Bumped when *Submission status* is invoked: the title row opens its + /// popover. + final ValueNotifier popoverRequests = ValueNotifier(0); + + void requestPopover() => popoverRequests.value++; + + void _notify() { + if (!_disposed) notifyListeners(); + } + + @override + void dispose() { + _disposed = true; + popoverRequests.dispose(); + unawaited(_changes?.cancel()); + if (_started) services.connectivity.removeListener(_onConnectivity); + super.dispose(); + } +} diff --git a/wonky_write/lib/features/publish/submission_title_actions.dart b/wonky_write/lib/features/publish/submission_title_actions.dart new file mode 100644 index 00000000..11f2cca7 --- /dev/null +++ b/wonky_write/lib/features/publish/submission_title_actions.dart @@ -0,0 +1,336 @@ +import 'dart:async'; + +import 'package:flutter/widgets.dart'; +import 'package:intl/intl.dart' as intl; +import 'package:shad/shad.dart'; +import 'package:wonky_app/wonky_app.dart'; +import 'package:wonky_client/wonky_client.dart'; +import 'package:wonky_core/wonky_core.dart'; +import 'package:wonky_ui/wonky_ui.dart'; + +import '../../l10n/write_l10n.dart'; +import '../screen/write_document_controller.dart'; +import 'submission_controller.dart'; + +/// The status chip and *Submit* button of a document with a submission +/// (specs/18 §4.1), right before *Share*. Nothing shows for documents +/// without one. +class SubmissionTitleActions extends StatefulWidget { + const SubmissionTitleActions({ + super.key, + required this.services, + required this.doc, + }); + + final ShellServices services; + final WriteDocumentController doc; + + @override + State createState() => _SubmissionTitleActionsState(); +} + +class _SubmissionTitleActionsState extends State { + final _popover = ShadPopoverController(); + + SubmissionController get c => widget.doc.submission; + ShellServices get s => widget.services; + + @override + void initState() { + super.initState(); + c.popoverRequests.addListener(_openPopover); + } + + @override + void dispose() { + c.popoverRequests.removeListener(_openPopover); + _popover.dispose(); + super.dispose(); + } + + void _openPopover() { + if (mounted && c.hasSubmission) _popover.show(); + } + + void _invoke(String id) => unawaited( + s.dispatcher + .invoke(id, source: InvocationSource.ui, context: context) + .catchError((Object e) { + s.toasts.error( + s.l10n?.errorGeneric ?? 'Error', + description: errorMessage(e), + ); + return const CommandResult.cancelled(); + }), + ); + + @override + Widget build(BuildContext context) => ListenableBuilder( + listenable: Listenable.merge([c, s.registry, s.activeDocument]), + builder: (context, _) { + final v = c.view; + if (v == null) return const SizedBox.shrink(); + final l = writeL10n(context); + final compact = MediaQuery.sizeOf(context).width < 1200; + final showButton = + widget.doc.role >= Role.editor && + v.status != SubmissionStatus.declined && + v.accepting; + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (v.status != SubmissionStatus.draft) ...[ + _chip(context, v), + const SizedBox(width: 6), + ], + if (showButton) ...[ + _button(context, v, l, compact), + const SizedBox(width: 6), + ], + ], + ); + }, + ); + + Widget _button( + BuildContext context, + SubmissionView v, + WriteLocalizations l, + bool compact, + ) { + final state = s.dispatcher.stateOf('write.submission.submit'); + final label = switch (v.status) { + SubmissionStatus.draft || SubmissionStatus.withdrawn => l.submitButton, + SubmissionStatus.published => l.submitUpdateButton, + _ => l.resubmitButton, + }; + final tip = !state.enabled && state.disabledReason != null + ? state.disabledReason! + : l.submitTooltip(v.publicationName); + return ShadTooltip( + builder: (_) => Text(tip), + child: compact + ? ShadIconButton.secondary( + key: const ValueKey('write.submission.submit'), + width: 32, + height: 32, + iconSize: 16, + semanticLabel: label, + enabled: state.enabled, + icon: c.busy + ? const SizedBox.square(dimension: 14, child: ShadSpinner()) + : const Icon(LucideIcons.send), + onPressed: () => _invoke('write.submission.submit'), + ) + : ShadButton.secondary( + key: const ValueKey('write.submission.submit'), + height: 32, + enabled: state.enabled, + leading: c.busy + ? const SizedBox.square(dimension: 14, child: ShadSpinner()) + : const Icon(LucideIcons.send, size: 14), + onPressed: () => _invoke('write.submission.submit'), + child: Text(label), + ), + ); + } + + Widget _chip(BuildContext context, SubmissionView v) { + final theme = ShadTheme.of(context); + final app = WonkyAppLocalizations.of(context); + final l = writeL10n(context); + final pending = v.delivery == SubmissionDeliveryState.pending; + final (Color fg, Color bg) = switch (v.status) { + SubmissionStatus.changesRequested => ( + theme.colorScheme.foreground, + theme.colorScheme.warning.withValues(alpha: 0.18), + ), + SubmissionStatus.published => ( + theme.colorScheme.foreground, + theme.colorScheme.success.withValues(alpha: 0.18), + ), + _ => (theme.colorScheme.mutedForeground, theme.colorScheme.muted), + }; + final text = pending + ? l.submittingChip + : submissionStatusLabel(app, v.status); + return ShadPopover( + controller: _popover, + anchor: const ShadAnchor( + childAlignment: AlignmentDirectional.bottomEnd, + overlayAlignment: AlignmentDirectional.topEnd, + offset: Offset(0, 6), + ), + popover: (context) => + _StatusPopover(services: s, doc: widget.doc, onClose: _popover.hide), + child: ShadButton.ghost( + key: const ValueKey('write.submission.chip'), + height: 28, + padding: const EdgeInsets.symmetric(horizontal: 10), + backgroundColor: bg, + foregroundColor: fg, + leading: const Icon(LucideIcons.newspaper, size: 14), + onPressed: _popover.toggle, + child: Text(text, style: theme.textTheme.small.copyWith(color: fg)), + ), + ); + } +} + +/// The status popover (specs/18 §4.3). +class _StatusPopover extends StatelessWidget { + const _StatusPopover({ + required this.services, + required this.doc, + required this.onClose, + }); + + final ShellServices services; + final WriteDocumentController doc; + final VoidCallback onClose; + + String _date(DateTime d) => + intl.DateFormat.yMMMd().add_Hm().format(d.toLocal()); + + void _invoke(BuildContext context, String id, [JsonArgs? args]) { + onClose(); + unawaited( + services.dispatcher + .invoke( + id, + args: args?.values ?? const {}, + source: InvocationSource.ui, + context: context, + ) + .catchError((Object e) { + services.toasts.error( + services.l10n?.errorGeneric ?? 'Error', + description: errorMessage(e), + ); + return const CommandResult.cancelled(); + }), + ); + } + + @override + Widget build(BuildContext context) => ListenableBuilder( + listenable: doc.submission, + builder: (context, _) { + final v = doc.submission.view; + if (v == null) return const SizedBox.shrink(); + final l = writeL10n(context); + final app = WonkyAppLocalizations.of(context); + final theme = ShadTheme.of(context); + final c = doc.submission; + final last = v.revisions.isEmpty ? null : v.revisions.last; + return SizedBox( + width: 320, + child: Column( + key: const ValueKey('write.submission.popover'), + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Row( + children: [ + const Icon(LucideIcons.newspaper, size: 16), + const SizedBox(width: 8), + Expanded( + child: Text( + v.publicationName, + style: theme.textTheme.small.copyWith( + fontWeight: FontWeight.w600, + ), + ), + ), + ], + ), + Text( + v.verified + ? '${v.shownHost} ✓' + : l.submitNotVerified(v.shownHost), + style: theme.textTheme.muted.copyWith(fontSize: 12), + ), + const SizedBox(height: 10), + Text( + v.delivery == SubmissionDeliveryState.pending + ? l.submittingChip + : v.delivery == SubmissionDeliveryState.failed + ? l.submitDeliveryFailed(v.publicationName) + : submissionStatusLabel(app, v.status), + style: theme.textTheme.small, + ), + if (last != null) + Text( + l.submittedBy( + last.submittedByName, + _date(last.submittedAt), + last.sequence, + ), + style: theme.textTheme.muted.copyWith(fontSize: 12), + ), + if (v.lastMessage != null) ...[ + const SizedBox(height: 10), + Container( + padding: const EdgeInsets.all(8), + decoration: BoxDecoration( + color: theme.colorScheme.muted, + borderRadius: BorderRadius.circular(6), + ), + child: Text( + v.lastMessage!, + maxLines: 6, + overflow: TextOverflow.ellipsis, + style: theme.textTheme.small, + ), + ), + ], + const SizedBox(height: 10), + Wrap( + spacing: 6, + runSpacing: 6, + children: [ + if (v.feedbackThreadUuid != null) + ShadButton.outline( + key: const ValueKey('write.submission.openThread'), + size: ShadButtonSize.sm, + onPressed: () => _invoke( + context, + 'write.comments.activate', + JsonArgs({'threadUuid': v.feedbackThreadUuid!.uuid}), + ), + child: Text(l.submitOpenThread), + ), + if (v.publicUrl != null) + ShadButton.outline( + key: const ValueKey('write.submission.viewPost'), + size: ShadButtonSize.sm, + onPressed: () { + onClose(); + unawaited(services.crossApp.openExternal(v.publicUrl!)); + }, + child: Text(l.submitViewPost), + ), + if (c.canWithdraw) + ShadButton.ghost( + key: const ValueKey('write.submission.withdraw'), + size: ShadButtonSize.sm, + onPressed: () => + _invoke(context, 'write.submission.withdraw'), + child: Text(l.cmdSubmissionWithdraw), + ), + if (c.canDisconnect && doc.role >= Role.editor) + ShadButton.ghost( + key: const ValueKey('write.submission.disconnect'), + size: ShadButtonSize.sm, + onPressed: () => + _invoke(context, 'write.submission.disconnect'), + child: Text(l.submitDisconnect(v.publicationName)), + ), + ], + ), + ], + ), + ); + }, + ); +} diff --git a/wonky_write/lib/features/publish/submit_dialog.dart b/wonky_write/lib/features/publish/submit_dialog.dart new file mode 100644 index 00000000..2418f0be --- /dev/null +++ b/wonky_write/lib/features/publish/submit_dialog.dart @@ -0,0 +1,204 @@ +import 'package:flutter/widgets.dart'; +import 'package:wonky_app/wonky_app.dart'; +import 'package:wonky_client/wonky_client.dart'; + +import '../../l10n/write_l10n.dart'; +import '../screen/write_document_controller.dart'; + +/// The default name of a story's document (server: `PublicationService`). +const untitledStoryName = 'Untitled story'; + +/// An image of the document that can be the cover (specs/18 §4.2). +class StoryImage { + const StoryImage(this.fileUuid, this.alt); + + final UuidValue fileUuid; + final String alt; +} + +/// The uploaded images of the document, in order. +List storyImages(WriteDocumentController doc) { + final out = []; + final seen = {}; + for (final op in doc.editor.delta.toList()) { + final data = op.data; + if (data is! Map || data['image'] is! Map) continue; + final image = data['image'] as Map; + final src = '${image['src'] ?? ''}'; + const scheme = 'wonky-file://'; + if (!src.startsWith(scheme)) continue; + final id = src.substring(scheme.length); + if (!seen.add(id)) continue; + try { + out.add( + StoryImage(UuidValue.withValidation(id), '${image['alt'] ?? ''}'), + ); + } on FormatException { + continue; + } + } + return out; +} + +/// The number of open suggestions in the document (they are sent as the +/// original text, specs/18 §4.2). +int openSuggestionCount(WriteDocumentController doc) { + final ids = {}; + for (final op in doc.editor.delta.toList()) { + for (final key in op.attributes?.keys ?? const []) { + if (key.startsWith('sug_')) ids.add(key); + } + } + return ids.length; +} + +/// The title a first submit starts with: the stored one, else the +/// document's name, else its first heading. +String initialStoryTitle(WriteDocumentController doc, SubmissionView v) { + if (v.values.title.trim().isNotEmpty && v.values.title != untitledStoryName) { + return v.values.title; + } + if (doc.title.trim().isNotEmpty && doc.title != untitledStoryName) { + return doc.title; + } + doc.insights.refresh(); + final outline = doc.insights.outline; + return outline.isEmpty ? '' : outline.first.text; +} + +/// *Submit to (publication)* (specs/18 §4.2): asks for the publication's +/// fields and submits the current revision. Returns the new view, or null +/// when cancelled. +Future showSubmitDialog( + BuildContext context, + ShellServices s, + WriteDocumentController doc, +) async { + final v = doc.submission.view; + if (v == null) return null; + final l = writeL10n(context); + final f = v.fields; + final images = storyImages(doc); + final suggestions = openSuggestionCount(doc); + String? need(PublicationFieldMode mode, String value) => + mode == PublicationFieldMode.required && value.trim().isEmpty + ? l.submitRequired + : null; + final cover = + v.values.coverImage ?? (images.isEmpty ? null : images.first.fileUuid); + final r = await showWonkyFormDialog( + context, + WonkyDialogSpec( + title: l.submitTitle(v.publicationName), + description: [ + v.verified + ? l.submitHostVerified(v.shownHost) + : l.submitHostUnverified(v.shownHost), + if (suggestions > 0) l.submitOpenSuggestions(suggestions), + l.submitCommentsStay, + ].join('\n\n'), + dialogKey: 'dialog.submit', + width: 520, + fields: [ + TextFieldSpec( + id: 'title', + label: l.submitFieldTitle, + initial: initialStoryTitle(doc, v), + maxLength: 300, + validator: (x) => x.trim().isEmpty ? l.submitRequired : null, + ), + if (f.summary != PublicationFieldMode.off) + TextFieldSpec( + id: 'summary', + label: _label(l, l.submitFieldSummary, f.summary), + initial: v.values.summary ?? '', + multiline: true, + maxLength: 2000, + validator: (x) => need(f.summary, x), + ), + if (f.tags != PublicationFieldMode.off) + TextFieldSpec( + id: 'tags', + label: _label(l, l.submitFieldTags, f.tags), + placeholder: f.allowedTags.isEmpty + ? l.submitTagsHint + : l.submitTagsFrom(f.allowedTags.join(', ')), + initial: v.values.tags.join(', '), + validator: (x) => need(f.tags, x), + ), + if (f.coverImage != PublicationFieldMode.off) + SelectFieldSpec( + id: 'cover', + label: _label(l, l.submitFieldCover, f.coverImage), + options: { + '': l.submitNoCover, + for (final (i, img) in images.indexed) + img.fileUuid.uuid: img.alt.isEmpty + ? l.submitImage(i + 1) + : l.submitImageAlt(i + 1, img.alt), + }, + initial: cover?.uuid ?? '', + ), + if (f.authorBio != PublicationFieldMode.off) + TextFieldSpec( + id: 'authorBio', + label: _label(l, l.submitFieldBio, f.authorBio), + initial: v.values.authorBio ?? '', + multiline: true, + maxLength: 2000, + validator: (x) => need(f.authorBio, x), + ), + if (f.note != PublicationFieldMode.off) + TextFieldSpec( + id: 'note', + label: _label(l, l.submitFieldNote, f.note), + multiline: true, + maxLength: 2000, + validator: (x) => need(f.note, x), + ), + if (v.consentNeeded && v.termsUrl != null) + CheckboxFieldSpec( + id: 'terms', + label: l.submitTerms(v.publicationName, v.termsUrl!), + ), + ], + buttons: [ + DialogButtonSpec( + id: 'cancel', + label: WonkyAppLocalizations.of(context).actionCancel, + validates: false, + ), + DialogButtonSpec(id: 'submit', label: l.submitButton, primary: true), + ], + ), + ); + if (r == null || r.buttonId != 'submit') return null; + if (v.consentNeeded && v.termsUrl != null && !r.flag('terms')) { + s.toasts.error(l.submitTermsRequired(v.publicationName)); + return null; + } + if (f.coverImage == PublicationFieldMode.required && + r.text('cover').isEmpty) { + s.toasts.error(l.submitCoverRequired); + return null; + } + String? opt(String id) => + r.text(id).trim().isEmpty ? null : r.text(id).trim(); + final values = SubmissionValues( + title: r.text('title').trim(), + summary: opt('summary'), + tags: [ + for (final t in r.text('tags').split(',')) + if (t.trim().isNotEmpty) t.trim(), + ], + coverImage: r.text('cover').isEmpty + ? null + : UuidValue.fromString(r.text('cover')), + authorBio: opt('authorBio'), + note: opt('note'), + ); + return doc.submission.submit(values, agreed: v.consentNeeded); +} + +String _label(WriteLocalizations l, String label, PublicationFieldMode mode) => + mode == PublicationFieldMode.required ? label : l.submitOptional(label); diff --git a/wonky_write/lib/features/screen/write_document_controller.dart b/wonky_write/lib/features/screen/write_document_controller.dart index a5590347..c955ceb5 100644 --- a/wonky_write/lib/features/screen/write_document_controller.dart +++ b/wonky_write/lib/features/screen/write_document_controller.dart @@ -26,6 +26,7 @@ import '../export/export_service.dart'; import '../find_replace/find_controller.dart'; import '../images/image_services.dart'; import '../outline/outline_panel.dart'; +import '../publish/submission_controller.dart'; import '../spellcheck/write_spellcheck.dart'; import '../themes/document_theme.dart'; import '../themes/write_fonts.dart'; @@ -164,6 +165,14 @@ class WriteDocumentController extends DocumentController { /// Spellcheck of this document (Write 04 §28.2). late final WriteSpellcheck spellcheck = WriteSpellcheck(controller: editor); + /// The document's submission to a publication (specs/18 §4); started by + /// the screen once the document is open. + late final SubmissionController submission = SubmissionController( + services: services, + itemUuid: session.itemUuid, + revision: () => session.revision, + ); + /// Scrolls a Delta offset into view (set by the screen's editor widget). void Function(int offset)? revealOffset; @@ -702,6 +711,7 @@ class WriteDocumentController extends DocumentController { editor.view.removeListener(notifyListeners); services.prefs.removeListener(_onPrefs); spellcheck.dispose(); + submission.dispose(); documentTheme.removeListener(_onTheme); images.dispose(); viewPrefs.dispose(); diff --git a/wonky_write/lib/features/screen/write_document_screen.dart b/wonky_write/lib/features/screen/write_document_screen.dart index dd020e64..c9505607 100644 --- a/wonky_write/lib/features/screen/write_document_screen.dart +++ b/wonky_write/lib/features/screen/write_document_screen.dart @@ -36,6 +36,7 @@ import 'command_invoke.dart'; import 'document_menus.dart'; import 'selection_toolbar.dart'; import 'write_document_controller.dart'; +import '../publish/submission_title_actions.dart'; import 'write_toolbar.dart'; /// Creates the document session of the screen (tests inject fakes). @@ -149,6 +150,7 @@ class _WriteDocumentScreenState extends State { void _onPhase() { if (session.phase.value != WriteSessionPhase.ready) return; + doc.submission.start(); WidgetsBinding.instance.addPostFrameCallback((_) { if (!mounted) return; final heading = widget.heading; @@ -191,6 +193,10 @@ class _WriteDocumentScreenState extends State { belowToolbar: _modeLine, // The comments toggle is in the toolbar, next to the mode switcher. commentsButton: false, + // A story for a publication: status chip and Submit (specs/18 §4.1). + titleActions: (context) => [ + SubmissionTitleActions(services: s, doc: doc), + ], // Rail order: Assistant, Outline, Find (then the shell's History). panels: [ if (s.assistant?.available ?? false) writeAssistantPanelSpec(ai), diff --git a/wonky_write/lib/l10n/gen/write_localizations.dart b/wonky_write/lib/l10n/gen/write_localizations.dart index 65eeeb45..c7a81ff7 100644 --- a/wonky_write/lib/l10n/gen/write_localizations.dart +++ b/wonky_write/lib/l10n/gen/write_localizations.dart @@ -8204,6 +8204,294 @@ abstract class WriteLocalizations { /// In en, this message translates to: /// **'Continue writing'** String get slashContinueWriting; + + /// File menu / command: submit the story to the blog it was started for (specs/18 §4.4). + /// + /// In en, this message translates to: + /// **'Submit to publication…'** + String get cmdSubmissionSubmit; + + /// No description provided for @cmdSubmissionStatus. + /// + /// In en, this message translates to: + /// **'Submission status'** + String get cmdSubmissionStatus; + + /// No description provided for @cmdSubmissionWithdraw. + /// + /// In en, this message translates to: + /// **'Withdraw submission'** + String get cmdSubmissionWithdraw; + + /// No description provided for @cmdSubmissionDisconnect. + /// + /// In en, this message translates to: + /// **'Disconnect from publication'** + String get cmdSubmissionDisconnect; + + /// Title row button: sends the story to the publication's review queue. + /// + /// In en, this message translates to: + /// **'Submit'** + String get submitButton; + + /// No description provided for @resubmitButton. + /// + /// In en, this message translates to: + /// **'Resubmit'** + String get resubmitButton; + + /// No description provided for @submitUpdateButton. + /// + /// In en, this message translates to: + /// **'Submit update'** + String get submitUpdateButton; + + /// No description provided for @submitTooltip. + /// + /// In en, this message translates to: + /// **'Submit to {publication}'** + String submitTooltip(String publication); + + /// No description provided for @submittingChip. + /// + /// In en, this message translates to: + /// **'Submitting…'** + String get submittingChip; + + /// No description provided for @submitTitle. + /// + /// In en, this message translates to: + /// **'Submit to {publication}'** + String submitTitle(String publication); + + /// No description provided for @submitHostVerified. + /// + /// In en, this message translates to: + /// **'{host} ✓'** + String submitHostVerified(String host); + + /// No description provided for @submitHostUnverified. + /// + /// In en, this message translates to: + /// **'Sent to {host} (Wonky hasn\'t verified this publication).'** + String submitHostUnverified(String host); + + /// No description provided for @submitNotVerified. + /// + /// In en, this message translates to: + /// **'{host} (not verified)'** + String submitNotVerified(String host); + + /// No description provided for @submitOpenSuggestions. + /// + /// In en, this message translates to: + /// **'{count, plural, =1{1 open suggestion isn\'t included: the original text is sent.} other{{count} open suggestions aren\'t included: the original text is sent.}}'** + String submitOpenSuggestions(int count); + + /// No description provided for @submitCommentsStay. + /// + /// In en, this message translates to: + /// **'Comments stay in Wonky. The moderators can read them.'** + String get submitCommentsStay; + + /// No description provided for @submitFieldTitle. + /// + /// In en, this message translates to: + /// **'Title'** + String get submitFieldTitle; + + /// No description provided for @submitFieldSummary. + /// + /// In en, this message translates to: + /// **'Summary'** + String get submitFieldSummary; + + /// No description provided for @submitFieldTags. + /// + /// In en, this message translates to: + /// **'Tags'** + String get submitFieldTags; + + /// No description provided for @submitFieldCover. + /// + /// In en, this message translates to: + /// **'Cover image'** + String get submitFieldCover; + + /// No description provided for @submitFieldBio. + /// + /// In en, this message translates to: + /// **'Author bio'** + String get submitFieldBio; + + /// No description provided for @submitFieldNote. + /// + /// In en, this message translates to: + /// **'Note to the moderators'** + String get submitFieldNote; + + /// No description provided for @submitOptional. + /// + /// In en, this message translates to: + /// **'{label} (optional)'** + String submitOptional(String label); + + /// No description provided for @submitRequired. + /// + /// In en, this message translates to: + /// **'Required.'** + String get submitRequired; + + /// No description provided for @submitTagsHint. + /// + /// In en, this message translates to: + /// **'Comma separated'** + String get submitTagsHint; + + /// No description provided for @submitTagsFrom. + /// + /// In en, this message translates to: + /// **'Comma separated, from: {tags}'** + String submitTagsFrom(String tags); + + /// No description provided for @submitNoCover. + /// + /// In en, this message translates to: + /// **'No cover image'** + String get submitNoCover; + + /// No description provided for @submitImage. + /// + /// In en, this message translates to: + /// **'Image {count}'** + String submitImage(int count); + + /// No description provided for @submitImageAlt. + /// + /// In en, this message translates to: + /// **'Image {count}: {alt}'** + String submitImageAlt(int count, String alt); + + /// No description provided for @submitTerms. + /// + /// In en, this message translates to: + /// **'I agree to {publication}\'s contributor terms ({url})'** + String submitTerms(String publication, String url); + + /// No description provided for @submitTermsRequired. + /// + /// In en, this message translates to: + /// **'Agree to {publication}\'s contributor terms to submit.'** + String submitTermsRequired(String publication); + + /// No description provided for @submitCoverRequired. + /// + /// In en, this message translates to: + /// **'Pick a cover image.'** + String get submitCoverRequired; + + /// No description provided for @submitDone. + /// + /// In en, this message translates to: + /// **'Submitted to {publication}'** + String submitDone(String publication); + + /// No description provided for @submitPending. + /// + /// In en, this message translates to: + /// **'{publication} didn\'t answer yet. We\'ll keep trying.'** + String submitPending(String publication); + + /// No description provided for @submitDeliveryFailed. + /// + /// In en, this message translates to: + /// **'{publication} couldn\'t receive your submission. Try again later.'** + String submitDeliveryFailed(String publication); + + /// No description provided for @submittedBy. + /// + /// In en, this message translates to: + /// **'Submitted by {name} · {date} · #{count}'** + String submittedBy(String name, String date, int count); + + /// No description provided for @submitOpenThread. + /// + /// In en, this message translates to: + /// **'Open messages'** + String get submitOpenThread; + + /// No description provided for @submitViewPost. + /// + /// In en, this message translates to: + /// **'View post'** + String get submitViewPost; + + /// No description provided for @submitDisconnect. + /// + /// In en, this message translates to: + /// **'Disconnect from {publication}'** + String submitDisconnect(String publication); + + /// No description provided for @submitReasonNone. + /// + /// In en, this message translates to: + /// **'This document isn\'t a story for a publication.'** + String get submitReasonNone; + + /// No description provided for @submitReasonOffline. + /// + /// In en, this message translates to: + /// **'Submitting needs a connection.'** + String get submitReasonOffline; + + /// No description provided for @submitReasonClosed. + /// + /// In en, this message translates to: + /// **'{publication} isn\'t accepting stories right now.'** + String submitReasonClosed(String publication); + + /// No description provided for @submitReasonDeclined. + /// + /// In en, this message translates to: + /// **'{publication} declined this story.'** + String submitReasonDeclined(String publication); + + /// No description provided for @submitReasonNoChanges. + /// + /// In en, this message translates to: + /// **'No changes since you submitted.'** + String get submitReasonNoChanges; + + /// No description provided for @submitReasonNotInReview. + /// + /// In en, this message translates to: + /// **'The story isn\'t in review.'** + String get submitReasonNotInReview; + + /// No description provided for @submitReasonWithdrawFirst. + /// + /// In en, this message translates to: + /// **'Withdraw the story before you disconnect it.'** + String get submitReasonWithdrawFirst; + + /// No description provided for @withdrawTitle. + /// + /// In en, this message translates to: + /// **'Withdraw from {publication}?'** + String withdrawTitle(String publication); + + /// No description provided for @withdrawBody. + /// + /// In en, this message translates to: + /// **'{publication} is told, and its moderators lose access to the document. You can submit it again later.'** + String withdrawBody(String publication); + + /// No description provided for @withdrawButton. + /// + /// In en, this message translates to: + /// **'Withdraw'** + String get withdrawButton; } class _WriteLocalizationsDelegate diff --git a/wonky_write/lib/l10n/gen/write_localizations_en.dart b/wonky_write/lib/l10n/gen/write_localizations_en.dart index 88e92952..3c2c1caa 100644 --- a/wonky_write/lib/l10n/gen/write_localizations_en.dart +++ b/wonky_write/lib/l10n/gen/write_localizations_en.dart @@ -4640,6 +4640,202 @@ class WriteLocalizationsEn extends WriteLocalizations { @override String get slashContinueWriting => 'Continue writing'; + + @override + String get cmdSubmissionSubmit => 'Submit to publication…'; + + @override + String get cmdSubmissionStatus => 'Submission status'; + + @override + String get cmdSubmissionWithdraw => 'Withdraw submission'; + + @override + String get cmdSubmissionDisconnect => 'Disconnect from publication'; + + @override + String get submitButton => 'Submit'; + + @override + String get resubmitButton => 'Resubmit'; + + @override + String get submitUpdateButton => 'Submit update'; + + @override + String submitTooltip(String publication) { + return 'Submit to $publication'; + } + + @override + String get submittingChip => 'Submitting…'; + + @override + String submitTitle(String publication) { + return 'Submit to $publication'; + } + + @override + String submitHostVerified(String host) { + return '$host ✓'; + } + + @override + String submitHostUnverified(String host) { + return 'Sent to $host (Wonky hasn\'t verified this publication).'; + } + + @override + String submitNotVerified(String host) { + return '$host (not verified)'; + } + + @override + String submitOpenSuggestions(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: + '$count open suggestions aren\'t included: the original text is sent.', + one: '1 open suggestion isn\'t included: the original text is sent.', + ); + return '$_temp0'; + } + + @override + String get submitCommentsStay => + 'Comments stay in Wonky. The moderators can read them.'; + + @override + String get submitFieldTitle => 'Title'; + + @override + String get submitFieldSummary => 'Summary'; + + @override + String get submitFieldTags => 'Tags'; + + @override + String get submitFieldCover => 'Cover image'; + + @override + String get submitFieldBio => 'Author bio'; + + @override + String get submitFieldNote => 'Note to the moderators'; + + @override + String submitOptional(String label) { + return '$label (optional)'; + } + + @override + String get submitRequired => 'Required.'; + + @override + String get submitTagsHint => 'Comma separated'; + + @override + String submitTagsFrom(String tags) { + return 'Comma separated, from: $tags'; + } + + @override + String get submitNoCover => 'No cover image'; + + @override + String submitImage(int count) { + return 'Image $count'; + } + + @override + String submitImageAlt(int count, String alt) { + return 'Image $count: $alt'; + } + + @override + String submitTerms(String publication, String url) { + return 'I agree to $publication\'s contributor terms ($url)'; + } + + @override + String submitTermsRequired(String publication) { + return 'Agree to $publication\'s contributor terms to submit.'; + } + + @override + String get submitCoverRequired => 'Pick a cover image.'; + + @override + String submitDone(String publication) { + return 'Submitted to $publication'; + } + + @override + String submitPending(String publication) { + return '$publication didn\'t answer yet. We\'ll keep trying.'; + } + + @override + String submitDeliveryFailed(String publication) { + return '$publication couldn\'t receive your submission. Try again later.'; + } + + @override + String submittedBy(String name, String date, int count) { + return 'Submitted by $name · $date · #$count'; + } + + @override + String get submitOpenThread => 'Open messages'; + + @override + String get submitViewPost => 'View post'; + + @override + String submitDisconnect(String publication) { + return 'Disconnect from $publication'; + } + + @override + String get submitReasonNone => + 'This document isn\'t a story for a publication.'; + + @override + String get submitReasonOffline => 'Submitting needs a connection.'; + + @override + String submitReasonClosed(String publication) { + return '$publication isn\'t accepting stories right now.'; + } + + @override + String submitReasonDeclined(String publication) { + return '$publication declined this story.'; + } + + @override + String get submitReasonNoChanges => 'No changes since you submitted.'; + + @override + String get submitReasonNotInReview => 'The story isn\'t in review.'; + + @override + String get submitReasonWithdrawFirst => + 'Withdraw the story before you disconnect it.'; + + @override + String withdrawTitle(String publication) { + return 'Withdraw from $publication?'; + } + + @override + String withdrawBody(String publication) { + return '$publication is told, and its moderators lose access to the document. You can submit it again later.'; + } + + @override + String get withdrawButton => 'Withdraw'; } /// The translations for English (`en_XA`). @@ -9337,4 +9533,203 @@ class WriteLocalizationsEnXa extends WriteLocalizationsEn { @override String get slashContinueWriting => '[Çöñţîñûé ŵŕîţîñĝ one tw]'; + + @override + String get cmdSubmissionSubmit => '[Šûƀɱîţ ţö þûƀļîçåţîöñ… one two]'; + + @override + String get cmdSubmissionStatus => '[Šûƀɱîššîöñ šţåţûš one tw]'; + + @override + String get cmdSubmissionWithdraw => '[Ŵîţĥðŕåŵ šûƀɱîššîöñ one two]'; + + @override + String get cmdSubmissionDisconnect => + '[Ðîšçöññéçţ ƒŕöɱ þûƀļîçåţîöñ one two t]'; + + @override + String get submitButton => '[Šûƀɱîţ one]'; + + @override + String get resubmitButton => '[Ŕéšûƀɱîţ one]'; + + @override + String get submitUpdateButton => '[Šûƀɱîţ ûþðåţé one t]'; + + @override + String submitTooltip(String publication) { + return '[Šûƀɱîţ ţö $publication one]'; + } + + @override + String get submittingChip => '[Šûƀɱîţţîñĝ… one]'; + + @override + String submitTitle(String publication) { + return '[Šûƀɱîţ ţö $publication one]'; + } + + @override + String submitHostVerified(String host) { + return '[$host ✓ o]'; + } + + @override + String submitHostUnverified(String host) { + return '[Šéñţ ţö $host (Ŵöñķý ĥåšñ\'ţ ṽéŕîƒîéð ţĥîš þûƀļîçåţîöñ). one two three fo]'; + } + + @override + String submitNotVerified(String host) { + return '[$host (ñöţ ṽéŕîƒîéð) one t]'; + } + + @override + String submitOpenSuggestions(int count) { + String _temp0 = intl.Intl.pluralLogic( + count, + locale: localeName, + other: + '$count öþéñ šûĝĝéšţîöñš åŕéñ\'ţ îñçļûðéð: ţĥé öŕîĝîñåļ ţéẋţ îš šéñţ.', + one: '1 öþéñ šûĝĝéšţîöñ îšñ\'ţ îñçļûðéð: ţĥé öŕîĝîñåļ ţéẋţ îš šéñţ.', + ); + return '[$_temp0 one two three four five six seven eig]'; + } + + @override + String get submitCommentsStay => + '[Çöɱɱéñţš šţåý îñ Ŵöñķý. Ţĥé ɱöðéŕåţöŕš çåñ ŕéåð ţĥéɱ. one two three fo]'; + + @override + String get submitFieldTitle => '[Ţîţļé on]'; + + @override + String get submitFieldSummary => '[Šûɱɱåŕý one]'; + + @override + String get submitFieldTags => '[Ţåĝš on]'; + + @override + String get submitFieldCover => '[Çöṽéŕ îɱåĝé one]'; + + @override + String get submitFieldBio => '[Åûţĥöŕ ƀîö one]'; + + @override + String get submitFieldNote => '[Ñöţé ţö ţĥé ɱöðéŕåţöŕš one two]'; + + @override + String submitOptional(String label) { + return '[$label (öþţîöñåļ) one]'; + } + + @override + String get submitRequired => '[Ŕéǫûîŕéð. one]'; + + @override + String get submitTagsHint => '[Çöɱɱå šéþåŕåţéð one t]'; + + @override + String submitTagsFrom(String tags) { + return '[Çöɱɱå šéþåŕåţéð, ƒŕöɱ: $tags one two]'; + } + + @override + String get submitNoCover => '[Ñö çöṽéŕ îɱåĝé one t]'; + + @override + String submitImage(int count) { + return '[Îɱåĝé $count on]'; + } + + @override + String submitImageAlt(int count, String alt) { + return '[Îɱåĝé $count: $alt one]'; + } + + @override + String submitTerms(String publication, String url) { + return '[Î åĝŕéé ţö $publication\'š çöñţŕîƀûţöŕ ţéŕɱš ($url) one two th]'; + } + + @override + String submitTermsRequired(String publication) { + return '[Åĝŕéé ţö $publication\'š çöñţŕîƀûţöŕ ţéŕɱš ţö šûƀɱîţ. one two thre]'; + } + + @override + String get submitCoverRequired => '[Þîçķ å çöṽéŕ îɱåĝé. one tw]'; + + @override + String submitDone(String publication) { + return '[Šûƀɱîţţéð ţö $publication one]'; + } + + @override + String submitPending(String publication) { + return '[$publication ðîðñ\'ţ åñšŵéŕ ýéţ. Ŵé\'ļļ ķééþ ţŕýîñĝ. one two thre]'; + } + + @override + String submitDeliveryFailed(String publication) { + return '[$publication çöûļðñ\'ţ ŕéçéîṽé ýöûŕ šûƀɱîššîöñ. Ţŕý åĝåîñ ļåţéŕ. one two three fo]'; + } + + @override + String submittedBy(String name, String date, int count) { + return '[Šûƀɱîţţéð ƀý $name · $date · #$count one t]'; + } + + @override + String get submitOpenThread => '[Öþéñ ɱéššåĝéš one t]'; + + @override + String get submitViewPost => '[Ṽîéŵ þöšţ one]'; + + @override + String submitDisconnect(String publication) { + return '[Ðîšçöññéçţ ƒŕöɱ $publication one t]'; + } + + @override + String get submitReasonNone => + '[Ţĥîš ðöçûɱéñţ îšñ\'ţ å šţöŕý ƒöŕ å þûƀļîçåţîöñ. one two three]'; + + @override + String get submitReasonOffline => + '[Šûƀɱîţţîñĝ ñééðš å çöññéçţîöñ. one two th]'; + + @override + String submitReasonClosed(String publication) { + return '[$publication îšñ\'ţ åççéþţîñĝ šţöŕîéš ŕîĝĥţ ñöŵ. one two thr]'; + } + + @override + String submitReasonDeclined(String publication) { + return '[$publication ðéçļîñéð ţĥîš šţöŕý. one two]'; + } + + @override + String get submitReasonNoChanges => + '[Ñö çĥåñĝéš šîñçé ýöû šûƀɱîţţéð. one two th]'; + + @override + String get submitReasonNotInReview => '[Ţĥé šţöŕý îšñ\'ţ îñ ŕéṽîéŵ. one two]'; + + @override + String get submitReasonWithdrawFirst => + '[Ŵîţĥðŕåŵ ţĥé šţöŕý ƀéƒöŕé ýöû ðîšçöññéçţ îţ. one two three]'; + + @override + String withdrawTitle(String publication) { + return '[Ŵîţĥðŕåŵ ƒŕöɱ $publication? one t]'; + } + + @override + String withdrawBody(String publication) { + return '[$publication îš ţöļð, åñð îţš ɱöðéŕåţöŕš ļöšé åççéšš ţö ţĥé ðöçûɱéñţ. Ýöû çåñ šûƀɱîţ îţ åĝåîñ ļåţéŕ. one two three four five si]'; + } + + @override + String get withdrawButton => '[Ŵîţĥðŕåŵ one]'; } diff --git a/wonky_write/lib/l10n/write_en.arb b/wonky_write/lib/l10n/write_en.arb index f4dec26a..6ff272f5 100644 --- a/wonky_write/lib/l10n/write_en.arb +++ b/wonky_write/lib/l10n/write_en.arb @@ -3262,5 +3262,76 @@ "slashEmoji": "Emoji…", "slashSpecialCharacters": "Special characters…", "slashAskAi": "Ask AI…", - "slashContinueWriting": "Continue writing" + "slashContinueWriting": "Continue writing", + "cmdSubmissionSubmit": "Submit to publication…", + "@cmdSubmissionSubmit": {"description": "File menu / command: submit the story to the blog it was started for (specs/18 §4.4)."}, + "cmdSubmissionStatus": "Submission status", + "cmdSubmissionWithdraw": "Withdraw submission", + "cmdSubmissionDisconnect": "Disconnect from publication", + "submitButton": "Submit", + "@submitButton": {"description": "Title row button: sends the story to the publication's review queue."}, + "resubmitButton": "Resubmit", + "submitUpdateButton": "Submit update", + "submitTooltip": "Submit to {publication}", + "@submitTooltip": {"placeholders": {"publication": {"type": "String"}}}, + "submittingChip": "Submitting…", + "submitTitle": "Submit to {publication}", + "@submitTitle": {"placeholders": {"publication": {"type": "String"}}}, + "submitHostVerified": "{host} ✓", + "@submitHostVerified": {"placeholders": {"host": {"type": "String"}}}, + "submitHostUnverified": "Sent to {host} (Wonky hasn't verified this publication).", + "@submitHostUnverified": {"placeholders": {"host": {"type": "String"}}}, + "submitNotVerified": "{host} (not verified)", + "@submitNotVerified": {"placeholders": {"host": {"type": "String"}}}, + "submitOpenSuggestions": "{count, plural, =1{1 open suggestion isn't included: the original text is sent.} other{{count} open suggestions aren't included: the original text is sent.}}", + "@submitOpenSuggestions": {"placeholders": {"count": {"type": "int"}}}, + "submitCommentsStay": "Comments stay in Wonky. The moderators can read them.", + "submitFieldTitle": "Title", + "submitFieldSummary": "Summary", + "submitFieldTags": "Tags", + "submitFieldCover": "Cover image", + "submitFieldBio": "Author bio", + "submitFieldNote": "Note to the moderators", + "submitOptional": "{label} (optional)", + "@submitOptional": {"placeholders": {"label": {"type": "String"}}}, + "submitRequired": "Required.", + "submitTagsHint": "Comma separated", + "submitTagsFrom": "Comma separated, from: {tags}", + "@submitTagsFrom": {"placeholders": {"tags": {"type": "String"}}}, + "submitNoCover": "No cover image", + "submitImage": "Image {count}", + "@submitImage": {"placeholders": {"count": {"type": "int"}}}, + "submitImageAlt": "Image {count}: {alt}", + "@submitImageAlt": {"placeholders": {"count": {"type": "int"}, "alt": {"type": "String"}}}, + "submitTerms": "I agree to {publication}'s contributor terms ({url})", + "@submitTerms": {"placeholders": {"publication": {"type": "String"}, "url": {"type": "String"}}}, + "submitTermsRequired": "Agree to {publication}'s contributor terms to submit.", + "@submitTermsRequired": {"placeholders": {"publication": {"type": "String"}}}, + "submitCoverRequired": "Pick a cover image.", + "submitDone": "Submitted to {publication}", + "@submitDone": {"placeholders": {"publication": {"type": "String"}}}, + "submitPending": "{publication} didn't answer yet. We'll keep trying.", + "@submitPending": {"placeholders": {"publication": {"type": "String"}}}, + "submitDeliveryFailed": "{publication} couldn't receive your submission. Try again later.", + "@submitDeliveryFailed": {"placeholders": {"publication": {"type": "String"}}}, + "submittedBy": "Submitted by {name} · {date} · #{count}", + "@submittedBy": {"placeholders": {"name": {"type": "String"}, "date": {"type": "String"}, "count": {"type": "int"}}}, + "submitOpenThread": "Open messages", + "submitViewPost": "View post", + "submitDisconnect": "Disconnect from {publication}", + "@submitDisconnect": {"placeholders": {"publication": {"type": "String"}}}, + "submitReasonNone": "This document isn't a story for a publication.", + "submitReasonOffline": "Submitting needs a connection.", + "submitReasonClosed": "{publication} isn't accepting stories right now.", + "@submitReasonClosed": {"placeholders": {"publication": {"type": "String"}}}, + "submitReasonDeclined": "{publication} declined this story.", + "@submitReasonDeclined": {"placeholders": {"publication": {"type": "String"}}}, + "submitReasonNoChanges": "No changes since you submitted.", + "submitReasonNotInReview": "The story isn't in review.", + "submitReasonWithdrawFirst": "Withdraw the story before you disconnect it.", + "withdrawTitle": "Withdraw from {publication}?", + "@withdrawTitle": {"placeholders": {"publication": {"type": "String"}}}, + "withdrawBody": "{publication} is told, and its moderators lose access to the document. You can submit it again later.", + "@withdrawBody": {"placeholders": {"publication": {"type": "String"}}}, + "withdrawButton": "Withdraw" } diff --git a/wonky_write/lib/l10n/write_en_XA.arb b/wonky_write/lib/l10n/write_en_XA.arb index 976ed21b..f50c8eb6 100644 --- a/wonky_write/lib/l10n/write_en_XA.arb +++ b/wonky_write/lib/l10n/write_en_XA.arb @@ -1350,5 +1350,53 @@ "slashEmoji": "[Éɱöĵî… one]", "slashSpecialCharacters": "[Šþéçîåļ çĥåŕåçţéŕš… one two]", "slashAskAi": "[Åšķ ÅÎ… one]", - "slashContinueWriting": "[Çöñţîñûé ŵŕîţîñĝ one tw]" + "slashContinueWriting": "[Çöñţîñûé ŵŕîţîñĝ one tw]", + "cmdSubmissionSubmit": "[Šûƀɱîţ ţö þûƀļîçåţîöñ… one two]", + "cmdSubmissionStatus": "[Šûƀɱîššîöñ šţåţûš one tw]", + "cmdSubmissionWithdraw": "[Ŵîţĥðŕåŵ šûƀɱîššîöñ one two]", + "cmdSubmissionDisconnect": "[Ðîšçöññéçţ ƒŕöɱ þûƀļîçåţîöñ one two t]", + "submitButton": "[Šûƀɱîţ one]", + "resubmitButton": "[Ŕéšûƀɱîţ one]", + "submitUpdateButton": "[Šûƀɱîţ ûþðåţé one t]", + "submitTooltip": "[Šûƀɱîţ ţö {publication} one]", + "submittingChip": "[Šûƀɱîţţîñĝ… one]", + "submitTitle": "[Šûƀɱîţ ţö {publication} one]", + "submitHostVerified": "[{host} ✓ o]", + "submitHostUnverified": "[Šéñţ ţö {host} (Ŵöñķý ĥåšñ'ţ ṽéŕîƒîéð ţĥîš þûƀļîçåţîöñ). one two three fo]", + "submitNotVerified": "[{host} (ñöţ ṽéŕîƒîéð) one t]", + "submitOpenSuggestions": "[{count, plural, =1{1 öþéñ šûĝĝéšţîöñ îšñ'ţ îñçļûðéð: ţĥé öŕîĝîñåļ ţéẋţ îš šéñţ.} other{{count} öþéñ šûĝĝéšţîöñš åŕéñ'ţ îñçļûðéð: ţĥé öŕîĝîñåļ ţéẋţ îš šéñţ.}} one two three four five six seven eig]", + "submitCommentsStay": "[Çöɱɱéñţš šţåý îñ Ŵöñķý. Ţĥé ɱöðéŕåţöŕš çåñ ŕéåð ţĥéɱ. one two three fo]", + "submitFieldTitle": "[Ţîţļé on]", + "submitFieldSummary": "[Šûɱɱåŕý one]", + "submitFieldTags": "[Ţåĝš on]", + "submitFieldCover": "[Çöṽéŕ îɱåĝé one]", + "submitFieldBio": "[Åûţĥöŕ ƀîö one]", + "submitFieldNote": "[Ñöţé ţö ţĥé ɱöðéŕåţöŕš one two]", + "submitOptional": "[{label} (öþţîöñåļ) one]", + "submitRequired": "[Ŕéǫûîŕéð. one]", + "submitTagsHint": "[Çöɱɱå šéþåŕåţéð one t]", + "submitTagsFrom": "[Çöɱɱå šéþåŕåţéð, ƒŕöɱ: {tags} one two]", + "submitNoCover": "[Ñö çöṽéŕ îɱåĝé one t]", + "submitImage": "[Îɱåĝé {count} on]", + "submitImageAlt": "[Îɱåĝé {count}: {alt} one]", + "submitTerms": "[Î åĝŕéé ţö {publication}'š çöñţŕîƀûţöŕ ţéŕɱš ({url}) one two th]", + "submitTermsRequired": "[Åĝŕéé ţö {publication}'š çöñţŕîƀûţöŕ ţéŕɱš ţö šûƀɱîţ. one two thre]", + "submitCoverRequired": "[Þîçķ å çöṽéŕ îɱåĝé. one tw]", + "submitDone": "[Šûƀɱîţţéð ţö {publication} one]", + "submitPending": "[{publication} ðîðñ'ţ åñšŵéŕ ýéţ. Ŵé'ļļ ķééþ ţŕýîñĝ. one two thre]", + "submitDeliveryFailed": "[{publication} çöûļðñ'ţ ŕéçéîṽé ýöûŕ šûƀɱîššîöñ. Ţŕý åĝåîñ ļåţéŕ. one two three fo]", + "submittedBy": "[Šûƀɱîţţéð ƀý {name} · {date} · #{count} one t]", + "submitOpenThread": "[Öþéñ ɱéššåĝéš one t]", + "submitViewPost": "[Ṽîéŵ þöšţ one]", + "submitDisconnect": "[Ðîšçöññéçţ ƒŕöɱ {publication} one t]", + "submitReasonNone": "[Ţĥîš ðöçûɱéñţ îšñ'ţ å šţöŕý ƒöŕ å þûƀļîçåţîöñ. one two three]", + "submitReasonOffline": "[Šûƀɱîţţîñĝ ñééðš å çöññéçţîöñ. one two th]", + "submitReasonClosed": "[{publication} îšñ'ţ åççéþţîñĝ šţöŕîéš ŕîĝĥţ ñöŵ. one two thr]", + "submitReasonDeclined": "[{publication} ðéçļîñéð ţĥîš šţöŕý. one two]", + "submitReasonNoChanges": "[Ñö çĥåñĝéš šîñçé ýöû šûƀɱîţţéð. one two th]", + "submitReasonNotInReview": "[Ţĥé šţöŕý îšñ'ţ îñ ŕéṽîéŵ. one two]", + "submitReasonWithdrawFirst": "[Ŵîţĥðŕåŵ ţĥé šţöŕý ƀéƒöŕé ýöû ðîšçöññéçţ îţ. one two three]", + "withdrawTitle": "[Ŵîţĥðŕåŵ ƒŕöɱ {publication}? one t]", + "withdrawBody": "[{publication} îš ţöļð, åñð îţš ɱöðéŕåţöŕš ļöšé åççéšš ţö ţĥé ðöçûɱéñţ. Ýöû çåñ šûƀɱîţ îţ åĝåîñ ļåţéŕ. one two three four five si]", + "withdrawButton": "[Ŵîţĥðŕåŵ one]" } diff --git a/wonky_write/test/features/document/support/session_harness.dart b/wonky_write/test/features/document/support/session_harness.dart index 04a9e9b8..01992cf5 100644 --- a/wonky_write/test/features/document/support/session_harness.dart +++ b/wonky_write/test/features/document/support/session_harness.dart @@ -4,7 +4,8 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_test/flutter_test.dart' show pumpEventQueue; import 'package:go_router/go_router.dart'; import 'package:wonky_app/spellcheck.dart' show ShellSpelling; -import 'package:wonky_app/testing.dart' show noSpellDictionaries; +import 'package:wonky_app/testing.dart' + show FakePublicationRepository, noSpellDictionaries; import 'package:wonky_app/wonky_app.dart'; import 'package:wonky_client/wonky_client.dart'; import 'package:wonky_write/features/document/write_document_api.dart'; @@ -240,6 +241,7 @@ class SessionHarness { versions: _FakeVersions(), files: _FakeFiles(), meta: _FakeMeta(), + publications: publications, ), urls: const AppUrls(apiUrl: 'http://localhost:8080/', apps: {}), connectivity: ConnectivityService(ping: () async {}), @@ -260,6 +262,9 @@ class SessionHarness { } final FakeDocumentServer server; + + /// Publications and submissions (specs/18). + final FakePublicationRepository publications = FakePublicationRepository(); final FakeComments comments; late final ShellServices services; late final FakeWriteApi api; diff --git a/wonky_write/test/features/publish/submission_test.dart b/wonky_write/test/features/publish/submission_test.dart new file mode 100644 index 00000000..07e5a536 --- /dev/null +++ b/wonky_write/test/features/publish/submission_test.dart @@ -0,0 +1,166 @@ +import 'package:flutter/widgets.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:wonky_app/testing.dart'; +import 'package:wonky_client/wonky_client.dart'; +import 'package:wonky_core/wonky_core.dart'; +import 'package:wonky_write/features/publish/submission_commands.dart'; +import 'package:wonky_write/features/publish/submission_title_actions.dart'; + +import '../document/support/session_harness.dart' as session; +import '../screen/support/screen_harness.dart'; + +Finder _key(String k) => find.byKey(ValueKey(k)); + +void main() { + final uuid = UuidValue.fromString(session.itemUuid); + + Future open( + WidgetTester tester, { + SubmissionView? view, + String markdown = '# Faster CI\n\nHello\n', + }) async { + final h = await ScreenHarness.open(tester, markdown: markdown); + final repo = h.session.publications; + if (view != null) repo.submissions[uuid] = view; + h.services.registry.registerAll(writeSubmissionCommands(h.services)); + h.doc.submission.start(); + await h.pump( + tester, + Center( + child: SubmissionTitleActions(services: h.services, doc: h.doc), + ), + ); + await tester.runAsync(() => h.doc.submission.refresh()); + await tester.pumpAndSettle(); + return h; + } + + group('Given a document without a submission', () { + testWidgets('then nothing shows and Submit is disabled', (tester) async { + final h = await open(tester); + + expect(_key('write.submission.submit'), findsNothing); + expect(_key('write.submission.chip'), findsNothing); + expect( + h.services.dispatcher.stateOf('write.submission.submit').enabled, + isFalse, + ); + await h.dispose(tester); + }); + }); + + group('Given a draft story', () { + testWidgets('then Submit shows without a status chip', (tester) async { + final h = await open(tester, view: FakePublicationRepository.view(uuid)); + + expect(_key('write.submission.submit'), findsOneWidget); + expect(_key('write.submission.chip'), findsNothing); + await h.dispose(tester); + }); + + testWidgets('when submitting then the title is the document\'s name and ' + 'the chip shows In review', (tester) async { + final h = await open(tester, view: FakePublicationRepository.view(uuid)); + + await tester.tap(_key('write.submission.submit')); + await tester.pumpAndSettle(); + expect(_key('dialog.submit'), findsOneWidget); + await tester.tap(_key('dialog.submit.submit')); + await tester.pumpAndSettle(); + + final repo = h.session.publications; + expect(repo.calls, contains('submit')); + expect(repo.lastValues!.title, 'Plan'); + expect(find.text('In review'), findsOneWidget); + await h.dispose(tester); + }); + + testWidgets('when offline then Submit is disabled with a reason', ( + tester, + ) async { + final h = await open(tester, view: FakePublicationRepository.view(uuid)); + + h.services.connectivity.forceOffline(true); + await tester.pump(); + + final state = h.services.dispatcher.stateOf('write.submission.submit'); + expect(state.enabled, isFalse); + expect(state.disabledReason, 'Submitting needs a connection.'); + h.services.connectivity.forceOffline(false); + await h.dispose(tester); + }); + }); + + group('Given a story with changes requested', () { + testWidgets('then the chip shows the status and the popover the message', ( + tester, + ) async { + final h = await open( + tester, + view: FakePublicationRepository.view( + uuid, + status: SubmissionStatus.changesRequested, + lastSubmittedRevision: 0, + lastMessage: 'Add an intro.', + ), + ); + + expect(find.text('Changes requested'), findsOneWidget); + await tester.tap(_key('write.submission.chip')); + await tester.pumpAndSettle(); + + expect(_key('write.submission.popover'), findsOneWidget); + expect(find.text('Add an intro.'), findsOneWidget); + expect(_key('write.submission.withdraw'), findsOneWidget); + await h.dispose(tester); + }); + }); + + group('Given a declined story', () { + testWidgets('then Submit is hidden', (tester) async { + final h = await open( + tester, + view: FakePublicationRepository.view( + uuid, + status: SubmissionStatus.declined, + ), + ); + + expect(_key('write.submission.submit'), findsNothing); + expect(find.text('Declined'), findsOneWidget); + await h.dispose(tester); + }); + }); + + group('Given a published story', () { + testWidgets('when disconnecting then undo connects it again', ( + tester, + ) async { + final h = await open( + tester, + view: FakePublicationRepository.view( + uuid, + status: SubmissionStatus.published, + publicUrl: 'https://blog.example.com/p', + ), + ); + + await tester.runAsync( + () => h.services.dispatcher.invoke( + 'write.submission.disconnect', + source: InvocationSource.ui, + ), + ); + await tester.pumpAndSettle(); + expect(h.doc.submission.hasSubmission, isFalse); + + await tester.runAsync(() => h.services.undo.undo()); + await tester.runAsync(() => h.doc.submission.refresh()); + await tester.pumpAndSettle(); + + expect(h.session.publications.calls, ['disconnect', 'reconnect']); + expect(h.doc.submission.hasSubmission, isTrue); + await h.dispose(tester); + }); + }); +}