abseil 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,55 +4,67 @@ Quickly traverse Discord [Components V2](https://docs.discord.com/developers/com
4
4
 
5
5
  ## Reference
6
6
 
7
- | function | description |
8
- | --------- | ----------------------------------------------------------------------------------------------------- |
9
- | accessory | Access the accessory of a [Section](https://docs.discord.com/developers/components/reference#section) |
10
- | child | Access the first child of a node |
11
- | previous | Return to the previous node |
12
- | sibling | Access the next node in an array |
13
- | update | Shallow merge with the current component in place |
14
- | value | The current component |
7
+ | function | description |
8
+ | ------------ | ----------------------------------------------------------------------------------------------------- |
9
+ | accessory | Access the accessory of a [Section](https://docs.discord.com/developers/components/reference#section) |
10
+ | child | Access the first child of a node |
11
+ | insertBefore | Insert a sibling before the current node |
12
+ | last | Jump to the last neighbouring node of a type in an array |
13
+ | next | Jump to the next neighbouring node of a type in an array |
14
+ | previous | Return to the previous node |
15
+ | sibling | Access the next node in an array |
16
+ | update | Shallow merge with the current component in place |
17
+ | value | The current component |
15
18
 
16
19
  ## Example
17
20
 
21
+ <details>
22
+ <summary>Sample message definition</summary>
23
+
18
24
  ```ts
19
- import { type APIMessage, ComponentType } from "discord-api-types/v10";
20
- import { Button, editMessage } from "dressed";
21
- import abseil from "abseil";
25
+ import type { APIMessage } from "discord-api-types/v10";
26
+ import { ActionRow, Button, Container, Section, Separator, TextDisplay } from "dressed";
22
27
 
23
28
  const message = {
24
29
  components: [
25
- { type: ComponentType.TextDisplay },
26
- {
27
- type: ComponentType.Container,
28
- components: [
29
- {
30
- type: ComponentType.Section,
31
- accessory: { type: ComponentType.Thumbnail },
32
- components: [{ type: ComponentType.TextDisplay }, { type: ComponentType.TextDisplay }],
33
- },
34
- { type: ComponentType.Separator },
35
- { type: ComponentType.ActionRow, components: [{ type: ComponentType.UserSelect }] },
36
- ],
37
- },
38
- {
39
- type: ComponentType.ActionRow,
40
- components: [{ type: ComponentType.Button }, { type: ComponentType.Button }],
41
- },
30
+ Container(
31
+ Section(["## Trivia!"], Button({ custom_id: "suggest", style: "Secondary" })),
32
+ TextDisplay("What is the meaning of life?"),
33
+ ActionRow(
34
+ Button({ custom_id: "money", label: "💵" }),
35
+ Button({ custom_id: "42", label: "🤖" }),
36
+ ),
37
+ Separator(),
38
+ Section(["## 🟩🟩🟥🟥🟥⬛⬛⬛⬛⬛"], Button({ custom_id: "stats", style: "Secondary" })),
39
+ ),
42
40
  ],
43
41
  } as APIMessage;
42
+ ```
43
+
44
+ </details>
45
+
46
+ ```ts
47
+ import abseil from "abseil";
48
+ import { editMessage } from "dressed";
49
+
50
+ const section = abseil(message.components ?? [])
51
+ .initial("Container")
52
+ .child("Section");
53
+
54
+ let button = section.next("ActionRow")?.child("Button");
55
+
56
+ while (button) {
57
+ button.update({ disabled: true });
58
+ // The last item in an array does not have a sibling function
59
+ button = button.sibling?.("Button");
60
+ }
61
+
62
+ // Insert-if-not-exists the warning message
63
+ if (section.last("TextDisplay")?.sibling) {
64
+ section.previous.update((prev) => ({
65
+ components: prev.components.concat(TextDisplay("-# This has expired!")),
66
+ }));
67
+ }
44
68
 
45
- abseil(message.components ?? [])
46
- .initial("TextDisplay")
47
- .sibling("Container")
48
- .update({ spoiler: true })
49
- .sibling("ActionRow")
50
- .update((p) => ({
51
- components: p.components.concat(Button({ custom_id: "new", label: "I'm new!" })),
52
- }))
53
- .previous.child("Section")
54
- .accessory(["Button", "Thumbnail"])
55
- .update({ id: 32 });
56
-
57
- editMessage("<CHANNEL_ID>", "<MESSAGE_ID>", message.components);
69
+ editMessage("<CHANNEL_ID>", "<MESSAGE_ID>", { components: message.components });
58
70
  ```
package/dist/index.d.ts CHANGED
@@ -33,6 +33,14 @@ type Traverser<T extends keyof CT, H extends (keyof CT)[], ST extends keyof CT =
33
33
  /** The current component */
34
34
  value: Component<T>;
35
35
  } & (T extends IComponentType[APISelectMenuComponent["type"]] ? object : {
36
+ /** Insert a sibling before the current node */
37
+ insertBefore: (component: Extract<APIMessageComponent, {
38
+ type: (typeof ComponentType)[Exclude<ST, "Button:URL" | "Button:SKU">];
39
+ }>) => Traverser<T, H, ST>;
40
+ /** Jump to the last neighbouring node of a type in an array */
41
+ last: <const N extends Arrable<ST>>(type: N) => Traverser<Narr<N>, [...H, T], ST> | undefined;
42
+ /** Jump to the next neighbouring node of a type in an array */
43
+ next: <const N extends Arrable<ST>>(type: N) => Traverser<Narr<N>, [...H, T], ST> | undefined;
36
44
  /** Access the next node in an array */
37
45
  sibling: TraverserFn<ST, [...H, T]>;
38
46
  }) & (T extends keyof ChildrenMap ? {
@@ -46,7 +54,7 @@ type Traverser<T extends keyof CT, H extends (keyof CT)[], ST extends keyof CT =
46
54
  previous: Traverser<Last<H>, Pop<H>>;
47
55
  });
48
56
  /** Initiate a tree traverser */
49
- declare const abseil: <T extends APIMessageComponent>(components: readonly T[]) => {
57
+ declare const abseil: <T extends APIMessageComponent>(components: T[]) => {
50
58
  initial: TraverserFn<IComponentType[T["type"]], [], "previous">;
51
59
  };
52
60
  export default abseil;
package/dist/index.js CHANGED
@@ -1,8 +1,18 @@
1
1
  /** biome-ignore-all lint/suspicious/noExplicitAny: Not worth my time */
2
2
  import { ComponentType, } from "discord-api-types/v10";
3
3
  const withChildren = new Set([ComponentType.ActionRow, ComponentType.Section, ComponentType.Container]);
4
- function createTraverser(component, expected, previous, siblings) {
5
- const expectedTypes = new Set(Array.isArray(expected) ? expected : [expected]);
4
+ const selects = new Set([
5
+ ComponentType.StringSelect,
6
+ ComponentType.UserSelect,
7
+ ComponentType.RoleSelect,
8
+ ComponentType.MentionableSelect,
9
+ ComponentType.ChannelSelect,
10
+ ]);
11
+ function matchTypes(component, expected, doNotThrow) {
12
+ const expectedTypes = new Set((Array.isArray(expected) ? expected : [expected]).filter(Boolean));
13
+ if (!expectedTypes.size) {
14
+ throw new Error("Selectors must specify expected type(s)");
15
+ }
6
16
  let actualType = ComponentType[component.type];
7
17
  if (actualType === "Button") {
8
18
  if ("url" in component)
@@ -11,8 +21,15 @@ function createTraverser(component, expected, previous, siblings) {
11
21
  actualType += ":SKU";
12
22
  }
13
23
  if (!expectedTypes.has(actualType)) {
14
- throw new TypeError(`Type mismatch: expected ${[...expectedTypes].join(" or ")}, got ${actualType}`);
24
+ if (!doNotThrow) {
25
+ throw new TypeError(`Type mismatch: expected ${[...expectedTypes].join(" or ")}, got ${actualType}`);
26
+ }
27
+ return false;
15
28
  }
29
+ return true;
30
+ }
31
+ function createTraverser(component, expected, previous, neighbours) {
32
+ matchTypes(component, expected);
16
33
  const traverser = {
17
34
  value: component,
18
35
  update(v) {
@@ -22,11 +39,34 @@ function createTraverser(component, expected, previous, siblings) {
22
39
  };
23
40
  if (previous)
24
41
  traverser.previous = previous;
25
- if (siblings === null || siblings === void 0 ? void 0 : siblings.length) {
26
- traverser.sibling = (t) => createTraverser(siblings[0], t, traverser, siblings.slice(1));
42
+ if (neighbours) {
43
+ if (!selects.has(component.type)) {
44
+ traverser.insertBefore = (v) => {
45
+ neighbours.splice(neighbours.indexOf(component), 0, v);
46
+ return traverser;
47
+ };
48
+ traverser.last = (t) => {
49
+ for (let i = neighbours.length - 1; i >= 0; --i) {
50
+ const sibling = neighbours[i];
51
+ if (!matchTypes(sibling, t, true))
52
+ continue;
53
+ return createTraverser(sibling, t, traverser, neighbours);
54
+ }
55
+ return undefined;
56
+ };
57
+ traverser.next = (t) => {
58
+ const next = neighbours.slice(neighbours.indexOf(component) + 1).find((s) => matchTypes(s, t, true));
59
+ if (!next)
60
+ return undefined;
61
+ return createTraverser(next, t, traverser, neighbours);
62
+ };
63
+ }
64
+ if (neighbours.length !== neighbours.indexOf(component) + 1) {
65
+ traverser.sibling = (t) => createTraverser(neighbours[neighbours.indexOf(component) + 1], t, traverser, neighbours);
66
+ }
27
67
  }
28
68
  if (withChildren.has(component.type) && "components" in component) {
29
- traverser.child = (t) => createTraverser(component.components[0], t, traverser, component.components.slice(1));
69
+ traverser.child = (t) => createTraverser(component.components[0], t, traverser, component.components);
30
70
  }
31
71
  if (component.type === ComponentType.Section) {
32
72
  traverser.accessory = (t) => createTraverser(component.accessory, t, traverser);
@@ -35,7 +75,7 @@ function createTraverser(component, expected, previous, siblings) {
35
75
  }
36
76
  /** Initiate a tree traverser */
37
77
  const abseil = (components) => ({
38
- initial: ((t) => createTraverser(components[0], t, undefined, components.slice(1))),
78
+ initial: ((t) => createTraverser(components[0], t, undefined, components)),
39
79
  });
40
80
  export default abseil;
41
81
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAML,aAAa,GACd,MAAM,uBAAuB,CAAC;AAmE/B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;AAExG,SAAS,eAAe,CACtB,SAAY,EACZ,QAA2B,EAC3B,QAA4C,EAC5C,QAAgC;IAEhC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/E,IAAI,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,KAAK,IAAI,SAAS;YAAE,UAAU,IAAI,MAAM,CAAC;aACxC,IAAI,QAAQ,IAAI,SAAS;YAAE,UAAU,IAAI,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACvG,CAAC;IACD,MAAM,SAAS,GAAQ;QACrB,KAAK,EAAE,SAAS;QAChB,MAAM,CAAC,CAAkC;YACvC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrE,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;IACF,IAAI,QAAQ;QAAE,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC5C,IAAI,QAAQ,aAAR,QAAQ,uBAAR,QAAQ,CAAE,MAAM,EAAE,CAAC;QACrB,SAAS,CAAC,OAAO,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnG,CAAC;IACD,IAAI,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;QAClE,SAAS,CAAC,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAC9B,eAAe,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC1F,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,CAAC,OAAO,EAAE,CAAC;QAC7C,SAAS,CAAC,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gCAAgC;AAChC,MAAM,MAAM,GAAG,CAAgC,UAAwB,EAAE,EAAE,CAAC,CAAC;IAC3E,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAIjF;CACF,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,OAAO,EAML,aAAa,GACd,MAAM,uBAAuB,CAAC;AA8E/B,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,CAAC,aAAa,CAAC,SAAS,EAAE,aAAa,CAAC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC,CAAC;AAExG,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC;IACtB,aAAa,CAAC,YAAY;IAC1B,aAAa,CAAC,UAAU;IACxB,aAAa,CAAC,UAAU;IACxB,aAAa,CAAC,iBAAiB;IAC/B,aAAa,CAAC,aAAa;CAC5B,CAAC,CAAC;AAEH,SAAS,UAAU,CAAC,SAA8B,EAAE,QAA2B,EAAE,UAAoB;IACnG,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC;IACjG,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IACD,IAAI,UAAU,GAAG,aAAa,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,UAAU,KAAK,QAAQ,EAAE,CAAC;QAC5B,IAAI,KAAK,IAAI,SAAS;YAAE,UAAU,IAAI,MAAM,CAAC;aACxC,IAAI,QAAQ,IAAI,SAAS;YAAE,UAAU,IAAI,MAAM,CAAC;IACvD,CAAC;IACD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC;QACnC,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,SAAS,CAAC,2BAA2B,CAAC,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;QACvG,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,eAAe,CACtB,SAAY,EACZ,QAA2B,EAC3B,QAA4C,EAC5C,UAAkC;IAElC,UAAU,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;IAChC,MAAM,SAAS,GAAQ;QACrB,KAAK,EAAE,SAAS;QAChB,MAAM,CAAC,CAAkC;YACvC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACrE,OAAO,SAAS,CAAC;QACnB,CAAC;KACF,CAAC;IACF,IAAI,QAAQ;QAAE,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC5C,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,SAAS,CAAC,YAAY,GAAG,CAAC,CAAsB,EAAE,EAAE;gBAClD,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,SAAkB,CAAC,EAAE,CAAC,EAAE,CAAU,CAAC,CAAC;gBACzE,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC;YACF,SAAS,CAAC,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;gBAC7B,KAAK,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;oBAChD,MAAM,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;oBAC9B,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,EAAE,IAAI,CAAC;wBAAE,SAAS;oBAC5C,OAAO,eAAe,CAAC,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;gBAC5D,CAAC;gBACD,OAAO,SAAS,CAAC;YACnB,CAAC,CAAC;YACF,SAAS,CAAC,IAAI,GAAG,CAAC,CAAS,EAAE,EAAE;gBAC7B,MAAM,IAAI,GAAG,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;gBACrG,IAAI,CAAC,IAAI;oBAAE,OAAO,SAAS,CAAC;gBAC5B,OAAO,eAAe,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;YACzD,CAAC,CAAC;QACJ,CAAC;QACD,IAAI,UAAU,CAAC,MAAM,KAAK,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC;YAC5D,SAAS,CAAC,OAAO,GAAG,CAAC,CAAS,EAAE,EAAE,CAChC,eAAe,CAAC,UAAU,CAAC,UAAU,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IACD,IAAI,YAAY,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,YAAY,IAAI,SAAS,EAAE,CAAC;QAClE,SAAS,CAAC,KAAK,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,SAAS,CAAC,UAAU,CAAC,CAAC;IAChH,CAAC;IACD,IAAI,SAAS,CAAC,IAAI,KAAK,aAAa,CAAC,OAAO,EAAE,CAAC;QAC7C,SAAS,CAAC,SAAS,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,SAAS,EAAE,CAAC,EAAE,SAAS,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,gCAAgC;AAChC,MAAM,MAAM,GAAG,CAAgC,UAAe,EAAE,EAAE,CAAC,CAAC;IAClE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,SAAS,EAAE,UAAU,CAAC,CAIxE;CACF,CAAC,CAAC;AAEH,eAAe,MAAM,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "abseil",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Quickly traverse Discord Components V2 trees.",
5
5
  "scripts": {
6
6
  "dist": "rm -fr dist && tsc",
@@ -1 +0,0 @@
1
- export {};
@@ -1,131 +0,0 @@
1
- import { describe, expect, test } from "bun:test";
2
- import { ButtonStyle, ComponentType, } from "discord-api-types/v10";
3
- import abseil from "./index.js";
4
- const message = {
5
- components: [
6
- { type: ComponentType.TextDisplay },
7
- {
8
- type: ComponentType.Container,
9
- components: [
10
- {
11
- type: ComponentType.Section,
12
- accessory: { type: ComponentType.Thumbnail },
13
- components: [
14
- { type: ComponentType.TextDisplay },
15
- { type: ComponentType.TextDisplay },
16
- ],
17
- },
18
- { type: ComponentType.Separator },
19
- {
20
- type: ComponentType.ActionRow,
21
- components: [{ type: ComponentType.UserSelect }],
22
- },
23
- ],
24
- accent_color: 0,
25
- spoiler: false,
26
- },
27
- {
28
- type: ComponentType.ActionRow,
29
- components: [
30
- { type: ComponentType.Button, custom_id: "b1" },
31
- { type: ComponentType.Button, custom_id: "b2" },
32
- ],
33
- },
34
- ],
35
- };
36
- describe("abseil traverser", () => {
37
- test("should traverse initial component", () => {
38
- const t = abseil(message.components).initial("TextDisplay");
39
- expect(t.value.type).toBe(ComponentType.TextDisplay);
40
- });
41
- test("should traverse sibling component", () => {
42
- const t = abseil(message.components).initial("TextDisplay").sibling("Container");
43
- expect(t.value.type).toBe(ComponentType.Container);
44
- });
45
- test("should traverse child component", () => {
46
- const t = abseil(message.components).initial("TextDisplay").sibling("Container").child("Section");
47
- expect(t.value.type).toBe(ComponentType.Section);
48
- });
49
- test("should traverse accessory component", () => {
50
- const t = abseil(message.components)
51
- .initial("TextDisplay")
52
- .sibling("Container")
53
- .child("Section")
54
- .accessory("Thumbnail");
55
- expect(t.value.type).toBe(ComponentType.Thumbnail);
56
- });
57
- test("should return to previous component", () => {
58
- var _a;
59
- const t = abseil(message.components).initial("TextDisplay").sibling("Container");
60
- expect((_a = t.previous) === null || _a === void 0 ? void 0 : _a.value.type).toBe(ComponentType.TextDisplay);
61
- });
62
- test("should update component properties in-place", () => {
63
- const traverser = abseil(message.components).initial("TextDisplay").sibling("Container").update({ spoiler: true });
64
- expect(message.components[1].spoiler).toBe(true);
65
- expect(traverser.value.spoiler).toBe(true);
66
- });
67
- test("should update component using a function in-place", () => {
68
- const traverser = abseil(message.components)
69
- .initial("TextDisplay")
70
- .sibling("Container")
71
- .update((prev) => ({ ...prev, accent_color: 42 }));
72
- expect(message.components[1].accent_color).toBe(42);
73
- expect(traverser.value.accent_color).toBe(42);
74
- });
75
- test("should handle URL button type correctly", () => {
76
- const urlButton = {
77
- type: ComponentType.Button,
78
- url: "https://example.com",
79
- style: ButtonStyle.Link,
80
- };
81
- const t = abseil([urlButton]).initial("Button:URL");
82
- expect(t.value.url).toBe("https://example.com");
83
- });
84
- test("should handle SKU button type correctly", () => {
85
- const skuButton = {
86
- type: ComponentType.Button,
87
- sku_id: "sku-123",
88
- style: ButtonStyle.Premium,
89
- };
90
- const t = abseil([skuButton]).initial("Button:SKU");
91
- expect(t.value.sku_id).toBe("sku-123");
92
- });
93
- test("should throw when initial type does not match", () => {
94
- const btn = {
95
- type: ComponentType.Button,
96
- custom_id: "b1",
97
- style: ButtonStyle.Primary,
98
- };
99
- expect(() => abseil([btn]).initial("Button:URL")).toThrow(TypeError);
100
- });
101
- test("should traverse sibling components sequentially", () => {
102
- var _a;
103
- const traverser = abseil(message.components).initial("TextDisplay").sibling("Container").sibling("ActionRow");
104
- expect(traverser.value.type).toBe(ComponentType.ActionRow);
105
- expect((_a = traverser.previous) === null || _a === void 0 ? void 0 : _a.value.type).toBe(ComponentType.Container);
106
- });
107
- test("should allow adding new components via update", () => {
108
- const t = abseil(message.components)
109
- .initial("TextDisplay")
110
- .sibling("Container")
111
- .sibling("ActionRow")
112
- .update((prev) => ({
113
- components: prev.components.concat({
114
- type: ComponentType.Button,
115
- custom_id: "new",
116
- style: ButtonStyle.Primary,
117
- }),
118
- }));
119
- expect(message.components[2].components.length).toBe(3);
120
- expect(t.value.components[2].custom_id).toBe("new");
121
- });
122
- test("do not include child function if not a parent type", () => {
123
- const t = abseil([{ type: ComponentType.TextDisplay, content: "" }]);
124
- expect(t.initial("TextDisplay")).not.toHaveProperty("child");
125
- });
126
- test("do not include sibling function if no siblings", () => {
127
- const t = abseil([{ type: ComponentType.TextDisplay, content: "" }]);
128
- expect(t.initial("TextDisplay")).not.toHaveProperty("sibling");
129
- });
130
- });
131
- //# sourceMappingURL=index.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.test.js","sourceRoot":"","sources":["../src/index.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAClD,OAAO,EASL,WAAW,EACX,aAAa,GACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,MAAM,MAAM,YAAY,CAAC;AAEhC,MAAM,OAAO,GAAG;IACd,UAAU,EAAE;QACV,EAAE,IAAI,EAAE,aAAa,CAAC,WAAW,EAA6B;QAC9D;YACE,IAAI,EAAE,aAAa,CAAC,SAAS;YAC7B,UAAU,EAAE;gBACV;oBACE,IAAI,EAAE,aAAa,CAAC,OAAO;oBAC3B,SAAS,EAAE,EAAE,IAAI,EAAE,aAAa,CAAC,SAAS,EAA2B;oBACrE,UAAU,EAAE;wBACV,EAAE,IAAI,EAAE,aAAa,CAAC,WAAW,EAA6B;wBAC9D,EAAE,IAAI,EAAE,aAAa,CAAC,WAAW,EAA6B;qBAC/D;iBAC4B;gBAC/B,EAAE,IAAI,EAAE,aAAa,CAAC,SAAS,EAAE;gBACjC;oBACE,IAAI,EAAE,aAAa,CAAC,SAAS;oBAC7B,UAAU,EAAE,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,UAAU,EAA4B,CAAC;iBACnB;aAC1D;YACD,YAAY,EAAE,CAAW;YACzB,OAAO,EAAE,KAAgB;SACM;QACjC;YACE,IAAI,EAAE,aAAa,CAAC,SAAS;YAC7B,UAAU,EAAE;gBACV,EAAE,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAoC;gBACjF,EAAE,IAAI,EAAE,aAAa,CAAC,MAAM,EAAE,SAAS,EAAE,IAAI,EAAoC;aAClF;SAC8D;KACzD;CACX,CAAC;AAEF,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC;QAC5D,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACjF,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iCAAiC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QAClG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;aACjC,OAAO,CAAC,aAAa,CAAC;aACtB,OAAO,CAAC,WAAW,CAAC;aACpB,KAAK,CAAC,SAAS,CAAC;aAChB,SAAS,CAAC,WAAW,CAAC,CAAC;QAC1B,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,qCAAqC,EAAE,GAAG,EAAE;;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QACjF,MAAM,CAAC,MAAA,CAAC,CAAC,QAAQ,0CAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,6CAA6C,EAAE,GAAG,EAAE;QACvD,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAEnH,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7C,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,mDAAmD,EAAE,GAAG,EAAE;QAC7D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;aACzC,OAAO,CAAC,aAAa,CAAC;aACtB,OAAO,CAAC,WAAW,CAAC;aACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,IAAI,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QAErD,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACnD,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,aAAa,CAAC,MAAM;YAC1B,GAAG,EAAE,qBAAqB;YAC1B,KAAK,EAAE,WAAW,CAAC,IAAI;SACK,CAAC;QAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC;IAClD,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,yCAAyC,EAAE,GAAG,EAAE;QACnD,MAAM,SAAS,GAAG;YAChB,IAAI,EAAE,aAAa,CAAC,MAAM;YAC1B,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,WAAW,CAAC,OAAO;SACE,CAAC;QAC/B,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QACpD,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACzD,MAAM,GAAG,GAAG;YACV,IAAI,EAAE,aAAa,CAAC,MAAM;YAC1B,SAAS,EAAE,IAAI;YACf,KAAK,EAAE,WAAW,CAAC,OAAO;SACE,CAAC;QAC/B,MAAM,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,iDAAiD,EAAE,GAAG,EAAE;;QAC3D,MAAM,SAAS,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC;QAE9G,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;QAC3D,MAAM,CAAC,MAAA,SAAS,CAAC,QAAQ,0CAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACzD,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC;aACjC,OAAO,CAAC,aAAa,CAAC;aACtB,OAAO,CAAC,WAAW,CAAC;aACpB,OAAO,CAAC,WAAW,CAAC;aACpB,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YACjB,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;gBACjC,IAAI,EAAE,aAAa,CAAC,MAAM;gBAC1B,SAAS,EAAE,KAAK;gBAChB,KAAK,EAAE,WAAW,CAAC,OAAO;aAC3B,CAAC;SACH,CAAC,CAAC,CAAC;QACN,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxD,MAAM,CAAE,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,CAAoC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC1F,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC9D,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,gDAAgD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,CAAC,WAAW,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;QACrE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}