Skip to content

Commit 77c5d8c

Browse files
committed
Bump version to 0.3.0, update README.md and CHANGELOG.md
1 parent 21b6298 commit 77c5d8c

File tree

9 files changed

+166
-14
lines changed

9 files changed

+166
-14
lines changed
25.2 KB
Loading
18.1 KB
Loading

.github/screenshots/modal-submit.png

16.9 KB
Loading

.github/screenshots/modal.png

30.6 KB
Loading

CHANGELOG.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
## 0.3.0
2+
3+
- Add support for [modals](https://github.com/mrbbot/slshx#using-modals)
4+
- Add support for [attachment options](https://github.com/mrbbot/slshx#options)
5+
- Return [error messages](https://github.com/mrbbot/slshx#errors) and stack
6+
traces to Discord during development
7+
- Add support for
8+
[`Bot` token authentication](https://github.com/mrbbot/slshx#missing-apis) to
9+
`call()`
10+
- Fallback to partial `{ id }` objects for mentionables, channels, and
11+
attachments on autocomplete. Closes
12+
[issue #1](https://github.com/mrbbot/slshx/issues/1), thanks
13+
[@helloimalastair](https://github.com/helloimalastair).
14+
- Throw clearer error when `useDescription("...")` isn't called. Closes
15+
[issue #2](https://github.com/mrbbot/slshx/issues/2), thanks
16+
[@SkyfallWasTaken](https://github.com/SkyfallWasTaken).
17+
18+
## 0.2.0
19+
20+
- Convert JSX `<Embed>` `author`/`footer` props to `snake_case`
21+
22+
## 0.1.1
23+
24+
- Fix missing `applicationPublicKey` error message
25+
- Add note to `README.md` that Slshx requires the
26+
[`--global-async-io` Miniflare flag](https://v2.miniflare.dev/core/standards#global-functionality-limits)
27+
to be set, to enable auto-deployments on reload.
28+
29+
## 0.1.0
30+
31+
Initial Release

README.md

Lines changed: 131 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
[Discord commands](https://discord.com/developers/docs/interactions/application-commands)
55
that run on [Cloudflare Workers](https://workers.cloudflare.com/), using a
66
React-inspired syntax. It focuses on providing a great local development
7-
experience, powered by [🔥 Miniflare 2](https://v2.miniflare.dev/).
7+
experience, powered by [🔥 Miniflare](https://miniflare.dev/).
88

99
<!-- prettier-ignore-start -->
1010
```tsx
@@ -15,7 +15,7 @@ function add(): CommandHandler {
1515
const a = useNumber("a", "1st number", { required: true });
1616
const b = useNumber("b", "2nd number", { required: true });
1717
return (interaction, env, ctx) => (
18-
<Message ephemeral>{a} + {b} = {a + b}</Message>
18+
<Message ephemeral>{a} + {b} = {a + b}</Message>
1919
);
2020
};
2121

@@ -44,14 +44,15 @@ export default { fetch: handler };
4444

4545
## Quick*ish* Start
4646

47-
> ⚠️ To enable auto-deployments on reload, Slshx requires the
48-
> [`--global-async-io` Miniflare flag](https://v2.miniflare.dev/core/standards#global-functionality-limits)
49-
> to be set.
50-
5147
1. Clone the [`slshx-starter`](https://github.com/mrbbot/slshx-starter)
52-
repository. This includes a [Miniflare](https://v2.miniflare.dev/) and
48+
repository. This includes a [Miniflare](https://miniflare.dev/) and
5349
[`esbuild`](https://esbuild.github.io/) setup that removes unneeded local
5450
development code when deploying to Workers.
51+
52+
> ⚠️ To enable auto-deployments on reload, Slshx requires the
53+
> [`--global-async-io` Miniflare flag](https://miniflare.dev/core/standards#global-functionality-limits)
54+
> to be set. `slshx-starter` automatically enables this for you.
55+
5556
2. Copy the `env.example.jsonc` file to `env.jsonc`. ⚠️ Do not commit this file.
5657
3. Create a new application in the
5758
[Discord Developer Portal](https://discord.com/developers/applications). Copy
@@ -220,7 +221,7 @@ Some types have additional optional fields that control acceptable values.
220221
<!-- prettier-ignore-start -->
221222
```tsx
222223
import { ChannelType } from "slshx";
223-
import type { APIUser, APIInteractionDataResolvedChannel, APIRole } from "discord-api-types/v9";
224+
import type { APIUser, APIInteractionDataResolvedChannel, APIRole, APIAttachment } from "discord-api-types/v9";
224225

225226
function cmd(): CommandHandler {
226227
useDescription("Command demonstrating option types");
@@ -256,6 +257,9 @@ function cmd(): CommandHandler {
256257
const n1 = useNumber("name", "Description");
257258
// └ number | null
258259
const n2 = useNumber("name", "Description", { min: 5, max: 100 });
260+
261+
const a = useAttachment("name", "Description");
262+
// └ APIAttachment | null
259263

260264
return () => {}; // ...
261265
};
@@ -347,6 +351,11 @@ function cover(): CommandHandler<Env> {
347351
}
348352
```
349353

354+
> ⚠️ Discord does not include full user, channel, role, mentionable or
355+
> attachment objects in autocomplete interactions. If a user specifies a value
356+
> for one of these options, the hook will return a partial object of the form
357+
> `{ id: "..." }` instead.
358+
350359
### Subcommands
351360

352361
Discord supports grouping chat commands into
@@ -1144,6 +1153,115 @@ function selects(): CommandHandler {
11441153

11451154
![Select Menu](./.github/screenshots/select.png)
11461155

1156+
## Using Modals
1157+
1158+
[Modals](https://discord.com/developers/docs/interactions/receiving-and-responding#responding-to-an-interaction)
1159+
allow you to respond to commands or message component interactions with dialog
1160+
boxes containing text inputs. Instead of returning a `<Message>`, return a
1161+
`<Modal>` or a plain message object with the `[$modal]` property set to `true`.
1162+
1163+
To generate a custom modal ID including the required Slshx routing information,
1164+
call the `useModal` hook. This takes a callback function taking an
1165+
`interaction`, `env`, and `ctx` that will be called when the modal is submitted.
1166+
1167+
To add text inputs, call the `useInput` hook. This returns an `[id, value]`
1168+
tuple containing a custom ID to identify the input and the submitted value. Note
1169+
that the `value` should only be used inside `useModal` callback functions.
1170+
1171+
<!-- prettier-ignore-start -->
1172+
```tsx
1173+
import { CommandHandler, useInput, useModal, createElement, Message, Modal, Input, $modal, ComponentType, TextInputStyle } from "slshx";
1174+
1175+
export function modals(): CommandHandler<Env> {
1176+
// ...
1177+
const [nameId, nameValue] = useInput();
1178+
const [messageId, messageValue] = useInput();
1179+
const modalId = useModal<Env>((interaction, env, ctx) => {
1180+
// └ APIModalSubmitInteraction
1181+
1182+
// With JSX
1183+
return <Message>Hello {nameValue}! {messageValue}</Message>;
1184+
1185+
// Without JSX
1186+
return { content: `Hello ${nameValue}! ${messageValue}` };
1187+
});
1188+
1189+
return () => {
1190+
// With JSX
1191+
return (
1192+
<Modal id={modalId} title="Send Message">
1193+
<Input
1194+
id={nameId} // Only `id` and `label` are required
1195+
label="Name"
1196+
required
1197+
value="Initial value"
1198+
minLength={1}
1199+
/>
1200+
<Input
1201+
id={messageId}
1202+
label="Message"
1203+
placeholder="Something to send"
1204+
maxLength={1000}
1205+
paragraph // Multiline input
1206+
/>
1207+
</Modal>
1208+
);
1209+
1210+
// Without JSX
1211+
return {
1212+
[$modal]: true,
1213+
custom_id: modalId,
1214+
title: "Send Message",
1215+
components: [
1216+
{
1217+
type: ComponentType.ACTION_ROW,
1218+
components: [
1219+
{
1220+
type: ComponentType.TEXT_INPUT,
1221+
style: TextInputStyle.SHORT,
1222+
custom_id: nameId,
1223+
label: "Name",
1224+
required: true,
1225+
value: "Initial value",
1226+
min_length: 1,
1227+
},
1228+
],
1229+
},
1230+
{
1231+
type: ComponentType.ACTION_ROW,
1232+
components: [
1233+
{
1234+
type: ComponentType.TEXT_INPUT,
1235+
style: TextInputStyle.PARAGRAPH,
1236+
custom_id: messageId,
1237+
label: "Message",
1238+
placeholder: "Something to send",
1239+
required: false, // Inputs are required by default
1240+
max_length: 1000,
1241+
},
1242+
],
1243+
},
1244+
],
1245+
};
1246+
};
1247+
}
1248+
```
1249+
<!-- prettier-ignore-end -->
1250+
1251+
![Modal](./.github/screenshots/modal.png)
1252+
1253+
![Modal Submission](./.github/screenshots/modal-submit.png)
1254+
1255+
## Errors
1256+
1257+
During development, if a command, message component, or modal submission handler
1258+
throws an error, Slshx will respond with the message and stack trace. In
1259+
production, the interaction will fail.
1260+
1261+
![Development Error](./.github/screenshots/error-development.png)
1262+
1263+
![Production Error](./.github/screenshots/error-production.png)
1264+
11471265
## Deploying Commands Globally
11481266

11491267
Once you're happy with your commands, you can deploy them globally, making them
@@ -1273,9 +1391,11 @@ If an API does not have Slshx bindings, you can use the
12731391
`URLSearchParams` (sent as `application/x-www-form-urlencoded`), or an
12741392
arbitrary JSON-serializable object (sent as `application/json`). If `body` is
12751393
falsy, it's omitted.
1276-
- `auth` can be an object of the form `{ bearer: string }` (what `getBearerAuth`
1277-
returns) to use `Bearer` token authentication, or
1278-
`{ username: string; password: string }` to use HTTP `Basic` authentication
1394+
- `auth` can be an object of the form:
1395+
- `{ bearer: string }` (what `getBearerAuth` returns) to use `Bearer` token
1396+
authentication
1397+
- `{ username: string; password: string }` to use HTTP `Basic` authentication
1398+
- `{ bot: string }` to use `Bot` token authentication
12791399

12801400
This function is generic in `Body` and `Result`. You can find types for these in
12811401
the `discord-api-types` package. See [`src/api/`](./src/api) for examples of

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "slshx",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"description": "Strongly-typed Discord commands on Cloudflare Workers",
55
"type": "module",
66
"exports": "./dist/src/index.js",

src/jsx/components/Input.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export function Input(
2626
value: props.value,
2727
min_length: props.minLength,
2828
max_length: props.maxLength,
29-
required: props.required,
29+
// `required` defaults to true, so explicitly set to false if falsy
30+
required: !!props.required,
3031
};
3132
}

test/jsx/Modal.spec.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ test("creates modal", (t) => {
6565
value: undefined,
6666
min_length: undefined,
6767
max_length: undefined,
68-
required: undefined,
68+
required: false,
6969
},
7070
],
7171
},

0 commit comments

Comments
 (0)