@saykit/carbon 0.9.1 → 0.11.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,7 +4,7 @@
4
4
 
5
5
  [![Coverage](https://codecov.io/gh/k0d13/saykit/graph/badge.svg?flag=integration-carbon)](https://codecov.io/gh/k0d13/saykit?flags%5B0%5D=integration-carbon)
6
6
 
7
- Registers a shared `Say` with your Carbon client, helps command and component classes expose translated metadata, and adds locale-aware `interaction.say` and `guild.say` properties.
7
+ Registers a shared catalogue with your Carbon client, helps command and component classes expose translated metadata, and adds locale-aware `interaction.say` and `guild.say` properties.
8
8
 
9
9
  ## Install
10
10
 
@@ -16,13 +16,12 @@ pnpm add @saykit/carbon saykit @buape/carbon
16
16
 
17
17
  ```ts
18
18
  import { Client, Command, type CommandInteraction } from '@buape/carbon';
19
- import { SayPlugin, withSay } from '@saykit/carbon';
20
- import { type Say } from 'saykit';
21
- import say from './i18n.js';
19
+ import { SayPlugin } from '@saykit/carbon';
20
+ import { catalogue, withSay } from './i18n.js';
22
21
 
23
22
  class PingCommand extends withSay(Command) {
24
- constructor(say: Say) {
25
- super(say, (say) => ({
23
+ constructor() {
24
+ super((say) => ({
26
25
  name: say`ping`,
27
26
  description: say`Ping the bot!`,
28
27
  }));
@@ -33,8 +32,8 @@ class PingCommand extends withSay(Command) {
33
32
  }
34
33
  }
35
34
 
36
- const client = new Client({/* options */}, { commands: [new PingCommand(say)] }, [
37
- new SayPlugin(say),
35
+ const client = new Client({/* options */}, { commands: [new PingCommand()] }, [
36
+ new SayPlugin(catalogue),
38
37
  ]);
39
38
  ```
40
39
 
package/dist/index.d.mts CHANGED
@@ -1,13 +1,9 @@
1
1
  import { APIInteraction, BaseCommand, BaseComponent, Modal, Plugin } from "@buape/carbon";
2
- import { Say } from "saykit";
3
- //#region src/constants.d.ts
4
- declare const kSay: unique symbol;
5
- //#endregion
2
+ import { Catalogue, View } from "saykit";
6
3
  //#region src/extensions/base-interaction.d.ts
7
4
  declare module '@buape/carbon' {
8
5
  interface BaseInteraction<T extends APIInteraction> {
9
- get say(): Say;
10
- [kSay]: Say;
6
+ get say(): View;
11
7
  }
12
8
  }
13
9
  declare function applyBaseInteractionExtension(): () => void;
@@ -15,8 +11,7 @@ declare function applyBaseInteractionExtension(): () => void;
15
11
  //#region src/extensions/guild.d.ts
16
12
  declare module '@buape/carbon' {
17
13
  interface Guild {
18
- get say(): Say;
19
- [kSay]: Say;
14
+ get say(): View;
20
15
  }
21
16
  }
22
17
  declare function applyGuildExtension(): () => void;
@@ -25,40 +20,70 @@ declare function applyGuildExtension(): () => void;
25
20
  type Keys = 'name' | 'description' | 'label' | 'title' | 'placeholder' | 'content' | 'options' | 'components' | 'subcommands' | 'subcommandGroups';
26
21
  type AbstractConstructor<Args extends any[] = any[], Instance extends object = object> = abstract new (...args: Args) => Instance;
27
22
  type SayProps<T> = Pick<T, Extract<keyof T, Keys>>;
23
+ interface WithSay {
24
+ /**
25
+ * Enhances a {@link BaseCommand} subclass with support for localisation.
26
+ *
27
+ * @param Base Abstract command constructor to extend.
28
+ * @returns A new constructor that accepts a properties-mapping function and
29
+ * the original constructor arguments.
30
+ */
31
+ <Args extends unknown[], Instance extends BaseCommand>(Base: AbstractConstructor<Args, Instance>): AbstractConstructor<[properties: (say: View) => SayProps<Instance>, ...args: Args], Instance & Partial<Record<Keys, unknown>>>;
32
+ /**
33
+ * Enhances a {@link BaseComponent} or {@link Modal} subclass with
34
+ * support for localisation.
35
+ *
36
+ * @param Base Abstract component or modal constructor to extend.
37
+ * @returns A new constructor that accepts a set of properties.
38
+ */
39
+ <Args extends unknown[], Instance extends BaseComponent | Modal>(Base: AbstractConstructor<Args, Instance>): AbstractConstructor<[properties: SayProps<Instance>, ...args: Args], Instance & Partial<Record<Keys, unknown>>>;
40
+ }
28
41
  /**
29
- * Enhances a {@link BaseCommand} subclass with support for localisation.
42
+ * Bind a `withSay` to a {@link Catalogue}, normally once beside the catalogue
43
+ * itself.
30
44
  *
31
- * @param Base Abstract command constructor to extend.
32
- * @returns A new constructor that accepts a {@link Say} instance, a
33
- * properties-mapping function, and the original constructor arguments.
34
- */
35
- declare function withSay<Args extends unknown[], Instance extends BaseCommand>(Base: AbstractConstructor<Args, Instance>): AbstractConstructor<[say: Say, properties: (say: Say) => SayProps<Instance>, ...args: Args], Instance & Partial<Record<Keys, unknown>>>;
36
- /**
37
- * Enhances a {@link BaseComponent} or {@link Modal} subclass with
38
- * support for localisation.
45
+ * `withSay` wraps a Carbon base class so a command's name, description and
46
+ * options are built once per locale in the catalogue and registered with
47
+ * Discord as localisations, without the command having to reach for the
48
+ * catalogue itself.
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * // i18n.ts
53
+ * export const withSay = createWithSay(catalogue);
54
+ *
55
+ * // commands/pick.ts
56
+ * export class PickCommand extends withSay(Command) {
57
+ * constructor() {
58
+ * super((say) => ({ name: say`pick`, description: say`What we are reading.` }));
59
+ * }
60
+ * }
61
+ * ```
39
62
  *
40
- * @param Base Abstract component or modal constructor to extend.
41
- * @returns A new constructor that accepts a set of properties.
63
+ * @param catalogue The catalogue to take views from
64
+ * @returns A `withSay` bound to that catalogue
65
+ * @throws If the base class is neither a {@link BaseCommand} nor a
66
+ * {@link BaseComponent}
42
67
  */
43
- declare function withSay<Args extends unknown[], Instance extends BaseComponent | Modal>(Base: AbstractConstructor<Args, Instance>): AbstractConstructor<[properties: SayProps<Instance>, ...args: Args], Instance & Partial<Record<Keys, unknown>>>;
68
+ declare function createWithSay(catalogue: Catalogue): WithSay;
44
69
  //#endregion
45
70
  //#region src/plugin.d.ts
46
71
  /**
47
- * A Carbon plugin that provides a singleton {@link Say} instance.
72
+ * A Carbon plugin that provides a singleton {@link Catalogue}.
48
73
  *
49
- * `SayPlugin` registers a {@link Say} instance globally and
50
- * applies interaction and guild-level extensions so that commands and
51
- * other handlers can access localisation utilities directly.
74
+ * `SayPlugin` registers a {@link Catalogue} globally and applies interaction and
75
+ * guild-level extensions, so that commands and other handlers can reach a view
76
+ * for their own locale directly.
52
77
  *
53
78
  * @example
54
79
  * ```ts
55
- * const say = new Say({ ... });
56
- * const client = new Client({ ... }, { ... }, [new SayPlugin(say)]);
80
+ * const catalogue = createCatalogue({ ... });
81
+ * const client = new Client({ ... }, { ... }, [new SayPlugin(catalogue)]);
57
82
  * ```
58
83
  */
59
84
  declare class SayPlugin extends Plugin {
60
85
  id: string;
61
- constructor(say: Say);
86
+ constructor(catalogue: Catalogue);
62
87
  }
63
88
  //#endregion
64
- export { SayPlugin, type applyBaseInteractionExtension, type applyGuildExtension, withSay };
89
+ export { SayPlugin, type applyBaseInteractionExtension, type applyGuildExtension, createWithSay };
package/dist/index.mjs CHANGED
@@ -21,29 +21,31 @@ function combineCommandOptions(mappedOptions, baseLocale) {
21
21
  }
22
22
  //#endregion
23
23
  //#region src/mixers/with-say.ts
24
- const ClassMap = /* @__PURE__ */ new WeakMap();
25
- function withSay(Base) {
26
- if (ClassMap.has(Base)) return ClassMap.get(Base);
27
- if (Base.prototype instanceof BaseCommand) {
28
- const Derived = createSayCommand(Base);
29
- ClassMap.set(Base, Derived);
30
- return Derived;
31
- }
32
- if (Base.prototype instanceof BaseComponent || Base === Modal) {
33
- const Derived = createSayComponent(Base);
34
- ClassMap.set(Base, Derived);
35
- return Derived;
36
- }
37
- throw new Error("Invalid base class");
24
+ function createWithSay(catalogue) {
25
+ const cache = /* @__PURE__ */ new WeakMap();
26
+ return function withSay(Base) {
27
+ if (cache.has(Base)) return cache.get(Base);
28
+ if (Base.prototype instanceof BaseCommand) {
29
+ const Derived = createSayCommand(catalogue, Base);
30
+ cache.set(Base, Derived);
31
+ return Derived;
32
+ }
33
+ if (Base.prototype instanceof BaseComponent || Base === Modal) {
34
+ const Derived = createSayComponent(Base);
35
+ cache.set(Base, Derived);
36
+ return Derived;
37
+ }
38
+ throw new Error("Invalid base class");
39
+ };
38
40
  }
39
- function createSayCommand(Base) {
41
+ function createSayCommand(catalogue, Base) {
40
42
  class SayCommand extends Base {
41
- constructor(say, properties, ...args) {
43
+ constructor(properties, ...args) {
42
44
  super(...args);
43
- const options = combineCommandOptions(Array.from(say).reduce((acc, [s, l]) => {
44
- acc[l] = properties(s);
45
+ const options = combineCommandOptions(Array.from(catalogue).reduce((acc, [locale, say]) => {
46
+ acc[locale] = properties(say);
45
47
  return acc;
46
- }, {}), say.locale);
48
+ }, {}), catalogue.locales[0]);
47
49
  Object.assign(this, options);
48
50
  }
49
51
  }
@@ -65,12 +67,9 @@ const kSay = Symbol.for("saykit.say");
65
67
  //#region src/extensions/base-interaction.ts
66
68
  function applyBaseInteractionExtension() {
67
69
  Object.defineProperty(BaseInteraction.prototype, "say", { get() {
68
- const say = Reflect.get(globalThis, kSay);
69
- if (!say) throw new Error("No `say` instance available");
70
- this[kSay] ??= say.clone();
71
- const locale = this[kSay].match([this.rawData.locale]);
72
- this[kSay].activate(locale);
73
- return this[kSay];
70
+ const catalogue = Reflect.get(globalThis, kSay);
71
+ if (!catalogue) throw new Error("No catalogue registered, add SayPlugin to your Carbon client");
72
+ return catalogue.locale(catalogue.match([this.rawData.locale]));
74
73
  } });
75
74
  return () => {
76
75
  Object.defineProperty(BaseInteraction.prototype, "say", { value: void 0 });
@@ -80,12 +79,9 @@ function applyBaseInteractionExtension() {
80
79
  //#region src/extensions/guild.ts
81
80
  function applyGuildExtension() {
82
81
  Object.defineProperty(Guild.prototype, "say", { get() {
83
- const say = Reflect.get(globalThis, kSay);
84
- if (!say) throw new Error("No `say` instance available");
85
- this[kSay] ??= say.clone();
86
- const locale = this[kSay].match([this.rawData.preferred_locale]);
87
- this[kSay].activate(locale);
88
- return this[kSay];
82
+ const catalogue = Reflect.get(globalThis, kSay);
83
+ if (!catalogue) throw new Error("No catalogue registered, add SayPlugin to your Carbon client");
84
+ return catalogue.locale(catalogue.match([this.rawData.preferred_locale]));
89
85
  } });
90
86
  return () => {
91
87
  Object.defineProperty(Guild.prototype, "say", { value: void 0 });
@@ -95,12 +91,12 @@ function applyGuildExtension() {
95
91
  //#region src/plugin.ts
96
92
  var SayPlugin = class extends Plugin {
97
93
  id = "saykit";
98
- constructor(say) {
94
+ constructor(catalogue) {
99
95
  super();
100
- Reflect.set(globalThis, kSay, say);
96
+ Reflect.set(globalThis, kSay, catalogue);
101
97
  applyBaseInteractionExtension();
102
98
  applyGuildExtension();
103
99
  }
104
100
  };
105
101
  //#endregion
106
- export { SayPlugin, withSay };
102
+ export { SayPlugin, createWithSay };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@saykit/carbon",
3
- "version": "0.9.1",
3
+ "version": "0.11.0",
4
4
  "description": "Carbon Discord framework integration for saykit",
5
5
  "keywords": [
6
6
  "bot",
@@ -37,7 +37,7 @@
37
37
  },
38
38
  "devDependencies": {
39
39
  "@buape/carbon": "0.16.0",
40
- "saykit": "^0.9.1"
40
+ "saykit": "^0.11.0"
41
41
  },
42
42
  "peerDependencies": {
43
43
  "@buape/carbon": "*",