chapterjs 0.1.2 → 0.1.4
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/dist/assets/asset.d.ts +46 -0
- package/dist/assets/asset.js +86 -0
- package/dist/assets/public.d.ts +19 -0
- package/dist/assets/public.js +120 -0
- package/dist/cache/cache.d.ts +62 -0
- package/dist/cache/cache.js +80 -0
- package/dist/cache/store.d.ts +45 -0
- package/dist/cache/store.js +53 -0
- package/dist/cli/build.d.ts +41 -0
- package/dist/cli/build.js +206 -0
- package/dist/cli/cli.js +108 -25
- package/dist/cli/cluster.d.ts +70 -0
- package/dist/cli/cluster.js +213 -0
- package/dist/cli/dev.d.ts +18 -1
- package/dist/cli/dev.js +252 -198
- package/dist/cli/env.d.ts +31 -0
- package/dist/cli/env.js +93 -0
- package/dist/cli/log.d.ts +13 -0
- package/dist/cli/log.js +17 -0
- package/dist/cli/node-version.d.ts +8 -0
- package/dist/cli/node-version.js +13 -0
- package/dist/cli/preflight.d.ts +36 -0
- package/dist/cli/preflight.js +122 -0
- package/dist/cli/project.d.ts +122 -0
- package/dist/cli/project.js +452 -0
- package/dist/cli/start.d.ts +25 -0
- package/dist/cli/start.js +225 -0
- package/dist/commands/autocomplete.d.ts +13 -0
- package/dist/commands/autocomplete.js +159 -0
- package/dist/commands/command.d.ts +346 -0
- package/dist/commands/command.js +28 -0
- package/dist/commands/convention.d.ts +64 -0
- package/dist/commands/convention.js +464 -0
- package/dist/commands/register.d.ts +18 -0
- package/dist/commands/register.js +42 -0
- package/dist/commands/router.d.ts +20 -0
- package/dist/commands/router.js +228 -0
- package/dist/commands/tree.d.ts +43 -0
- package/dist/commands/tree.js +206 -0
- package/dist/commands/twins.d.ts +15 -0
- package/dist/commands/twins.js +78 -0
- package/dist/components/button.d.ts +79 -0
- package/dist/components/button.js +108 -0
- package/dist/components/component.d.ts +140 -0
- package/dist/components/component.js +39 -0
- package/dist/components/convention.d.ts +35 -0
- package/dist/components/convention.js +339 -0
- package/dist/components/custom-id.d.ts +72 -0
- package/dist/components/custom-id.js +128 -0
- package/dist/components/embed.d.ts +28 -0
- package/dist/components/embed.js +11 -0
- package/dist/components/file.d.ts +30 -0
- package/dist/components/file.js +52 -0
- package/dist/components/instance.d.ts +100 -0
- package/dist/components/instance.js +86 -0
- package/dist/components/layout.d.ts +103 -0
- package/dist/components/layout.js +279 -0
- package/dist/components/modal.d.ts +244 -0
- package/dist/components/modal.js +399 -0
- package/dist/components/options.d.ts +41 -0
- package/dist/components/options.js +101 -0
- package/dist/components/render.d.ts +12 -0
- package/dist/components/render.js +58 -0
- package/dist/components/router.d.ts +18 -0
- package/dist/components/router.js +256 -0
- package/dist/components/select.d.ts +144 -0
- package/dist/components/select.js +179 -0
- package/dist/core/bot.d.ts +99 -0
- package/dist/core/bot.js +174 -0
- package/dist/core/memory.d.ts +66 -0
- package/dist/core/memory.js +115 -0
- package/dist/discord/api.d.ts +112 -0
- package/dist/discord/api.js +115 -0
- package/dist/discord/cdn.d.ts +67 -0
- package/dist/discord/cdn.js +100 -0
- package/dist/discord/codes.d.ts +171 -0
- package/dist/discord/codes.js +421 -0
- package/dist/discord/endpoint.d.ts +56 -0
- package/dist/discord/endpoint.js +53 -0
- package/dist/discord/endpoints.d.ts +1529 -0
- package/dist/discord/endpoints.js +1139 -0
- package/dist/discord/formatting.d.ts +67 -0
- package/dist/discord/formatting.js +87 -0
- package/dist/discord/index.d.ts +10 -0
- package/dist/discord/index.js +13 -0
- package/dist/discord/intents.d.ts +48 -0
- package/dist/discord/intents.js +128 -0
- package/dist/discord/permissions.d.ts +94 -0
- package/dist/discord/permissions.js +185 -0
- package/dist/discord/snowflake.d.ts +21 -0
- package/dist/discord/snowflake.js +36 -0
- package/dist/discord/types/application-command.d.ts +332 -0
- package/dist/discord/types/application-command.js +48 -0
- package/dist/discord/types/application-role-connection-metadata.d.ts +42 -0
- package/dist/discord/types/application-role-connection-metadata.js +22 -0
- package/dist/discord/types/application.d.ts +208 -0
- package/dist/discord/types/application.js +48 -0
- package/dist/discord/types/audit-log.d.ts +255 -0
- package/dist/discord/types/audit-log.js +144 -0
- package/dist/discord/types/auto-moderation.d.ts +167 -0
- package/dist/discord/types/auto-moderation.js +52 -0
- package/dist/discord/types/channel.d.ts +557 -0
- package/dist/discord/types/channel.js +88 -0
- package/dist/discord/types/common.d.ts +54 -0
- package/dist/discord/types/common.js +38 -0
- package/dist/discord/types/component.d.ts +775 -0
- package/dist/discord/types/component.js +76 -0
- package/dist/discord/types/emoji.d.ts +74 -0
- package/dist/discord/types/emoji.js +1 -0
- package/dist/discord/types/entitlement.d.ts +84 -0
- package/dist/discord/types/entitlement.js +22 -0
- package/dist/discord/types/gateway-events.d.ts +1148 -0
- package/dist/discord/types/gateway-events.js +54 -0
- package/dist/discord/types/gateway.d.ts +38 -0
- package/dist/discord/types/gateway.js +1 -0
- package/dist/discord/types/guild-scheduled-event.d.ts +257 -0
- package/dist/discord/types/guild-scheduled-event.js +68 -0
- package/dist/discord/types/guild-template.d.ts +51 -0
- package/dist/discord/types/guild-template.js +1 -0
- package/dist/discord/types/guild.d.ts +910 -0
- package/dist/discord/types/guild.js +153 -0
- package/dist/discord/types/index.d.ts +31 -0
- package/dist/discord/types/index.js +31 -0
- package/dist/discord/types/interaction.d.ts +321 -0
- package/dist/discord/types/interaction.js +47 -0
- package/dist/discord/types/invite.d.ts +158 -0
- package/dist/discord/types/invite.js +39 -0
- package/dist/discord/types/message.d.ts +834 -0
- package/dist/discord/types/message.js +159 -0
- package/dist/discord/types/oauth2.d.ts +22 -0
- package/dist/discord/types/oauth2.js +1 -0
- package/dist/discord/types/permissions.d.ts +183 -0
- package/dist/discord/types/permissions.js +118 -0
- package/dist/discord/types/poll.d.ts +106 -0
- package/dist/discord/types/poll.js +8 -0
- package/dist/discord/types/sku.d.ts +47 -0
- package/dist/discord/types/sku.js +26 -0
- package/dist/discord/types/soundboard.d.ts +71 -0
- package/dist/discord/types/soundboard.js +1 -0
- package/dist/discord/types/stage-instance.d.ts +58 -0
- package/dist/discord/types/stage-instance.js +10 -0
- package/dist/discord/types/sticker.d.ts +115 -0
- package/dist/discord/types/sticker.js +20 -0
- package/dist/discord/types/subscription.d.ts +54 -0
- package/dist/discord/types/subscription.js +12 -0
- package/dist/discord/types/team.d.ts +55 -0
- package/dist/discord/types/team.js +21 -0
- package/dist/discord/types/user.d.ts +273 -0
- package/dist/discord/types/user.js +83 -0
- package/dist/discord/types/voice.d.ts +72 -0
- package/dist/discord/types/voice.js +1 -0
- package/dist/discord/types/webhook.d.ts +184 -0
- package/dist/discord/types/webhook.js +12 -0
- package/dist/events/convention.d.ts +25 -0
- package/dist/events/convention.js +97 -0
- package/dist/events/event.d.ts +8 -0
- package/dist/events/event.js +20 -0
- package/dist/events/registry.d.ts +706 -0
- package/dist/events/registry.js +839 -0
- package/dist/events/router.d.ts +45 -0
- package/dist/events/router.js +133 -0
- package/dist/events/types.d.ts +7 -0
- package/dist/events/types.js +48 -0
- package/dist/gateway/errors.d.ts +18 -0
- package/dist/gateway/errors.js +47 -0
- package/dist/gateway/gateway.d.ts +64 -0
- package/dist/gateway/gateway.js +117 -0
- package/dist/gateway/identify-queue.d.ts +25 -0
- package/dist/gateway/identify-queue.js +29 -0
- package/dist/gateway/shard.d.ts +94 -0
- package/dist/gateway/shard.js +414 -0
- package/dist/gateway/state.d.ts +11 -0
- package/dist/gateway/state.js +184 -0
- package/dist/index.d.ts +55 -18
- package/dist/index.js +38 -12
- package/dist/interactions/cooldown.d.ts +33 -0
- package/dist/interactions/cooldown.js +74 -0
- package/dist/interactions/dispatch.d.ts +91 -0
- package/dist/interactions/dispatch.js +110 -0
- package/dist/loader/generated.d.ts +37 -0
- package/dist/loader/generated.js +114 -0
- package/dist/loader/hot.d.ts +13 -0
- package/dist/loader/hot.js +85 -0
- package/dist/loader/loader.d.ts +72 -0
- package/dist/loader/loader.js +135 -0
- package/dist/loader/locate.d.ts +10 -0
- package/dist/loader/locate.js +36 -0
- package/dist/loader/watch.d.ts +17 -0
- package/dist/loader/watch.js +66 -0
- package/dist/main.d.ts +3 -0
- package/dist/main.js +6 -0
- package/dist/messages/commands.d.ts +23 -0
- package/dist/messages/commands.js +123 -0
- package/dist/messages/convention.d.ts +89 -0
- package/dist/messages/convention.js +347 -0
- package/dist/messages/messages.d.ts +219 -0
- package/dist/messages/messages.js +30 -0
- package/dist/messages/phrases.d.ts +23 -0
- package/dist/messages/phrases.js +44 -0
- package/dist/messages/translate.d.ts +100 -0
- package/dist/messages/translate.js +249 -0
- package/dist/presence/convention.d.ts +26 -0
- package/dist/presence/convention.js +133 -0
- package/dist/presence/presence.d.ts +57 -0
- package/dist/presence/presence.js +27 -0
- package/dist/rest/errors.d.ts +55 -0
- package/dist/rest/errors.js +92 -0
- package/dist/rest/rate-limiter.d.ts +46 -0
- package/dist/rest/rate-limiter.js +153 -0
- package/dist/rest/rest.d.ts +63 -0
- package/dist/rest/rest.js +194 -0
- package/dist/structures/base.d.ts +48 -0
- package/dist/structures/base.js +84 -0
- package/dist/structures/channel.d.ts +380 -0
- package/dist/structures/channel.js +627 -0
- package/dist/structures/context.d.ts +30 -0
- package/dist/structures/context.js +7 -0
- package/dist/structures/emoji.d.ts +46 -0
- package/dist/structures/emoji.js +65 -0
- package/dist/structures/entities.d.ts +62 -0
- package/dist/structures/entities.js +226 -0
- package/dist/structures/guild.d.ts +348 -0
- package/dist/structures/guild.js +466 -0
- package/dist/structures/interaction.d.ts +197 -0
- package/dist/structures/interaction.js +396 -0
- package/dist/structures/invite.d.ts +38 -0
- package/dist/structures/invite.js +57 -0
- package/dist/structures/known.d.ts +28 -0
- package/dist/structures/known.js +58 -0
- package/dist/structures/member.d.ts +140 -0
- package/dist/structures/member.js +260 -0
- package/dist/structures/message.d.ts +197 -0
- package/dist/structures/message.js +268 -0
- package/dist/structures/payload.d.ts +91 -0
- package/dist/structures/payload.js +184 -0
- package/dist/structures/role.d.ts +69 -0
- package/dist/structures/role.js +112 -0
- package/dist/structures/user.d.ts +59 -0
- package/dist/structures/user.js +94 -0
- package/dist/structures/webhook.d.ts +46 -0
- package/dist/structures/webhook.js +79 -0
- package/dist/tasks/convention.d.ts +26 -0
- package/dist/tasks/convention.js +78 -0
- package/dist/tasks/schedule.d.ts +54 -0
- package/dist/tasks/schedule.js +236 -0
- package/dist/tasks/scheduler.d.ts +33 -0
- package/dist/tasks/scheduler.js +107 -0
- package/dist/tasks/task.d.ts +76 -0
- package/dist/tasks/task.js +28 -0
- package/dist/util/case.d.ts +13 -0
- package/dist/util/case.js +54 -0
- package/dist/util/duration.d.ts +8 -0
- package/dist/util/duration.js +29 -0
- package/dist/util/websocket.d.ts +9 -0
- package/dist/util/websocket.js +31 -0
- package/dist/voice/connection.d.ts +90 -0
- package/dist/voice/connection.js +494 -0
- package/dist/voice/dave.d.ts +109 -0
- package/dist/voice/dave.js +245 -0
- package/dist/voice/opus.d.ts +19 -0
- package/dist/voice/opus.js +273 -0
- package/dist/voice/session.d.ts +55 -0
- package/dist/voice/session.js +405 -0
- package/dist/voice/source.d.ts +22 -0
- package/dist/voice/source.js +195 -0
- package/dist/voice/transport.d.ts +43 -0
- package/dist/voice/transport.js +140 -0
- package/dist/voice/usage.d.ts +4 -0
- package/dist/voice/usage.js +33 -0
- package/package.json +26 -7
- package/vendor/dave/LICENSE +231 -0
- package/vendor/dave/libdave.d.mts +99 -0
- package/vendor/dave/libdave.mjs +2 -0
- package/vendor/dave/libdave.wasm +0 -0
- package/dist/components.d.ts +0 -97
- package/dist/components.js +0 -260
- package/dist/context.d.ts +0 -72
- package/dist/context.js +0 -273
- package/dist/discord/client.d.ts +0 -35
- package/dist/discord/client.js +0 -66
- package/dist/discord/constants.d.ts +0 -49
- package/dist/discord/constants.js +0 -61
- package/dist/discord/events.d.ts +0 -129
- package/dist/discord/events.js +0 -102
- package/dist/discord/gateway.d.ts +0 -61
- package/dist/discord/gateway.js +0 -320
- package/dist/discord/payloads.d.ts +0 -275
- package/dist/discord/payloads.js +0 -3
- package/dist/discord/presence.d.ts +0 -42
- package/dist/discord/presence.js +0 -51
- package/dist/discord/rest.d.ts +0 -49
- package/dist/discord/rest.js +0 -271
- package/dist/discord/types.d.ts +0 -334
- package/dist/discord/types.js +0 -4
- package/dist/events.d.ts +0 -94
- package/dist/events.js +0 -255
- package/dist/presence.d.ts +0 -92
- package/dist/presence.js +0 -250
- package/dist/structures/Channel.d.ts +0 -110
- package/dist/structures/Channel.js +0 -171
- package/dist/structures/Guild.d.ts +0 -70
- package/dist/structures/Guild.js +0 -105
- package/dist/structures/Interaction.d.ts +0 -113
- package/dist/structures/Interaction.js +0 -274
- package/dist/structures/Member.d.ts +0 -70
- package/dist/structures/Member.js +0 -124
- package/dist/structures/Message.d.ts +0 -87
- package/dist/structures/Message.js +0 -182
- package/dist/structures/Reaction.d.ts +0 -38
- package/dist/structures/Reaction.js +0 -64
- package/dist/structures/Role.d.ts +0 -43
- package/dist/structures/Role.js +0 -77
- package/dist/structures/User.d.ts +0 -41
- package/dist/structures/User.js +0 -79
- package/dist/structures/utils.d.ts +0 -72
- package/dist/structures/utils.js +0 -59
- package/dist/utils/errors.d.ts +0 -5
- package/dist/utils/errors.js +0 -28
- package/dist/utils/modules.d.ts +0 -39
- package/dist/utils/modules.js +0 -156
package/dist/index.d.ts
CHANGED
|
@@ -1,18 +1,55 @@
|
|
|
1
|
-
export
|
|
2
|
-
export type {
|
|
3
|
-
export {
|
|
4
|
-
export type {
|
|
5
|
-
export
|
|
6
|
-
export type {
|
|
7
|
-
export {
|
|
8
|
-
export {
|
|
9
|
-
export {
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export {
|
|
13
|
-
export {
|
|
14
|
-
export {
|
|
15
|
-
export {
|
|
16
|
-
export {
|
|
17
|
-
export type {
|
|
18
|
-
export
|
|
1
|
+
export { command } from './commands/command.js';
|
|
2
|
+
export type { AutocompleteContext, ChannelOption, CommandAutocomplete, CommandConfig, CommandContext, CommandInDm, CommandInGuild, CommandInPrivate, CommandWhere, CommandFile, CommandLocales, CommandOption, CommandOptions, CommandTranslation, Cooldown, Duration, NumberOption, OptionsSoFar, OptionTranslation, OptionValuesOf, SimpleOption, StringOption, Suggestion, } from './commands/command.js';
|
|
3
|
+
export type { CommandInteraction, ComponentInteraction, DmCommandInteraction, GuildCommandInteraction, PrivateCommandInteraction, Interaction, InteractionReply, InteractionReplyOptions, ModalInteraction, } from './structures/interaction.js';
|
|
4
|
+
export type { DynamicText, TextContext } from './components/component.js';
|
|
5
|
+
export { button } from './components/button.js';
|
|
6
|
+
export type { ButtonConfig, ButtonContext, ButtonFile, ButtonLook, ButtonStyleName, } from './components/button.js';
|
|
7
|
+
export { select } from './components/select.js';
|
|
8
|
+
export type { EntitySelectConfig, EntitySelectType, SelectConfig, SelectContext, SelectFile, SelectInstanceOptions, SelectLook, SelectType, StringSelectConfig, } from './components/select.js';
|
|
9
|
+
export { modal } from './components/modal.js';
|
|
10
|
+
export type { CheckboxField, CheckboxesField, EntityField, FieldValue, FieldValuesOf, FilesField, ModalConfig, ModalContext, ModalField, ModalFields, ModalFile, ModalInstanceOptions, ModalPrefill, NoteField, RadioField, SelectField, TextField, } from './components/modal.js';
|
|
11
|
+
export { embed } from './components/embed.js';
|
|
12
|
+
export type { EmbedFile } from './components/embed.js';
|
|
13
|
+
export type { ComponentWhere, ComponentWho, InDm, InGuild, InPrivate, InteractiveConfig, InteractiveContext, PlaceInDm, PlaceInGuild, PlaceInPrivate, PlaceOf, } from './components/component.js';
|
|
14
|
+
export type { DataField, DataInputOf, DataKind, DataShape, DataValuesOf, } from './components/custom-id.js';
|
|
15
|
+
export type { OptionValue, RichOption, SelectOptions, } from './components/options.js';
|
|
16
|
+
export { container, file, gallery, linkButton, premiumButton, row, section, separator, text, thumbnail, } from './components/layout.js';
|
|
17
|
+
export type { ContainerOptions, LinkButtonOptions, MediaOptions, SeparatorOptions, } from './components/layout.js';
|
|
18
|
+
export type { ActionRowComponent, ButtonComponent, ContainerChild, ContainerComponent, FileComponent, GalleryComponent, MessageComponent, ModalComponent, Piece, SectionComponent, SelectComponent, SeparatorComponent, TextComponent, ThumbnailComponent, } from './components/instance.js';
|
|
19
|
+
export type { ContextOf, EventWhere, WhereEventOptions, EventContexts, EventFile, EventName, EventOptions, MessageEventOptions, ReactionEventOptions, } from './events/registry.js';
|
|
20
|
+
export type { CategoryChannel, Channel, DMChannel, FetchMessagesOptions, ForumChannel, ForumPostOptions, ForumTag, GuildChannel, GuildChannelEditOptions, InviteCreateOptions, PermissionOverwrite, TextBasedChannel, GuildTextBasedChannel, TextChannel, ThreadChannel, ThreadCreateOptions, ThreadEditOptions, ThreadMember, VoiceChannel, } from './structures/channel.js';
|
|
21
|
+
export type { GuildEmoji } from './structures/emoji.js';
|
|
22
|
+
export type { AuditLog, AuditLogEntry, AutoModerationRule, Ban, ChannelCreateOptions, Guild, GuildEditOptions, RoleCreateOptions, ScheduledEvent, Sticker, VoiceState, } from './structures/guild.js';
|
|
23
|
+
export type { Invite } from './structures/invite.js';
|
|
24
|
+
export type { BanOptions, GuildMember, MemberEditOptions, } from './structures/member.js';
|
|
25
|
+
export type { Attachment, EmojiInput, DmMessage, GuildMessage, MemberMessage, Message, PrivateMessage, MessageFlagName, Reaction, ReactionEmoji, } from './structures/message.js';
|
|
26
|
+
export { language } from './messages/messages.js';
|
|
27
|
+
export type { CommandsTranslations, FrameworkTexts, LanguageConfig, LanguageFile, MessagesOf, MessageText, MessageTexts, PluralText, ProjectCommands, ParamsArgs, ParamsOf, Placeholders, ProjectLocale, ProjectLocales, LocaleGiven, ProjectMessages, TranslationContext, Translator, } from './messages/messages.js';
|
|
28
|
+
export { presence } from './presence/presence.js';
|
|
29
|
+
export type { Activity, ActivityKind, PlainActivity, PresenceConfig, PresenceFile, PresenceStatusName, StreamingActivity, } from './presence/presence.js';
|
|
30
|
+
export { task } from './tasks/task.js';
|
|
31
|
+
export type { CronTaskConfig, EveryTaskConfig, TaskConfig, TaskContext, TaskFile, } from './tasks/task.js';
|
|
32
|
+
export type { AssetFile, AssetOptions } from './assets/asset.js';
|
|
33
|
+
export type { AllowedMentions, Embed, FileInput, MessageEditOptions, MessageInput, MessageOptions, PollInput, } from './structures/payload.js';
|
|
34
|
+
export type { Role, RoleEditOptions } from './structures/role.js';
|
|
35
|
+
export type { User, UserFlagName, UserPresence } from './structures/user.js';
|
|
36
|
+
export type { Webhook, WebhookMessageOptions } from './structures/webhook.js';
|
|
37
|
+
export type { JoinOptions, VoiceConnection } from './voice/connection.js';
|
|
38
|
+
export type { AudioSource } from './voice/source.js';
|
|
39
|
+
export { DiscordApiError, DiscordUnavailableError, InvalidTokenError, } from './rest/errors.js';
|
|
40
|
+
export type { DiscordFieldError } from './rest/errors.js';
|
|
41
|
+
export { Permissions } from './discord/permissions.js';
|
|
42
|
+
export type { PermissionName, PermissionResolvable, } from './discord/permissions.js';
|
|
43
|
+
export { PermissionFlags } from './discord/types/permissions.js';
|
|
44
|
+
export { channelMention, commandMention, emojiMention, GuildNavigation, roleMention, timestamp, TimestampStyle, userMention, } from './discord/formatting.js';
|
|
45
|
+
export type { ImageFormat, ImageOptions, ImageSize } from './discord/cdn.js';
|
|
46
|
+
export { isSnowflake, snowflakeFromTimestamp, snowflakeTimestamp, } from './discord/snowflake.js';
|
|
47
|
+
export { ChannelType, ForumLayoutType, ForumSortOrderType, VideoQualityMode, } from './discord/types/channel.js';
|
|
48
|
+
export { Locale } from './discord/types/common.js';
|
|
49
|
+
export type { Snowflake } from './discord/types/common.js';
|
|
50
|
+
export { ButtonStyle, ComponentType, TextInputStyle, } from './discord/types/component.js';
|
|
51
|
+
export { DefaultMessageNotificationLevel, ExplicitContentFilterLevel, PremiumTier, VerificationLevel, } from './discord/types/guild.js';
|
|
52
|
+
export type { GuildFeature } from './discord/types/guild.js';
|
|
53
|
+
export { AuditLogEvent } from './discord/types/audit-log.js';
|
|
54
|
+
export { MessageFlags, MessageType } from './discord/types/message.js';
|
|
55
|
+
export { UserFlags } from './discord/types/user.js';
|
package/dist/index.js
CHANGED
|
@@ -1,12 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
// The public types of ChapterJS, and everything in its API that is the same
|
|
2
|
+
// wherever it is imported. What depends on the folder of the importing file
|
|
3
|
+
// (`event`...) is exported at runtime by `main.ts`, and typed for each
|
|
4
|
+
// folder of a project by the generated `.chapterjs/` (see
|
|
5
|
+
// `loader/generated.ts`): declaring it here too would make editors offer
|
|
6
|
+
// two imports of the same name.
|
|
7
|
+
//
|
|
8
|
+
// The public API of ChapterJS. User code gets structures from the framework
|
|
9
|
+
// (in events, commands...) and never creates them: classes are exported as
|
|
10
|
+
// types only, and nothing here lets user code connect to Discord or send
|
|
11
|
+
// requests by itself.
|
|
12
|
+
// Slash commands: what the files of src/commands/ are written with.
|
|
13
|
+
export { command } from './commands/command.js';
|
|
14
|
+
export { button } from './components/button.js';
|
|
15
|
+
export { select } from './components/select.js';
|
|
16
|
+
export { modal } from './components/modal.js';
|
|
17
|
+
export { embed } from './components/embed.js';
|
|
18
|
+
export { container, file, gallery, linkButton, premiumButton, row, section, separator, text, thumbnail, } from './components/layout.js';
|
|
19
|
+
// Tasks: what the files of src/tasks/ are written with.
|
|
20
|
+
export { language } from './messages/messages.js';
|
|
21
|
+
export { presence } from './presence/presence.js';
|
|
22
|
+
export { task } from './tasks/task.js';
|
|
23
|
+
// Errors handlers can catch.
|
|
24
|
+
export { DiscordApiError, DiscordUnavailableError, InvalidTokenError, } from './rest/errors.js';
|
|
25
|
+
// Permissions.
|
|
26
|
+
export { Permissions } from './discord/permissions.js';
|
|
27
|
+
export { PermissionFlags } from './discord/types/permissions.js';
|
|
28
|
+
// Helpers to write messages.
|
|
29
|
+
export { channelMention, commandMention, emojiMention, GuildNavigation, roleMention, timestamp, TimestampStyle, userMention, } from './discord/formatting.js';
|
|
30
|
+
export { isSnowflake, snowflakeFromTimestamp, snowflakeTimestamp, } from './discord/snowflake.js';
|
|
31
|
+
// The values Discord uses, by name.
|
|
32
|
+
export { ChannelType, ForumLayoutType, ForumSortOrderType, VideoQualityMode, } from './discord/types/channel.js';
|
|
33
|
+
export { Locale } from './discord/types/common.js';
|
|
34
|
+
export { ButtonStyle, ComponentType, TextInputStyle, } from './discord/types/component.js';
|
|
35
|
+
export { DefaultMessageNotificationLevel, ExplicitContentFilterLevel, PremiumTier, VerificationLevel, } from './discord/types/guild.js';
|
|
36
|
+
export { AuditLogEvent } from './discord/types/audit-log.js';
|
|
37
|
+
export { MessageFlags, MessageType } from './discord/types/message.js';
|
|
38
|
+
export { UserFlags } from './discord/types/user.js';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/** What a cooldown applies to: the person, the channel or the server. */
|
|
2
|
+
export type CooldownScope = 'user' | 'channel' | 'guild';
|
|
3
|
+
export declare const COOLDOWN_SCOPES: readonly CooldownScope[];
|
|
4
|
+
/** How long each scope waits, in milliseconds; `0` when it does not. */
|
|
5
|
+
export type CooldownLimits = Readonly<Record<CooldownScope, number>>;
|
|
6
|
+
/** No cooldown at all. */
|
|
7
|
+
export declare const NO_COOLDOWN: CooldownLimits;
|
|
8
|
+
/** Where the last uses are kept. */
|
|
9
|
+
export interface CooldownStore {
|
|
10
|
+
/** When `key` may be used again, as a timestamp; `0` when it may now. */
|
|
11
|
+
until(key: string, now: number): number;
|
|
12
|
+
/** Remembers that `key` may not be used again before `until`. */
|
|
13
|
+
set(key: string, until: number): void;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The default store: a `Map` in the memory of the process. It forgets
|
|
17
|
+
* what expired on its own, so it never grows with the uses of the past.
|
|
18
|
+
*/
|
|
19
|
+
export declare class MemoryCooldowns implements CooldownStore {
|
|
20
|
+
#private;
|
|
21
|
+
until(key: string, now: number): number;
|
|
22
|
+
set(key: string, until: number): void;
|
|
23
|
+
/** How many keys are remembered. */
|
|
24
|
+
get size(): number;
|
|
25
|
+
}
|
|
26
|
+
/** The ids a use is counted against, when they exist. */
|
|
27
|
+
export type CooldownIds = Readonly<Partial<Record<CooldownScope, string>>>;
|
|
28
|
+
/**
|
|
29
|
+
* Whether `name` may be used now by these ids, given its limits. Returns
|
|
30
|
+
* `0` and counts the use, or the time it may be used again (the latest
|
|
31
|
+
* of the scopes still waiting) and counts nothing.
|
|
32
|
+
*/
|
|
33
|
+
export declare function checkCooldown(store: CooldownStore, name: string, limits: CooldownLimits, ids: CooldownIds, now?: number): number;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
// Cooldowns: refusing something to a person, a channel or a server that
|
|
2
|
+
// used it a moment ago. Written once for every interaction that can have
|
|
3
|
+
// one (a command today). Where the last uses are kept is behind
|
|
4
|
+
// `CooldownStore`, with a store in memory as default: one shared between
|
|
5
|
+
// processes or machines is another implementation, and nothing else.
|
|
6
|
+
export const COOLDOWN_SCOPES = [
|
|
7
|
+
'user',
|
|
8
|
+
'channel',
|
|
9
|
+
'guild',
|
|
10
|
+
];
|
|
11
|
+
/** No cooldown at all. */
|
|
12
|
+
export const NO_COOLDOWN = Object.freeze({
|
|
13
|
+
user: 0,
|
|
14
|
+
channel: 0,
|
|
15
|
+
guild: 0,
|
|
16
|
+
});
|
|
17
|
+
/**
|
|
18
|
+
* The default store: a `Map` in the memory of the process. It forgets
|
|
19
|
+
* what expired on its own, so it never grows with the uses of the past.
|
|
20
|
+
*/
|
|
21
|
+
export class MemoryCooldowns {
|
|
22
|
+
#until = new Map();
|
|
23
|
+
#sweepAt = 1000;
|
|
24
|
+
until(key, now) {
|
|
25
|
+
const until = this.#until.get(key);
|
|
26
|
+
if (until === undefined)
|
|
27
|
+
return 0;
|
|
28
|
+
if (until <= now) {
|
|
29
|
+
this.#until.delete(key);
|
|
30
|
+
return 0;
|
|
31
|
+
}
|
|
32
|
+
return until;
|
|
33
|
+
}
|
|
34
|
+
set(key, until) {
|
|
35
|
+
this.#until.set(key, until);
|
|
36
|
+
if (this.#until.size >= this.#sweepAt)
|
|
37
|
+
this.#sweep(Date.now());
|
|
38
|
+
}
|
|
39
|
+
/** How many keys are remembered. */
|
|
40
|
+
get size() {
|
|
41
|
+
return this.#until.size;
|
|
42
|
+
}
|
|
43
|
+
/** Forgets what expired, and sweeps again when the rest doubled. */
|
|
44
|
+
#sweep(now) {
|
|
45
|
+
for (const [key, until] of this.#until) {
|
|
46
|
+
if (until <= now)
|
|
47
|
+
this.#until.delete(key);
|
|
48
|
+
}
|
|
49
|
+
this.#sweepAt = Math.max(1000, this.#until.size * 2);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Whether `name` may be used now by these ids, given its limits. Returns
|
|
54
|
+
* `0` and counts the use, or the time it may be used again (the latest
|
|
55
|
+
* of the scopes still waiting) and counts nothing.
|
|
56
|
+
*/
|
|
57
|
+
export function checkCooldown(store, name, limits, ids, now = Date.now()) {
|
|
58
|
+
const keys = [];
|
|
59
|
+
let until = 0;
|
|
60
|
+
for (const scope of COOLDOWN_SCOPES) {
|
|
61
|
+
const limit = limits[scope];
|
|
62
|
+
const id = ids[scope];
|
|
63
|
+
if (limit <= 0 || id === undefined)
|
|
64
|
+
continue;
|
|
65
|
+
const key = `${name}\0${scope}\0${id}`;
|
|
66
|
+
until = Math.max(until, store.until(key, now));
|
|
67
|
+
keys.push([key, now + limit]);
|
|
68
|
+
}
|
|
69
|
+
if (until > 0)
|
|
70
|
+
return until;
|
|
71
|
+
for (const [key, expires] of keys)
|
|
72
|
+
store.set(key, expires);
|
|
73
|
+
return 0;
|
|
74
|
+
}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import type { RawGuildMember } from '../discord/types/guild.js';
|
|
2
|
+
import type { RawInteraction } from '../discord/types/interaction.js';
|
|
3
|
+
import type { RawUser } from '../discord/types/user.js';
|
|
4
|
+
import { type FrameworkKey, type What } from '../messages/phrases.js';
|
|
5
|
+
import type { TextBasedChannel } from '../structures/channel.js';
|
|
6
|
+
import type { Context } from '../structures/context.js';
|
|
7
|
+
import type { Guild } from '../structures/guild.js';
|
|
8
|
+
import { type Interaction } from '../structures/interaction.js';
|
|
9
|
+
import type { GuildMember } from '../structures/member.js';
|
|
10
|
+
import type { User } from '../structures/user.js';
|
|
11
|
+
/** Where something can be used: the same word for commands and components. */
|
|
12
|
+
export type Where = 'guild' | 'dm' | 'both';
|
|
13
|
+
/** What the developer is told. */
|
|
14
|
+
export interface Reporter {
|
|
15
|
+
/** A `run` threw: reported with the file it comes from. */
|
|
16
|
+
onError: (file: string, error: unknown) => void;
|
|
17
|
+
/** Something the developer should know, that is not an error of theirs. */
|
|
18
|
+
onWarning: (file: string, message: string) => void;
|
|
19
|
+
/**
|
|
20
|
+
* After how long without an answer the framework defers, in milliseconds.
|
|
21
|
+
* Discord gives 3 seconds: the default leaves room for the request.
|
|
22
|
+
*/
|
|
23
|
+
deferAfter?: number;
|
|
24
|
+
}
|
|
25
|
+
/** Who did it, as Discord sent it: the member in a server, the user elsewhere. */
|
|
26
|
+
export declare function authorOf(raw: RawInteraction): {
|
|
27
|
+
user: RawUser;
|
|
28
|
+
member: RawGuildMember | undefined;
|
|
29
|
+
} | null;
|
|
30
|
+
/** Where an interaction happened, as its `run` receives it. */
|
|
31
|
+
export interface Place {
|
|
32
|
+
user: User;
|
|
33
|
+
guild: Guild | null;
|
|
34
|
+
member: GuildMember | null;
|
|
35
|
+
channel: TextBasedChannel;
|
|
36
|
+
/** In a server the bot is in, with the member. */
|
|
37
|
+
inGuild: boolean;
|
|
38
|
+
}
|
|
39
|
+
export type Placed = {
|
|
40
|
+
place: Place;
|
|
41
|
+
refusal?: undefined;
|
|
42
|
+
} | {
|
|
43
|
+
place?: undefined;
|
|
44
|
+
refusal: 'guildOnly' | 'dmOnly' | 'notHere';
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Where the interaction was used, checked against where `what` works.
|
|
48
|
+
* Returns the place, or what to tell the person when it can't run there.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolvePlace(ctx: Context, raw: RawInteraction, user: User, rawMember: RawGuildMember | undefined, where: Where, warn: (message: string) => void): Placed;
|
|
51
|
+
/** What `run` receives about the place, following `where`. */
|
|
52
|
+
export declare function placeContext(place: Place, where: Where): Record<string, unknown>;
|
|
53
|
+
/** A phrase of the framework, in the language of the person. */
|
|
54
|
+
export declare function says(interaction: Interaction, key: FrameworkKey, params?: {
|
|
55
|
+
what?: What;
|
|
56
|
+
permissions?: string;
|
|
57
|
+
count?: number;
|
|
58
|
+
when?: string;
|
|
59
|
+
}): string;
|
|
60
|
+
/**
|
|
61
|
+
* Answers with a private message, in the language of the person, and
|
|
62
|
+
* never fails.
|
|
63
|
+
*/
|
|
64
|
+
export declare function refuse(interaction: Interaction, key: FrameworkKey, params?: {
|
|
65
|
+
what?: What;
|
|
66
|
+
permissions?: string;
|
|
67
|
+
count?: number;
|
|
68
|
+
when?: string;
|
|
69
|
+
}): Promise<void>;
|
|
70
|
+
export interface RunOptions {
|
|
71
|
+
interaction: Interaction;
|
|
72
|
+
/** The file the function comes from. */
|
|
73
|
+
file: string;
|
|
74
|
+
/** How the thing is named in messages to the developer: `/ping`, `buttons/ban`. */
|
|
75
|
+
name: string;
|
|
76
|
+
/** What it is, for the person: "command", "button", "menu", "form". */
|
|
77
|
+
what: What;
|
|
78
|
+
reporter: Reporter;
|
|
79
|
+
/** What to tell Discord when the answer takes long. */
|
|
80
|
+
defer: () => Promise<void>;
|
|
81
|
+
/** What to tell the developer when `run` finishes without answering. */
|
|
82
|
+
unanswered: string;
|
|
83
|
+
run: () => unknown;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Runs the function of an interaction. Discord wants an answer within 3
|
|
87
|
+
* seconds: when `run` takes longer, the framework says the answer is
|
|
88
|
+
* coming. When `run` throws, the person gets a plain answer and the
|
|
89
|
+
* developer the error with its file and line.
|
|
90
|
+
*/
|
|
91
|
+
export declare function runInteraction(options: RunOptions): void;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// What every interaction shares, whatever runs for it (a command, a
|
|
2
|
+
// button, a menu, a form): who did it and where, whether it is allowed
|
|
3
|
+
// there, and how its function is run so that the person always gets an
|
|
4
|
+
// answer and the developer always gets the error. Written once here;
|
|
5
|
+
// `commands/router.ts` and `components/router.ts` add what is theirs.
|
|
6
|
+
import { setTimeout as sleep } from 'node:timers/promises';
|
|
7
|
+
import { phrase } from '../messages/phrases.js';
|
|
8
|
+
import { DiscordApiError } from '../rest/errors.js';
|
|
9
|
+
import { ctxOf } from '../structures/base.js';
|
|
10
|
+
import { isUpdating } from '../structures/interaction.js';
|
|
11
|
+
/** Who did it, as Discord sent it: the member in a server, the user elsewhere. */
|
|
12
|
+
export function authorOf(raw) {
|
|
13
|
+
const user = raw.member?.user ?? raw.user;
|
|
14
|
+
return user ? { user, member: raw.member } : null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Where the interaction was used, checked against where `what` works.
|
|
18
|
+
* Returns the place, or what to tell the person when it can't run there.
|
|
19
|
+
*/
|
|
20
|
+
export function resolvePlace(ctx, raw, user, rawMember, where, warn) {
|
|
21
|
+
// In a server Discord sends the member, in a private message the user.
|
|
22
|
+
const guild = raw.guild_id
|
|
23
|
+
? (ctx.cache.guilds.get(raw.guild_id) ?? null)
|
|
24
|
+
: null;
|
|
25
|
+
const member = raw.guild_id && rawMember
|
|
26
|
+
? ctx.entities.member(raw.guild_id, rawMember)
|
|
27
|
+
: null;
|
|
28
|
+
const inGuild = guild !== null && member !== null;
|
|
29
|
+
if (where === 'guild' && !inGuild) {
|
|
30
|
+
return { refusal: 'guildOnly' };
|
|
31
|
+
}
|
|
32
|
+
if (where === 'dm' && raw.guild_id) {
|
|
33
|
+
return { refusal: 'dmOnly' };
|
|
34
|
+
}
|
|
35
|
+
if (raw.guild_id && !inGuild) {
|
|
36
|
+
// A server the bot is not in: nothing of it is known.
|
|
37
|
+
return { refusal: 'notHere' };
|
|
38
|
+
}
|
|
39
|
+
// Discord sends the channel with the interaction: known without asking.
|
|
40
|
+
const channel = (raw.channel_id ? ctx.cache.channels.get(raw.channel_id) : undefined) ??
|
|
41
|
+
(raw.channel?.id
|
|
42
|
+
? ctx.entities.channel(raw.channel, raw.guild_id)
|
|
43
|
+
: undefined);
|
|
44
|
+
if (!channel?.isTextBased() || (!inGuild && !channel.isDM())) {
|
|
45
|
+
warn(`was used in a channel the bot can't answer in (${channel ? `type ${channel.type}` : 'Discord did not say which'}): it did not run.`);
|
|
46
|
+
return { refusal: 'notHere' };
|
|
47
|
+
}
|
|
48
|
+
return { place: { user, guild, member, channel, inGuild } };
|
|
49
|
+
}
|
|
50
|
+
/** What `run` receives about the place, following `where`. */
|
|
51
|
+
export function placeContext(place, where) {
|
|
52
|
+
// What a `run` receives follows where it works: nothing about a server
|
|
53
|
+
// exists for what only works in private messages.
|
|
54
|
+
return {
|
|
55
|
+
channel: place.channel,
|
|
56
|
+
...(where === 'dm' ? {} : { guild: place.guild, member: place.member }),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
/** A phrase of the framework, in the language of the person. */
|
|
60
|
+
export function says(interaction, key, params) {
|
|
61
|
+
return phrase(ctxOf(interaction), interaction.locale, key, params);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Answers with a private message, in the language of the person, and
|
|
65
|
+
* never fails.
|
|
66
|
+
*/
|
|
67
|
+
export function refuse(interaction, key, params) {
|
|
68
|
+
return interaction
|
|
69
|
+
.reply({ content: says(interaction, key, params), ephemeral: true })
|
|
70
|
+
.then(() => { }, () => { });
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Runs the function of an interaction. Discord wants an answer within 3
|
|
74
|
+
* seconds: when `run` takes longer, the framework says the answer is
|
|
75
|
+
* coming. When `run` throws, the person gets a plain answer and the
|
|
76
|
+
* developer the error with its file and line.
|
|
77
|
+
*/
|
|
78
|
+
export function runInteraction(options) {
|
|
79
|
+
const { interaction, file, name, reporter } = options;
|
|
80
|
+
const stop = new AbortController();
|
|
81
|
+
sleep(reporter.deferAfter ?? 2000, undefined, { signal: stop.signal })
|
|
82
|
+
.then(() => options.defer())
|
|
83
|
+
.catch(() => { });
|
|
84
|
+
new Promise(resolve => resolve(options.run()))
|
|
85
|
+
.then(() => {
|
|
86
|
+
if (!interaction.answered) {
|
|
87
|
+
reporter.onWarning(file, `${name} ${options.unanswered}`);
|
|
88
|
+
}
|
|
89
|
+
})
|
|
90
|
+
.catch((error) => {
|
|
91
|
+
reporter.onError(file, error);
|
|
92
|
+
// The person gets a plain answer, never the technical details.
|
|
93
|
+
const missingPermission = error instanceof DiscordApiError &&
|
|
94
|
+
(error.code === 50013 || error.code === 50001);
|
|
95
|
+
const content = missingPermission
|
|
96
|
+
? says(interaction, 'missingPermission')
|
|
97
|
+
: says(interaction, 'failed', { what: options.what });
|
|
98
|
+
const tell = isUpdating(interaction)
|
|
99
|
+
? // The pending answer is a change of a message: the bad news must
|
|
100
|
+
// not replace that message.
|
|
101
|
+
interaction.followUp({ content, ephemeral: true })
|
|
102
|
+
: interaction.deferred
|
|
103
|
+
? interaction.edit(content)
|
|
104
|
+
: interaction.answered
|
|
105
|
+
? interaction.followUp({ content, ephemeral: true })
|
|
106
|
+
: interaction.reply({ content, ephemeral: true });
|
|
107
|
+
tell.catch(() => { });
|
|
108
|
+
})
|
|
109
|
+
.finally(() => stop.abort());
|
|
110
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/** A folder of user files in which 'chapterjs' has its own types. */
|
|
2
|
+
export interface TypedFolder {
|
|
3
|
+
/** A unique name, used for file names: `events.memberJoin`. */
|
|
4
|
+
id: string;
|
|
5
|
+
/**
|
|
6
|
+
* The folder, from the project folder, with `/`. It may contain `**` to
|
|
7
|
+
* be found at any depth (inside `(group)` folders). It may also be one
|
|
8
|
+
* file (`src/messages/fr.ts`): a file whose 'chapterjs' is its own.
|
|
9
|
+
*/
|
|
10
|
+
folder: string;
|
|
11
|
+
/**
|
|
12
|
+
* What the project of this folder includes on top of its declarations:
|
|
13
|
+
* `shared` (what every file of the project gets, the default) and/or
|
|
14
|
+
* `main` (what the files outside typed folders get). A folder whose
|
|
15
|
+
* files `shared` refers to (a language file, which types `t` for every
|
|
16
|
+
* other file) takes `main` alone: through `shared`, the other files of
|
|
17
|
+
* its family would be checked with its declarations.
|
|
18
|
+
*/
|
|
19
|
+
includes?: readonly ('shared' | 'main')[];
|
|
20
|
+
/**
|
|
21
|
+
* The declarations 'chapterjs' has in this folder, on top of what the
|
|
22
|
+
* package exports. Written like a `.d.ts` that imports the package from
|
|
23
|
+
* `'#chapterjs'`.
|
|
24
|
+
*/
|
|
25
|
+
declarations: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Writes the `.chapterjs/` folder of a project. A file whose content did
|
|
29
|
+
* not change is left alone, so editors don't reload for nothing; what an
|
|
30
|
+
* older version wrote and this one does not is removed. `shared` is what
|
|
31
|
+
* 'chapterjs' declares in every file of the project, whatever its folder:
|
|
32
|
+
* a `declare module 'chapterjs'` augmentation, importing the package from
|
|
33
|
+
* `'#chapterjs'` like the declarations of a `TypedFolder`. `main` is the
|
|
34
|
+
* same for the files outside typed folders only.
|
|
35
|
+
* @returns how many files were written
|
|
36
|
+
*/
|
|
37
|
+
export declare function writeGenerated(projectDir: string, folders: readonly TypedFolder[], shared?: string, main?: string): Promise<number>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
// The `.chapterjs/` folder of a project: what the framework writes so that
|
|
2
|
+
// user files are typed from where they are, with nothing to write.
|
|
3
|
+
//
|
|
4
|
+
// A user file imports everything from 'chapterjs'. To give that import a
|
|
5
|
+
// different type in each conventional folder (`event()` in
|
|
6
|
+
// `src/events/memberJoin/` knows it receives a member), each such folder is
|
|
7
|
+
// its own TypeScript project, in which 'chapterjs' resolves to a generated
|
|
8
|
+
// declaration file: everything the package exports, plus what is specific
|
|
9
|
+
// to the folder. The tsconfig of the user project only references this
|
|
10
|
+
// folder; editors and `tsc -b` find the project of each file by themselves.
|
|
11
|
+
import { existsSync } from 'node:fs';
|
|
12
|
+
import { mkdir, readdir, readFile, rm, writeFile } from 'node:fs/promises';
|
|
13
|
+
import { dirname, join, relative, sep } from 'node:path';
|
|
14
|
+
import { fileURLToPath } from 'node:url';
|
|
15
|
+
const HEADER = '// Written by ChapterJS: do not edit, it is overwritten.\n';
|
|
16
|
+
const json = (value) => `${JSON.stringify(value, null, 2)}\n`;
|
|
17
|
+
/** How a file of `.chapterjs/types/` imports the real package. */
|
|
18
|
+
function packageSpecifier(projectDir) {
|
|
19
|
+
const installed = join(projectDir, 'node_modules', 'chapterjs');
|
|
20
|
+
const target = existsSync(installed)
|
|
21
|
+
? installed
|
|
22
|
+
: // No node_modules (some package managers): where this code runs from.
|
|
23
|
+
fileURLToPath(new URL('../..', import.meta.url));
|
|
24
|
+
const path = relative(join(projectDir, '.chapterjs', 'types'), target);
|
|
25
|
+
return `${path.split(sep).join('/')}/dist/index.js`;
|
|
26
|
+
}
|
|
27
|
+
/** Every file of `.chapterjs/`, by its path inside it. */
|
|
28
|
+
function generatedFiles(projectDir, folders, shared, main) {
|
|
29
|
+
const files = new Map();
|
|
30
|
+
const specifier = packageSpecifier(projectDir);
|
|
31
|
+
const types = (declarations) => `${HEADER}export * from '${specifier}';\n${declarations.replaceAll("'#chapterjs'", `'${specifier}'`)}`;
|
|
32
|
+
// The folder ignores itself: nothing to add to the project's .gitignore.
|
|
33
|
+
files.set('.gitignore', '*\n');
|
|
34
|
+
// What every file of the project gets, whatever its folder: written as
|
|
35
|
+
// an augmentation of 'chapterjs', so it adds to the package in the main
|
|
36
|
+
// project and to the generated types in the others, without a second
|
|
37
|
+
// copy of the package for editors to offer.
|
|
38
|
+
const everywhere = shared === '' ? [] : ['../types/shared.d.ts'];
|
|
39
|
+
if (shared !== '') {
|
|
40
|
+
files.set('types/shared.d.ts', `${HEADER}${shared.replaceAll("'#chapterjs'", `'${specifier}'`)}`);
|
|
41
|
+
}
|
|
42
|
+
// What only the files outside typed folders get, and the typed folders
|
|
43
|
+
// that ask for it (`includes`): the commands a language file may
|
|
44
|
+
// translate.
|
|
45
|
+
const mainOnly = main === '' ? [] : ['../types/main.d.ts'];
|
|
46
|
+
if (main !== '') {
|
|
47
|
+
files.set('types/main.d.ts', `${HEADER}${main.replaceAll("'#chapterjs'", `'${specifier}'`)}`);
|
|
48
|
+
}
|
|
49
|
+
// Files that are in no typed folder: 'chapterjs' is the package itself.
|
|
50
|
+
files.set('projects/main.json', json({
|
|
51
|
+
extends: '../../tsconfig.json',
|
|
52
|
+
include: ['../../src', ...everywhere, ...mainOnly],
|
|
53
|
+
exclude: folders.map(({ folder }) => `../../${folder}`),
|
|
54
|
+
}));
|
|
55
|
+
for (const { id, folder, declarations, includes } of folders) {
|
|
56
|
+
const more = (includes ?? ['shared']).flatMap(what => what === 'shared' ? everywhere : mainOnly);
|
|
57
|
+
files.set(`projects/${id}.json`, json({
|
|
58
|
+
extends: '../../tsconfig.json',
|
|
59
|
+
compilerOptions: { paths: { chapterjs: [`../types/${id}.d.ts`] } },
|
|
60
|
+
// The declaration file is listed too: a folder that does not exist
|
|
61
|
+
// yet is then a valid, empty project, typed as soon as it exists.
|
|
62
|
+
include: [`../../${folder}`, `../types/${id}.d.ts`, ...more],
|
|
63
|
+
}));
|
|
64
|
+
files.set(`types/${id}.d.ts`, types(declarations));
|
|
65
|
+
}
|
|
66
|
+
files.set('tsconfig.json', json({
|
|
67
|
+
files: [],
|
|
68
|
+
references: [
|
|
69
|
+
{ path: './projects/main.json' },
|
|
70
|
+
...folders.map(({ id }) => ({ path: `./projects/${id}.json` })),
|
|
71
|
+
],
|
|
72
|
+
}));
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Writes the `.chapterjs/` folder of a project. A file whose content did
|
|
77
|
+
* not change is left alone, so editors don't reload for nothing; what an
|
|
78
|
+
* older version wrote and this one does not is removed. `shared` is what
|
|
79
|
+
* 'chapterjs' declares in every file of the project, whatever its folder:
|
|
80
|
+
* a `declare module 'chapterjs'` augmentation, importing the package from
|
|
81
|
+
* `'#chapterjs'` like the declarations of a `TypedFolder`. `main` is the
|
|
82
|
+
* same for the files outside typed folders only.
|
|
83
|
+
* @returns how many files were written
|
|
84
|
+
*/
|
|
85
|
+
export async function writeGenerated(projectDir, folders, shared = '', main = '') {
|
|
86
|
+
const root = join(projectDir, '.chapterjs');
|
|
87
|
+
const files = generatedFiles(projectDir, folders, shared, main);
|
|
88
|
+
const existing = await readdir(root, {
|
|
89
|
+
recursive: true,
|
|
90
|
+
withFileTypes: true,
|
|
91
|
+
}).catch(() => []);
|
|
92
|
+
await Promise.all(existing
|
|
93
|
+
.filter(entry => entry.isFile())
|
|
94
|
+
.map(entry => join(entry.parentPath, entry.name))
|
|
95
|
+
.filter(path => !files.has(relative(root, path).split(sep).join('/')) &&
|
|
96
|
+
// What TypeScript itself leaves there to check faster next time,
|
|
97
|
+
// and what features remember between two runs.
|
|
98
|
+
!path.endsWith('.tsbuildinfo') &&
|
|
99
|
+
!relative(root, path).startsWith(`cache${sep}`) &&
|
|
100
|
+
// What `chapterjs build` made is not ours to remove.
|
|
101
|
+
!relative(root, path).startsWith(`build${sep}`))
|
|
102
|
+
.map(path => rm(path, { force: true })));
|
|
103
|
+
let written = 0;
|
|
104
|
+
await Promise.all([...files].map(async ([path, content]) => {
|
|
105
|
+
const target = join(root, path);
|
|
106
|
+
if ((await readFile(target, 'utf8').catch(() => null)) === content) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
await mkdir(dirname(target), { recursive: true });
|
|
110
|
+
await writeFile(target, content);
|
|
111
|
+
written++;
|
|
112
|
+
}));
|
|
113
|
+
return written;
|
|
114
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Takes over how the files under `dir` are loaded. Called once, before
|
|
3
|
+
* loading. With `reload`, `nextGeneration()` makes them load again.
|
|
4
|
+
*/
|
|
5
|
+
export declare function enableProjectLoader(dir: string, { reload }: {
|
|
6
|
+
reload: boolean;
|
|
7
|
+
}): void;
|
|
8
|
+
/** Makes the next imports load the files again. */
|
|
9
|
+
export declare function nextGeneration(): void;
|
|
10
|
+
/** Imports a file of the project, in its current version. */
|
|
11
|
+
export declare function importFile(path: string): Promise<Record<string, unknown>>;
|
|
12
|
+
/** Removes what hot reload adds to the paths shown in errors. */
|
|
13
|
+
export declare function cleanPath(text: string): string;
|