chapterjs 0.1.2 → 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.
Files changed (318) hide show
  1. package/dist/assets/asset.d.ts +46 -0
  2. package/dist/assets/asset.js +86 -0
  3. package/dist/assets/public.d.ts +19 -0
  4. package/dist/assets/public.js +120 -0
  5. package/dist/cache/cache.d.ts +62 -0
  6. package/dist/cache/cache.js +80 -0
  7. package/dist/cache/store.d.ts +45 -0
  8. package/dist/cache/store.js +53 -0
  9. package/dist/cli/build.d.ts +41 -0
  10. package/dist/cli/build.js +205 -0
  11. package/dist/cli/cli.js +108 -25
  12. package/dist/cli/cluster.d.ts +70 -0
  13. package/dist/cli/cluster.js +213 -0
  14. package/dist/cli/dev.d.ts +18 -1
  15. package/dist/cli/dev.js +253 -198
  16. package/dist/cli/env.d.ts +31 -0
  17. package/dist/cli/env.js +93 -0
  18. package/dist/cli/log.d.ts +13 -0
  19. package/dist/cli/log.js +17 -0
  20. package/dist/cli/node-version.d.ts +8 -0
  21. package/dist/cli/node-version.js +13 -0
  22. package/dist/cli/preflight.d.ts +36 -0
  23. package/dist/cli/preflight.js +122 -0
  24. package/dist/cli/project.d.ts +135 -0
  25. package/dist/cli/project.js +517 -0
  26. package/dist/cli/start.d.ts +25 -0
  27. package/dist/cli/start.js +225 -0
  28. package/dist/commands/autocomplete.d.ts +13 -0
  29. package/dist/commands/autocomplete.js +159 -0
  30. package/dist/commands/command.d.ts +360 -0
  31. package/dist/commands/command.js +28 -0
  32. package/dist/commands/declaration.d.ts +77 -0
  33. package/dist/commands/declaration.js +492 -0
  34. package/dist/commands/register.d.ts +18 -0
  35. package/dist/commands/register.js +42 -0
  36. package/dist/commands/router.d.ts +20 -0
  37. package/dist/commands/router.js +228 -0
  38. package/dist/commands/tree.d.ts +47 -0
  39. package/dist/commands/tree.js +216 -0
  40. package/dist/commands/twins.d.ts +15 -0
  41. package/dist/commands/twins.js +78 -0
  42. package/dist/components/button.d.ts +79 -0
  43. package/dist/components/button.js +106 -0
  44. package/dist/components/component.d.ts +140 -0
  45. package/dist/components/component.js +39 -0
  46. package/dist/components/custom-id.d.ts +72 -0
  47. package/dist/components/custom-id.js +128 -0
  48. package/dist/components/declaration.d.ts +42 -0
  49. package/dist/components/declaration.js +342 -0
  50. package/dist/components/declared.d.ts +29 -0
  51. package/dist/components/declared.js +49 -0
  52. package/dist/components/embed.d.ts +29 -0
  53. package/dist/components/embed.js +11 -0
  54. package/dist/components/instance.d.ts +100 -0
  55. package/dist/components/instance.js +86 -0
  56. package/dist/components/layout.d.ts +103 -0
  57. package/dist/components/layout.js +279 -0
  58. package/dist/components/modal.d.ts +245 -0
  59. package/dist/components/modal.js +398 -0
  60. package/dist/components/options.d.ts +41 -0
  61. package/dist/components/options.js +101 -0
  62. package/dist/components/render.d.ts +12 -0
  63. package/dist/components/render.js +58 -0
  64. package/dist/components/router.d.ts +19 -0
  65. package/dist/components/router.js +251 -0
  66. package/dist/components/select.d.ts +146 -0
  67. package/dist/components/select.js +179 -0
  68. package/dist/core/bot.d.ts +99 -0
  69. package/dist/core/bot.js +174 -0
  70. package/dist/core/memory.d.ts +66 -0
  71. package/dist/core/memory.js +115 -0
  72. package/dist/discord/api.d.ts +112 -0
  73. package/dist/discord/api.js +115 -0
  74. package/dist/discord/cdn.d.ts +67 -0
  75. package/dist/discord/cdn.js +100 -0
  76. package/dist/discord/codes.d.ts +171 -0
  77. package/dist/discord/codes.js +421 -0
  78. package/dist/discord/endpoint.d.ts +56 -0
  79. package/dist/discord/endpoint.js +53 -0
  80. package/dist/discord/endpoints.d.ts +1529 -0
  81. package/dist/discord/endpoints.js +1139 -0
  82. package/dist/discord/formatting.d.ts +67 -0
  83. package/dist/discord/formatting.js +87 -0
  84. package/dist/discord/index.d.ts +10 -0
  85. package/dist/discord/index.js +13 -0
  86. package/dist/discord/intents.d.ts +48 -0
  87. package/dist/discord/intents.js +128 -0
  88. package/dist/discord/permissions.d.ts +94 -0
  89. package/dist/discord/permissions.js +185 -0
  90. package/dist/discord/snowflake.d.ts +21 -0
  91. package/dist/discord/snowflake.js +36 -0
  92. package/dist/discord/types/application-command.d.ts +332 -0
  93. package/dist/discord/types/application-command.js +48 -0
  94. package/dist/discord/types/application-role-connection-metadata.d.ts +42 -0
  95. package/dist/discord/types/application-role-connection-metadata.js +22 -0
  96. package/dist/discord/types/application.d.ts +208 -0
  97. package/dist/discord/types/application.js +48 -0
  98. package/dist/discord/types/audit-log.d.ts +255 -0
  99. package/dist/discord/types/audit-log.js +144 -0
  100. package/dist/discord/types/auto-moderation.d.ts +167 -0
  101. package/dist/discord/types/auto-moderation.js +52 -0
  102. package/dist/discord/types/channel.d.ts +557 -0
  103. package/dist/discord/types/channel.js +88 -0
  104. package/dist/discord/types/common.d.ts +54 -0
  105. package/dist/discord/types/common.js +38 -0
  106. package/dist/discord/types/component.d.ts +775 -0
  107. package/dist/discord/types/component.js +76 -0
  108. package/dist/discord/types/emoji.d.ts +74 -0
  109. package/dist/discord/types/emoji.js +1 -0
  110. package/dist/discord/types/entitlement.d.ts +84 -0
  111. package/dist/discord/types/entitlement.js +22 -0
  112. package/dist/discord/types/gateway-events.d.ts +1148 -0
  113. package/dist/discord/types/gateway-events.js +54 -0
  114. package/dist/discord/types/gateway.d.ts +38 -0
  115. package/dist/discord/types/gateway.js +1 -0
  116. package/dist/discord/types/guild-scheduled-event.d.ts +257 -0
  117. package/dist/discord/types/guild-scheduled-event.js +68 -0
  118. package/dist/discord/types/guild-template.d.ts +51 -0
  119. package/dist/discord/types/guild-template.js +1 -0
  120. package/dist/discord/types/guild.d.ts +910 -0
  121. package/dist/discord/types/guild.js +153 -0
  122. package/dist/discord/types/index.d.ts +31 -0
  123. package/dist/discord/types/index.js +31 -0
  124. package/dist/discord/types/interaction.d.ts +321 -0
  125. package/dist/discord/types/interaction.js +47 -0
  126. package/dist/discord/types/invite.d.ts +158 -0
  127. package/dist/discord/types/invite.js +39 -0
  128. package/dist/discord/types/message.d.ts +834 -0
  129. package/dist/discord/types/message.js +159 -0
  130. package/dist/discord/types/oauth2.d.ts +22 -0
  131. package/dist/discord/types/oauth2.js +1 -0
  132. package/dist/discord/types/permissions.d.ts +183 -0
  133. package/dist/discord/types/permissions.js +118 -0
  134. package/dist/discord/types/poll.d.ts +106 -0
  135. package/dist/discord/types/poll.js +8 -0
  136. package/dist/discord/types/sku.d.ts +47 -0
  137. package/dist/discord/types/sku.js +26 -0
  138. package/dist/discord/types/soundboard.d.ts +71 -0
  139. package/dist/discord/types/soundboard.js +1 -0
  140. package/dist/discord/types/stage-instance.d.ts +58 -0
  141. package/dist/discord/types/stage-instance.js +10 -0
  142. package/dist/discord/types/sticker.d.ts +115 -0
  143. package/dist/discord/types/sticker.js +20 -0
  144. package/dist/discord/types/subscription.d.ts +54 -0
  145. package/dist/discord/types/subscription.js +12 -0
  146. package/dist/discord/types/team.d.ts +55 -0
  147. package/dist/discord/types/team.js +21 -0
  148. package/dist/discord/types/user.d.ts +273 -0
  149. package/dist/discord/types/user.js +83 -0
  150. package/dist/discord/types/voice.d.ts +72 -0
  151. package/dist/discord/types/voice.js +1 -0
  152. package/dist/discord/types/webhook.d.ts +184 -0
  153. package/dist/discord/types/webhook.js +12 -0
  154. package/dist/events/declaration.d.ts +16 -0
  155. package/dist/events/declaration.js +80 -0
  156. package/dist/events/event.d.ts +45 -0
  157. package/dist/events/event.js +34 -0
  158. package/dist/events/registry.d.ts +697 -0
  159. package/dist/events/registry.js +839 -0
  160. package/dist/events/router.d.ts +46 -0
  161. package/dist/events/router.js +133 -0
  162. package/dist/gateway/errors.d.ts +18 -0
  163. package/dist/gateway/errors.js +47 -0
  164. package/dist/gateway/gateway.d.ts +64 -0
  165. package/dist/gateway/gateway.js +117 -0
  166. package/dist/gateway/identify-queue.d.ts +25 -0
  167. package/dist/gateway/identify-queue.js +29 -0
  168. package/dist/gateway/shard.d.ts +94 -0
  169. package/dist/gateway/shard.js +414 -0
  170. package/dist/gateway/state.d.ts +11 -0
  171. package/dist/gateway/state.js +184 -0
  172. package/dist/index.d.ts +57 -18
  173. package/dist/index.js +40 -12
  174. package/dist/interactions/cooldown.d.ts +33 -0
  175. package/dist/interactions/cooldown.js +74 -0
  176. package/dist/interactions/dispatch.d.ts +91 -0
  177. package/dist/interactions/dispatch.js +110 -0
  178. package/dist/loader/generated.d.ts +10 -0
  179. package/dist/loader/generated.js +80 -0
  180. package/dist/loader/hot.d.ts +13 -0
  181. package/dist/loader/hot.js +85 -0
  182. package/dist/loader/loader.d.ts +85 -0
  183. package/dist/loader/loader.js +119 -0
  184. package/dist/loader/locate.d.ts +10 -0
  185. package/dist/loader/locate.js +36 -0
  186. package/dist/loader/watch.d.ts +17 -0
  187. package/dist/loader/watch.js +66 -0
  188. package/dist/main.d.ts +2 -0
  189. package/dist/main.js +5 -0
  190. package/dist/messages/commands.d.ts +23 -0
  191. package/dist/messages/commands.js +142 -0
  192. package/dist/messages/declaration.d.ts +89 -0
  193. package/dist/messages/declaration.js +455 -0
  194. package/dist/messages/messages.d.ts +241 -0
  195. package/dist/messages/messages.js +31 -0
  196. package/dist/messages/phrases.d.ts +23 -0
  197. package/dist/messages/phrases.js +44 -0
  198. package/dist/messages/translate.d.ts +100 -0
  199. package/dist/messages/translate.js +249 -0
  200. package/dist/presence/declaration.d.ts +19 -0
  201. package/dist/presence/declaration.js +118 -0
  202. package/dist/presence/presence.d.ts +57 -0
  203. package/dist/presence/presence.js +27 -0
  204. package/dist/rest/errors.d.ts +55 -0
  205. package/dist/rest/errors.js +92 -0
  206. package/dist/rest/rate-limiter.d.ts +46 -0
  207. package/dist/rest/rate-limiter.js +153 -0
  208. package/dist/rest/rest.d.ts +63 -0
  209. package/dist/rest/rest.js +194 -0
  210. package/dist/structures/base.d.ts +48 -0
  211. package/dist/structures/base.js +84 -0
  212. package/dist/structures/channel.d.ts +380 -0
  213. package/dist/structures/channel.js +627 -0
  214. package/dist/structures/context.d.ts +30 -0
  215. package/dist/structures/context.js +7 -0
  216. package/dist/structures/emoji.d.ts +46 -0
  217. package/dist/structures/emoji.js +65 -0
  218. package/dist/structures/entities.d.ts +62 -0
  219. package/dist/structures/entities.js +226 -0
  220. package/dist/structures/guild.d.ts +348 -0
  221. package/dist/structures/guild.js +466 -0
  222. package/dist/structures/interaction.d.ts +197 -0
  223. package/dist/structures/interaction.js +396 -0
  224. package/dist/structures/invite.d.ts +38 -0
  225. package/dist/structures/invite.js +57 -0
  226. package/dist/structures/known.d.ts +28 -0
  227. package/dist/structures/known.js +58 -0
  228. package/dist/structures/member.d.ts +140 -0
  229. package/dist/structures/member.js +260 -0
  230. package/dist/structures/message.d.ts +197 -0
  231. package/dist/structures/message.js +268 -0
  232. package/dist/structures/payload.d.ts +91 -0
  233. package/dist/structures/payload.js +184 -0
  234. package/dist/structures/role.d.ts +69 -0
  235. package/dist/structures/role.js +112 -0
  236. package/dist/structures/user.d.ts +59 -0
  237. package/dist/structures/user.js +94 -0
  238. package/dist/structures/webhook.d.ts +46 -0
  239. package/dist/structures/webhook.js +79 -0
  240. package/dist/tasks/declaration.d.ts +16 -0
  241. package/dist/tasks/declaration.js +56 -0
  242. package/dist/tasks/schedule.d.ts +54 -0
  243. package/dist/tasks/schedule.js +236 -0
  244. package/dist/tasks/scheduler.d.ts +35 -0
  245. package/dist/tasks/scheduler.js +107 -0
  246. package/dist/tasks/task.d.ts +75 -0
  247. package/dist/tasks/task.js +27 -0
  248. package/dist/util/case.d.ts +13 -0
  249. package/dist/util/case.js +54 -0
  250. package/dist/util/duration.d.ts +8 -0
  251. package/dist/util/duration.js +29 -0
  252. package/dist/util/websocket.d.ts +9 -0
  253. package/dist/util/websocket.js +31 -0
  254. package/dist/voice/connection.d.ts +90 -0
  255. package/dist/voice/connection.js +494 -0
  256. package/dist/voice/dave.d.ts +109 -0
  257. package/dist/voice/dave.js +245 -0
  258. package/dist/voice/opus.d.ts +19 -0
  259. package/dist/voice/opus.js +273 -0
  260. package/dist/voice/session.d.ts +55 -0
  261. package/dist/voice/session.js +405 -0
  262. package/dist/voice/source.d.ts +22 -0
  263. package/dist/voice/source.js +195 -0
  264. package/dist/voice/transport.d.ts +43 -0
  265. package/dist/voice/transport.js +140 -0
  266. package/dist/voice/usage.d.ts +4 -0
  267. package/dist/voice/usage.js +33 -0
  268. package/package.json +26 -7
  269. package/vendor/dave/LICENSE +231 -0
  270. package/vendor/dave/libdave.d.mts +99 -0
  271. package/vendor/dave/libdave.mjs +2 -0
  272. package/vendor/dave/libdave.wasm +0 -0
  273. package/dist/components.d.ts +0 -97
  274. package/dist/components.js +0 -260
  275. package/dist/context.d.ts +0 -72
  276. package/dist/context.js +0 -273
  277. package/dist/discord/client.d.ts +0 -35
  278. package/dist/discord/client.js +0 -66
  279. package/dist/discord/constants.d.ts +0 -49
  280. package/dist/discord/constants.js +0 -61
  281. package/dist/discord/events.d.ts +0 -129
  282. package/dist/discord/events.js +0 -102
  283. package/dist/discord/gateway.d.ts +0 -61
  284. package/dist/discord/gateway.js +0 -320
  285. package/dist/discord/payloads.d.ts +0 -275
  286. package/dist/discord/payloads.js +0 -3
  287. package/dist/discord/presence.d.ts +0 -42
  288. package/dist/discord/presence.js +0 -51
  289. package/dist/discord/rest.d.ts +0 -49
  290. package/dist/discord/rest.js +0 -271
  291. package/dist/discord/types.d.ts +0 -334
  292. package/dist/discord/types.js +0 -4
  293. package/dist/events.d.ts +0 -94
  294. package/dist/events.js +0 -255
  295. package/dist/presence.d.ts +0 -92
  296. package/dist/presence.js +0 -250
  297. package/dist/structures/Channel.d.ts +0 -110
  298. package/dist/structures/Channel.js +0 -171
  299. package/dist/structures/Guild.d.ts +0 -70
  300. package/dist/structures/Guild.js +0 -105
  301. package/dist/structures/Interaction.d.ts +0 -113
  302. package/dist/structures/Interaction.js +0 -274
  303. package/dist/structures/Member.d.ts +0 -70
  304. package/dist/structures/Member.js +0 -124
  305. package/dist/structures/Message.d.ts +0 -87
  306. package/dist/structures/Message.js +0 -182
  307. package/dist/structures/Reaction.d.ts +0 -38
  308. package/dist/structures/Reaction.js +0 -64
  309. package/dist/structures/Role.d.ts +0 -43
  310. package/dist/structures/Role.js +0 -77
  311. package/dist/structures/User.d.ts +0 -41
  312. package/dist/structures/User.js +0 -79
  313. package/dist/structures/utils.d.ts +0 -72
  314. package/dist/structures/utils.js +0 -59
  315. package/dist/utils/errors.d.ts +0 -5
  316. package/dist/utils/errors.js +0 -28
  317. package/dist/utils/modules.d.ts +0 -39
  318. package/dist/utils/modules.js +0 -156
@@ -0,0 +1,46 @@
1
+ /** What can change about a file of `public/` when it is sent. */
2
+ export interface AssetOptions {
3
+ /** The name the file is sent under; by default its own name. */
4
+ name?: string;
5
+ /** What the file shows, for people who can't see it. */
6
+ description?: string;
7
+ /** Hides the file until it is clicked. */
8
+ spoiler?: boolean;
9
+ /** The media type of the file (`image/png`); guessed from the name when missing. */
10
+ contentType?: string;
11
+ }
12
+ declare const brand: unique symbol;
13
+ /**
14
+ * A file of the `public/` folder of the project, made by `asset()`, to put
15
+ * in the `files` of a message. It is read when the message is sent.
16
+ */
17
+ export interface AssetFile {
18
+ readonly [brand]: 'asset';
19
+ /** The name the file is sent under, with its extension. */
20
+ readonly name: string;
21
+ /** The path of the file inside `public/`. */
22
+ readonly path: string;
23
+ /** What the file shows, for people who can't see it. */
24
+ readonly description?: string;
25
+ /** Hides the file until it is clicked. */
26
+ readonly spoiler?: boolean;
27
+ /** The media type of the file; guessed from the name when missing. */
28
+ readonly contentType?: string;
29
+ }
30
+ /** Tells `asset()` where the project is. Only the CLI calls it. */
31
+ export declare function setPublicDir(projectDir: string): void;
32
+ /** Whether a value was made by `asset()`. */
33
+ export declare function isAssetFile(value: unknown): value is AssetFile;
34
+ /**
35
+ * A file of the `public/` folder of the project, to send with a message:
36
+ * `files: [asset('photos/monday.png')]`. The file is read when the message
37
+ * is sent, so a missing file is an error there.
38
+ */
39
+ export declare function asset(path: string, options?: AssetOptions): AssetFile;
40
+ /** Where the file of an asset is on disk, checked to be inside `public/`. */
41
+ export declare function assetPath(file: AssetFile): string;
42
+ /** The error to give for an asset whose file could not be opened. */
43
+ export declare function missingAsset(file: AssetFile, error: unknown): unknown;
44
+ /** Reads the file of an asset, when the message is sent. */
45
+ export declare function readAsset(file: AssetFile): Promise<Uint8Array>;
46
+ export {};
@@ -0,0 +1,86 @@
1
+ // `asset()`, as user files import it from 'chapterjs': a file of the
2
+ // `public/` folder of the project, to send with a message. Its type is
3
+ // written per project (see `public.ts`), so the editor lists the files.
4
+ import { readFile } from 'node:fs/promises';
5
+ import { basename, join, normalize, sep } from 'node:path';
6
+ import { PUBLIC_FOLDER } from './public.js';
7
+ const ASSET = Symbol.for('chapterjs.asset');
8
+ /** Where `public/` is: told by the CLI, which knows the project. */
9
+ let publicDir = null;
10
+ /** Tells `asset()` where the project is. Only the CLI calls it. */
11
+ export function setPublicDir(projectDir) {
12
+ publicDir = join(projectDir, PUBLIC_FOLDER);
13
+ }
14
+ /** Whether a value was made by `asset()`. */
15
+ export function isAssetFile(value) {
16
+ return (typeof value === 'object' &&
17
+ value !== null &&
18
+ value[ASSET] === true);
19
+ }
20
+ /**
21
+ * A file of the `public/` folder of the project, to send with a message:
22
+ * `files: [asset('photos/monday.png')]`. The file is read when the message
23
+ * is sent, so a missing file is an error there.
24
+ */
25
+ export function asset(path, options = {}) {
26
+ if (typeof path !== 'string' || path.trim() === '') {
27
+ throw new TypeError(`asset() takes the path of a file inside ${PUBLIC_FOLDER}/, like asset('photos/monday.png').`);
28
+ }
29
+ const clean = path.replace(/\\/g, '/').replace(/^\/+/, '');
30
+ if (clean.split('/').some(part => part === '..' || part === '')) {
31
+ throw new TypeError(`asset() only reads inside ${PUBLIC_FOLDER}/: ${JSON.stringify(path)} leaves it.`);
32
+ }
33
+ if (typeof options !== 'object' || options === null) {
34
+ throw new TypeError(`The options of asset() are an object like { description: '...' }.`);
35
+ }
36
+ for (const key of Object.keys(options)) {
37
+ if (!['name', 'description', 'spoiler', 'contentType'].includes(key)) {
38
+ throw new TypeError(`"${key}" is not an option of asset(). Options are: name, description, spoiler, contentType.`);
39
+ }
40
+ }
41
+ const name = options.name ?? basename(clean);
42
+ if (typeof name !== 'string' || name.trim() === '' || name.includes('/')) {
43
+ throw new TypeError(`The name of an asset is a file name with its extension, like "chart.png", got ${JSON.stringify(options.name)}.`);
44
+ }
45
+ const file = {
46
+ name,
47
+ path: clean,
48
+ ...(options.description !== undefined
49
+ ? { description: options.description }
50
+ : {}),
51
+ ...(options.spoiler ? { spoiler: true } : {}),
52
+ ...(options.contentType !== undefined
53
+ ? { contentType: options.contentType }
54
+ : {}),
55
+ };
56
+ // The brand is not shown by console.log, nor copied by a spread.
57
+ Object.defineProperty(file, ASSET, { value: true });
58
+ return Object.freeze(file);
59
+ }
60
+ /** Where the file of an asset is on disk, checked to be inside `public/`. */
61
+ export function assetPath(file) {
62
+ if (!publicDir) {
63
+ throw new Error(`asset('${file.path}') can only be sent by a bot run with chapterjs dev or chapterjs start.`);
64
+ }
65
+ const target = join(publicDir, normalize(file.path));
66
+ if (!target.startsWith(publicDir + sep)) {
67
+ throw new Error(`asset() only reads inside ${PUBLIC_FOLDER}/: ${JSON.stringify(file.path)} leaves it.`);
68
+ }
69
+ return target;
70
+ }
71
+ /** The error to give for an asset whose file could not be opened. */
72
+ export function missingAsset(file, error) {
73
+ return error.code === 'ENOENT'
74
+ ? new Error(`There is no file ${PUBLIC_FOLDER}/${file.path} in your project: put it there, or pick one of the files the editor lists in asset().`)
75
+ : error;
76
+ }
77
+ /** Reads the file of an asset, when the message is sent. */
78
+ export async function readAsset(file) {
79
+ const target = assetPath(file);
80
+ try {
81
+ return await readFile(target);
82
+ }
83
+ catch (error) {
84
+ throw missingAsset(file, error);
85
+ }
86
+ }
@@ -0,0 +1,19 @@
1
+ /** The folder, at the root of the project. */
2
+ export declare const PUBLIC_FOLDER = "public";
3
+ /**
4
+ * Every file of `public/`, as a path from it with `/`, sorted. Hidden files
5
+ * (starting with `.`) are left out. An absent folder is an empty list.
6
+ */
7
+ export declare function listPublic(projectDir: string): Promise<string[]>;
8
+ /**
9
+ * What `'chapterjs'` declares in every file of the project about `public/`:
10
+ * the union of its files, and `asset()` typed with it.
11
+ */
12
+ export declare function publicDeclarations(paths: readonly string[]): string;
13
+ /**
14
+ * Calls `onChange` when a file of `public/` is added, removed or saved.
15
+ * The folder may not exist yet: it is watched for as soon as it appears.
16
+ */
17
+ export declare function watchPublic(projectDir: string, onChange: () => void): {
18
+ close(): void;
19
+ };
@@ -0,0 +1,120 @@
1
+ // The `public/` folder of a project: the files a bot sends (pictures,
2
+ // documents...). Its content is listed to type `asset()`, so that the
3
+ // editor offers every file and underlines one that does not exist.
4
+ import { existsSync, watch } from 'node:fs';
5
+ import { readdir } from 'node:fs/promises';
6
+ import { join, relative, sep } from 'node:path';
7
+ import { watchFolder } from '../loader/watch.js';
8
+ /** The folder, at the root of the project. */
9
+ export const PUBLIC_FOLDER = 'public';
10
+ /**
11
+ * Every file of `public/`, as a path from it with `/`, sorted. Hidden files
12
+ * (starting with `.`) are left out. An absent folder is an empty list.
13
+ */
14
+ export async function listPublic(projectDir) {
15
+ const root = join(projectDir, PUBLIC_FOLDER);
16
+ const entries = await readdir(root, {
17
+ recursive: true,
18
+ withFileTypes: true,
19
+ }).catch(() => []);
20
+ return entries
21
+ .filter(entry => entry.isFile())
22
+ .map(entry => relative(root, join(entry.parentPath, entry.name)).split(sep).join('/'))
23
+ .filter(path => !path.split('/').some(part => part.startsWith('.')))
24
+ .sort();
25
+ }
26
+ /**
27
+ * What `'chapterjs'` declares in every file of the project about `public/`:
28
+ * the union of its files, and `asset()` typed with it.
29
+ */
30
+ export function publicDeclarations(paths) {
31
+ const union = paths.length === 0
32
+ ? 'never'
33
+ : paths.map(path => `\n | ${JSON.stringify(path)}`).join('');
34
+ return `import type { AssetFile, AssetOptions } from '#chapterjs';
35
+
36
+ declare module 'chapterjs' {
37
+ /**
38
+ * A file of the public/ folder of your project, as a path from it:
39
+ * \`'photos/monday.png'\`.${paths.length === 0 ? ' The folder is empty or missing: put files in it, and they are listed here.' : ''}
40
+ */
41
+ export type PublicFile = ${union.replaceAll('\n', '\n ')};
42
+
43
+ /**
44
+ * A file of the public/ folder of your project, to send with a message:
45
+ * \`files: [asset('photos/monday.png')]\`. The editor lists the files of the
46
+ * folder; the file is read when the message is sent.
47
+ */
48
+ export function asset(path: PublicFile, options?: AssetOptions): AssetFile;
49
+ }
50
+ `;
51
+ }
52
+ /**
53
+ * Calls `onChange` when a file of `public/` is added, removed or saved.
54
+ * The folder may not exist yet: it is watched for as soon as it appears.
55
+ */
56
+ export function watchPublic(projectDir, onChange) {
57
+ const root = join(projectDir, PUBLIC_FOLDER);
58
+ let inner = null;
59
+ let outer = null;
60
+ const watchInside = (loaded) => {
61
+ try {
62
+ inner = watchFolder(root, onChange, loaded ? { loaded } : {});
63
+ }
64
+ catch {
65
+ inner = null;
66
+ }
67
+ };
68
+ let catchUps = [];
69
+ const appeared = () => {
70
+ if (inner)
71
+ return;
72
+ // The folder was not there: what it has by the time it is watched
73
+ // (files copied with it, or written right after) is all new.
74
+ watchInside(Promise.resolve(''));
75
+ if (!inner)
76
+ return;
77
+ outer?.close();
78
+ outer = null;
79
+ for (const catchUp of catchUps)
80
+ clearTimeout(catchUp);
81
+ onChange();
82
+ };
83
+ // Until the folder exists, only its parent is watched, for its creation.
84
+ const watchForCreation = () => {
85
+ try {
86
+ outer = watch(projectDir, (_event, name) => {
87
+ if (name === PUBLIC_FOLDER)
88
+ appeared();
89
+ });
90
+ outer.unref();
91
+ }
92
+ catch {
93
+ outer = null;
94
+ }
95
+ // The system takes a moment to really start watching: a folder created
96
+ // meanwhile is looked for a little later.
97
+ catchUps = [300, 1500].map(wait => {
98
+ const timer = setTimeout(() => {
99
+ if (existsSync(root))
100
+ appeared();
101
+ }, wait);
102
+ timer.unref();
103
+ return timer;
104
+ });
105
+ };
106
+ // Whether the folder is there is asked, not inferred from watch()
107
+ // failing: on Linux, Node 24 watches a missing folder without an error.
108
+ if (existsSync(root))
109
+ watchInside();
110
+ if (!inner)
111
+ watchForCreation();
112
+ return {
113
+ close() {
114
+ for (const catchUp of catchUps)
115
+ clearTimeout(catchUp);
116
+ inner?.close();
117
+ outer?.close();
118
+ },
119
+ };
120
+ }
@@ -0,0 +1,62 @@
1
+ import type { Snowflake } from '../discord/types/common.js';
2
+ import type { Channel } from '../structures/channel.js';
3
+ import type { Guild } from '../structures/guild.js';
4
+ import type { User } from '../structures/user.js';
5
+ import { type CacheStore, type CacheStoreFactory } from './store.js';
6
+ /**
7
+ * How many of each kind of thing are remembered. `0` disables a kind,
8
+ * `Infinity` keeps everything Discord sends.
9
+ */
10
+ export interface CacheLimits {
11
+ /** Users, across every server. */
12
+ users: number;
13
+ /**
14
+ * Members, per server: the ones seen the most recently. The bot itself
15
+ * is always kept, apart from this.
16
+ */
17
+ members: number;
18
+ /** Messages, per channel. */
19
+ messages: number;
20
+ }
21
+ /**
22
+ * Messages are not kept by default: they are by far what a bot receives the
23
+ * most, and most bots never read an old one. A feature that needs them
24
+ * raises the limit.
25
+ */
26
+ export declare const DEFAULT_CACHE_LIMITS: CacheLimits;
27
+ export interface CacheOptions {
28
+ limits?: Partial<CacheLimits>;
29
+ /** Where data is stored. Default: the memory of the process. */
30
+ store?: CacheStoreFactory;
31
+ }
32
+ /**
33
+ * What the bot currently knows about Discord, kept up to date by events so
34
+ * that reading it never costs a request. Servers own what belongs to them
35
+ * (roles, members, emojis...): forgetting a server forgets it all.
36
+ */
37
+ export declare class Cache {
38
+ #private;
39
+ readonly createStore: CacheStoreFactory;
40
+ readonly users: CacheStore<Snowflake, User>;
41
+ readonly guilds: CacheStore<Snowflake, Guild>;
42
+ /** Every channel the bot knows: of servers, threads and private ones. */
43
+ readonly channels: CacheStore<Snowflake, Channel>;
44
+ constructor(options?: CacheOptions);
45
+ /** How many of each kind are kept when memory is not a concern. */
46
+ get configured(): Readonly<CacheLimits>;
47
+ /**
48
+ * Changes what is kept when memory is not a concern (the files of the
49
+ * project changed and need more, or less). What holds right now follows,
50
+ * except what memory made lower: that stays as low as it is.
51
+ */
52
+ configure(limits: Partial<CacheLimits>): void;
53
+ /**
54
+ * How many of each kind are kept right now: what was configured, or less
55
+ * while memory is short (see `core/memory.ts`). New stores follow it.
56
+ */
57
+ get limits(): Readonly<CacheLimits>;
58
+ /** Changes the limits new stores follow; existing ones are resized apart. */
59
+ setLimits(limits: Partial<CacheLimits>): void;
60
+ /** Forgets everything (the session was lost and starts over). */
61
+ clear(): void;
62
+ }
@@ -0,0 +1,80 @@
1
+ import { memoryStore, } from './store.js';
2
+ /**
3
+ * Messages are not kept by default: they are by far what a bot receives the
4
+ * most, and most bots never read an old one. A feature that needs them
5
+ * raises the limit.
6
+ */
7
+ export const DEFAULT_CACHE_LIMITS = {
8
+ users: Infinity,
9
+ // A server can have millions of members, and Discord recommends keeping
10
+ // only what the app needs: what an event comes with (the author of a
11
+ // message, who used a command) is kept by the event itself, whatever this
12
+ // limit. A feature that needs more members remembered asks for it (see
13
+ // `remembers` in the events).
14
+ // https://docs.discord.com/developers/events/gateway#tracking-state
15
+ members: 100,
16
+ messages: 0,
17
+ };
18
+ /**
19
+ * What the bot currently knows about Discord, kept up to date by events so
20
+ * that reading it never costs a request. Servers own what belongs to them
21
+ * (roles, members, emojis...): forgetting a server forgets it all.
22
+ */
23
+ export class Cache {
24
+ #configured;
25
+ #limits;
26
+ createStore;
27
+ users;
28
+ guilds;
29
+ /** Every channel the bot knows: of servers, threads and private ones. */
30
+ channels;
31
+ constructor(options = {}) {
32
+ this.#configured = Object.freeze({
33
+ ...DEFAULT_CACHE_LIMITS,
34
+ ...options.limits,
35
+ });
36
+ this.#limits = { ...this.#configured };
37
+ this.createStore = options.store ?? memoryStore;
38
+ this.users = this.createStore({ limit: this.limits.users });
39
+ this.guilds = this.createStore();
40
+ this.channels = this.createStore();
41
+ }
42
+ /** How many of each kind are kept when memory is not a concern. */
43
+ get configured() {
44
+ return this.#configured;
45
+ }
46
+ /**
47
+ * Changes what is kept when memory is not a concern (the files of the
48
+ * project changed and need more, or less). What holds right now follows,
49
+ * except what memory made lower: that stays as low as it is.
50
+ */
51
+ configure(limits) {
52
+ const next = Object.freeze({ ...this.#configured, ...limits });
53
+ const now = { ...this.#limits };
54
+ for (const kind of Object.keys(next)) {
55
+ now[kind] =
56
+ this.#limits[kind] === this.#configured[kind]
57
+ ? next[kind]
58
+ : Math.min(this.#limits[kind], next[kind]);
59
+ }
60
+ this.#configured = next;
61
+ this.#limits = now;
62
+ }
63
+ /**
64
+ * How many of each kind are kept right now: what was configured, or less
65
+ * while memory is short (see `core/memory.ts`). New stores follow it.
66
+ */
67
+ get limits() {
68
+ return this.#limits;
69
+ }
70
+ /** Changes the limits new stores follow; existing ones are resized apart. */
71
+ setLimits(limits) {
72
+ this.#limits = { ...this.#limits, ...limits };
73
+ }
74
+ /** Forgets everything (the session was lost and starts over). */
75
+ clear() {
76
+ this.users.clear();
77
+ this.guilds.clear();
78
+ this.channels.clear();
79
+ }
80
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Where one kind of thing is remembered (the roles of a server, the
3
+ * messages of a channel...). Reading is a plain `ReadonlyMap`, which is what
4
+ * users get; only the framework writes.
5
+ *
6
+ * Stores are synchronous on purpose: they are read on every event, in the
7
+ * process that received it. Sharing data between processes is the job of
8
+ * the layer that coordinates processes, not of the cache.
9
+ */
10
+ export interface CacheStore<K, V> extends ReadonlyMap<K, V> {
11
+ /** How many entries it keeps at most right now. */
12
+ readonly limit: number;
13
+ /**
14
+ * Changes how many entries it keeps. Lowered, the entries written the
15
+ * longest ago leave at once; returns how many did.
16
+ */
17
+ resize(limit: number): number;
18
+ set(key: K, value: V): unknown;
19
+ delete(key: K): boolean;
20
+ clear(): void;
21
+ }
22
+ export interface CacheStoreOptions {
23
+ /**
24
+ * How many entries are kept at most: `0` keeps nothing, `Infinity` (the
25
+ * default) keeps everything. When full, the entry that was written the
26
+ * longest ago leaves: writing an entry again makes it the most recent.
27
+ */
28
+ limit?: number;
29
+ }
30
+ /** Creates the store of one kind of thing. A new backend is one of these. */
31
+ export type CacheStoreFactory = <K, V>(options?: CacheStoreOptions) => CacheStore<K, V>;
32
+ /** The default store: a `Map` in the memory of the process. */
33
+ export declare class MemoryStore<K, V> extends Map<K, V> implements CacheStore<K, V> {
34
+ #private;
35
+ constructor({ limit }?: CacheStoreOptions);
36
+ get limit(): number;
37
+ resize(limit: number): number;
38
+ set(key: K, value: V): this;
39
+ }
40
+ /**
41
+ * Makes a store forget its oldest entries until `keep` are left. Returns
42
+ * how many it forgot.
43
+ */
44
+ export declare function trimStore<K>(store: CacheStore<K, unknown>, keep: number): number;
45
+ export declare const memoryStore: CacheStoreFactory;
@@ -0,0 +1,53 @@
1
+ function checkLimit(limit) {
2
+ if (Number.isNaN(limit) || limit < 0) {
3
+ throw new RangeError(`A cache limit is 0 or more (or Infinity), got ${limit}.`);
4
+ }
5
+ return limit;
6
+ }
7
+ /** The default store: a `Map` in the memory of the process. */
8
+ export class MemoryStore extends Map {
9
+ #limit;
10
+ constructor({ limit = Infinity } = {}) {
11
+ super();
12
+ this.#limit = checkLimit(limit);
13
+ }
14
+ get limit() {
15
+ return this.#limit;
16
+ }
17
+ resize(limit) {
18
+ this.#limit = checkLimit(limit);
19
+ return trimStore(this, limit);
20
+ }
21
+ set(key, value) {
22
+ if (this.#limit === 0)
23
+ return this;
24
+ if (this.#limit !== Infinity) {
25
+ // A Map iterates in insertion order: written again, an entry goes to
26
+ // the end, so the first key is always the one seen the longest ago.
27
+ if (!super.delete(key) && this.size >= this.#limit) {
28
+ for (const oldest of this.keys()) {
29
+ this.delete(oldest);
30
+ break;
31
+ }
32
+ }
33
+ }
34
+ return super.set(key, value);
35
+ }
36
+ }
37
+ /**
38
+ * Makes a store forget its oldest entries until `keep` are left. Returns
39
+ * how many it forgot.
40
+ */
41
+ export function trimStore(store, keep) {
42
+ let extra = store.size - Math.max(0, keep);
43
+ if (extra <= 0)
44
+ return 0;
45
+ const forgotten = extra;
46
+ for (const key of [...store.keys()]) {
47
+ if (extra-- <= 0)
48
+ break;
49
+ store.delete(key);
50
+ }
51
+ return forgotten;
52
+ }
53
+ export const memoryStore = options => new MemoryStore(options);
@@ -0,0 +1,41 @@
1
+ import { type BuiltFile } from '../loader/loader.js';
2
+ import type { Log } from './log.js';
3
+ /** Where the build of a project is, from its folder. */
4
+ export declare const buildDir: (cwd: string) => string;
5
+ /** The file the whole bot is compiled into, in the build. */
6
+ export declare const BUNDLE = "bot.js";
7
+ /** What `build.json` says of a build. */
8
+ export interface BuildInfo {
9
+ /** The version of the framework that made it. */
10
+ version: string;
11
+ /** What the files of `src` were when it was made. */
12
+ sources: string;
13
+ commands: number;
14
+ events: number;
15
+ /** Whether the files join voice channels (an intent to ask for). */
16
+ voice: boolean;
17
+ }
18
+ /** One value for everything in a folder: it changes when a file does. */
19
+ export declare function fingerprint(dir: string): Promise<string>;
20
+ /** The build of a project, or why there is none to run. */
21
+ export declare function readBuild(cwd: string, version: string): Promise<{
22
+ info: BuildInfo;
23
+ stale: boolean;
24
+ } | {
25
+ problem: string;
26
+ }>;
27
+ /**
28
+ * Loads the bot a build compiled: every file of the project, already run.
29
+ * Errors that come out of it afterwards name the file and the line of the
30
+ * project, not of the compiled file: Node reads the map next to it.
31
+ */
32
+ export declare function loadBundle(cwd: string): Promise<BuiltFile[]>;
33
+ export interface BuildOptions {
34
+ /** The folder of the project. */
35
+ cwd: string;
36
+ /** The version of the framework. */
37
+ version: string;
38
+ log: Log;
39
+ }
40
+ /** Resolves with the exit code of the process. */
41
+ export declare function build(options: BuildOptions): Promise<number>;