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.
- 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 +205 -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 +253 -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 +135 -0
- package/dist/cli/project.js +517 -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 +360 -0
- package/dist/commands/command.js +28 -0
- package/dist/commands/declaration.d.ts +77 -0
- package/dist/commands/declaration.js +492 -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 +47 -0
- package/dist/commands/tree.js +216 -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 +106 -0
- package/dist/components/component.d.ts +140 -0
- package/dist/components/component.js +39 -0
- package/dist/components/custom-id.d.ts +72 -0
- package/dist/components/custom-id.js +128 -0
- package/dist/components/declaration.d.ts +42 -0
- package/dist/components/declaration.js +342 -0
- package/dist/components/declared.d.ts +29 -0
- package/dist/components/declared.js +49 -0
- package/dist/components/embed.d.ts +29 -0
- package/dist/components/embed.js +11 -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 +245 -0
- package/dist/components/modal.js +398 -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 +19 -0
- package/dist/components/router.js +251 -0
- package/dist/components/select.d.ts +146 -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/declaration.d.ts +16 -0
- package/dist/events/declaration.js +80 -0
- package/dist/events/event.d.ts +45 -0
- package/dist/events/event.js +34 -0
- package/dist/events/registry.d.ts +697 -0
- package/dist/events/registry.js +839 -0
- package/dist/events/router.d.ts +46 -0
- package/dist/events/router.js +133 -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 +57 -18
- package/dist/index.js +40 -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 +10 -0
- package/dist/loader/generated.js +80 -0
- package/dist/loader/hot.d.ts +13 -0
- package/dist/loader/hot.js +85 -0
- package/dist/loader/loader.d.ts +85 -0
- package/dist/loader/loader.js +119 -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 +2 -0
- package/dist/main.js +5 -0
- package/dist/messages/commands.d.ts +23 -0
- package/dist/messages/commands.js +142 -0
- package/dist/messages/declaration.d.ts +89 -0
- package/dist/messages/declaration.js +455 -0
- package/dist/messages/messages.d.ts +241 -0
- package/dist/messages/messages.js +31 -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/declaration.d.ts +19 -0
- package/dist/presence/declaration.js +118 -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/declaration.d.ts +16 -0
- package/dist/tasks/declaration.js +56 -0
- package/dist/tasks/schedule.d.ts +54 -0
- package/dist/tasks/schedule.js +236 -0
- package/dist/tasks/scheduler.d.ts +35 -0
- package/dist/tasks/scheduler.js +107 -0
- package/dist/tasks/task.d.ts +75 -0
- package/dist/tasks/task.js +27 -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
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/** Where a declaration was found: a file of the project, and its export. */
|
|
2
|
+
export interface ExportSite {
|
|
3
|
+
/** The path from the project folder, with `/`: `src/moderation/ban.ts`. */
|
|
4
|
+
file: string;
|
|
5
|
+
/** The name of the export: `'ban'`, or `'default'`. */
|
|
6
|
+
export: string;
|
|
7
|
+
/**
|
|
8
|
+
* The name the export gives to what it declares: the name of the export,
|
|
9
|
+
* or the name of the file (without extension) for the default export.
|
|
10
|
+
*/
|
|
11
|
+
name: string;
|
|
12
|
+
}
|
|
13
|
+
/** A kind of declaration a feature reads from the exports of the files. */
|
|
14
|
+
export interface Declaration<T> {
|
|
15
|
+
/** What one is called in messages: "event", "command"... */
|
|
16
|
+
one: string;
|
|
17
|
+
many: string;
|
|
18
|
+
/** Whether a value is one of these, before it is read. */
|
|
19
|
+
is(value: unknown): boolean;
|
|
20
|
+
/**
|
|
21
|
+
* Whether a file may export several in a list. Only what names itself
|
|
22
|
+
* (an event, a command, a language) may: a list has no export name to
|
|
23
|
+
* give each one.
|
|
24
|
+
*/
|
|
25
|
+
list: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Checks a declaration and returns what the feature needs from it.
|
|
28
|
+
* Throws an error whose message says what to write.
|
|
29
|
+
*/
|
|
30
|
+
read(value: unknown, site: ExportSite): T;
|
|
31
|
+
}
|
|
32
|
+
/** A declaration, read, with where it comes from. */
|
|
33
|
+
export interface LoadedItem<T> extends ExportSite {
|
|
34
|
+
value: T;
|
|
35
|
+
}
|
|
36
|
+
/** An export the framework could not use, or a file that could not run. */
|
|
37
|
+
export interface FailedFile {
|
|
38
|
+
file: string;
|
|
39
|
+
/** The export that failed, when the file itself ran. */
|
|
40
|
+
export?: string;
|
|
41
|
+
error: unknown;
|
|
42
|
+
}
|
|
43
|
+
/** The declarations of one kind found in the files. */
|
|
44
|
+
export interface LoadResult<T> {
|
|
45
|
+
loaded: LoadedItem<T>[];
|
|
46
|
+
failed: FailedFile[];
|
|
47
|
+
}
|
|
48
|
+
/** What `file` is called in a message: `src/a.ts`, or `src/a.ts (ban)`. */
|
|
49
|
+
export declare const siteName: (site: {
|
|
50
|
+
file: string;
|
|
51
|
+
export?: string;
|
|
52
|
+
}) => string;
|
|
53
|
+
/** A file of the project, found but not run. */
|
|
54
|
+
export interface FoundFile {
|
|
55
|
+
/** The path from the project folder, with `/`: `src/ping.ts`. */
|
|
56
|
+
file: string;
|
|
57
|
+
/** Where it is on disk. */
|
|
58
|
+
path: string;
|
|
59
|
+
}
|
|
60
|
+
/** Every source file of `src/`, in a stable order. */
|
|
61
|
+
export declare function listSources(projectDir: string): Promise<FoundFile[]>;
|
|
62
|
+
/** A file of the project, run: what it exports. */
|
|
63
|
+
export interface LoadedModule {
|
|
64
|
+
/** The path from the project folder: `src/ping.ts`. */
|
|
65
|
+
file: string;
|
|
66
|
+
exports: Record<string, unknown>;
|
|
67
|
+
}
|
|
68
|
+
/** The files of the project, run (`modules`) or not (`failed`). */
|
|
69
|
+
export interface LoadedSources {
|
|
70
|
+
modules: LoadedModule[];
|
|
71
|
+
failed: FailedFile[];
|
|
72
|
+
}
|
|
73
|
+
/** Runs every file of `src/`. A file that fails to run never throws. */
|
|
74
|
+
export declare function loadSources(projectDir: string): Promise<LoadedSources>;
|
|
75
|
+
/**
|
|
76
|
+
* Reads the declarations of one kind from what the files export. Every
|
|
77
|
+
* export is looked at; the ones the kind recognises are read, the others
|
|
78
|
+
* are someone else's (another kind, or plain code). The same value
|
|
79
|
+
* exported twice (re-exported by another file) is one declaration, at the
|
|
80
|
+
* first place it is found. An export that can't be read is returned in
|
|
81
|
+
* `failed`, with its name, and never throws.
|
|
82
|
+
*/
|
|
83
|
+
export declare function readDeclarations<T>(modules: readonly LoadedModule[], declaration: Declaration<T>): LoadResult<T>;
|
|
84
|
+
/** A file of the project as a build kept it: already run. */
|
|
85
|
+
export type BuiltFile = LoadedModule;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
// Loads the files of a project and finds what they declare. Every source
|
|
2
|
+
// file under `src/` is loaded, wherever it is and whatever it is called:
|
|
3
|
+
// what the framework runs is what the files export, made with one of its
|
|
4
|
+
// functions (`command()`, `event()`, `button()`...). One mechanism for
|
|
5
|
+
// every feature: a feature only says how to recognise and read its
|
|
6
|
+
// declarations.
|
|
7
|
+
import { readdir } from 'node:fs/promises';
|
|
8
|
+
import { join, relative, sep } from 'node:path';
|
|
9
|
+
import { importFile } from './hot.js';
|
|
10
|
+
/** What `file` is called in a message: `src/a.ts`, or `src/a.ts (ban)`. */
|
|
11
|
+
export const siteName = (site) => site.export === undefined || site.export === 'default'
|
|
12
|
+
? site.file
|
|
13
|
+
: `${site.file} (${site.export})`;
|
|
14
|
+
const SOURCE = /\.(?:ts|mts|js|mjs)$/;
|
|
15
|
+
const DECLARATION = /\.d\.m?ts$/;
|
|
16
|
+
/** Tests next to the code: they are for a test runner, not for the bot. */
|
|
17
|
+
const TEST = /\.(?:test|spec)\.[^.]+$/;
|
|
18
|
+
/** The source files of a folder and its subfolders, in a stable order. */
|
|
19
|
+
async function scan(dir) {
|
|
20
|
+
let entries;
|
|
21
|
+
try {
|
|
22
|
+
entries = await readdir(dir, { withFileTypes: true });
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.code === 'ENOENT')
|
|
26
|
+
return [];
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
const files = [];
|
|
30
|
+
for (const entry of entries.sort((a, b) => (a.name < b.name ? -1 : 1))) {
|
|
31
|
+
const path = join(dir, entry.name);
|
|
32
|
+
if (entry.isDirectory())
|
|
33
|
+
files.push(...(await scan(path)));
|
|
34
|
+
else if (SOURCE.test(entry.name) &&
|
|
35
|
+
!DECLARATION.test(entry.name) &&
|
|
36
|
+
!TEST.test(entry.name)) {
|
|
37
|
+
files.push(path);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return files;
|
|
41
|
+
}
|
|
42
|
+
/** Every source file of `src/`, in a stable order. */
|
|
43
|
+
export async function listSources(projectDir) {
|
|
44
|
+
const paths = await scan(join(projectDir, 'src'));
|
|
45
|
+
return paths
|
|
46
|
+
.map(path => ({
|
|
47
|
+
file: relative(projectDir, path).split(sep).join('/'),
|
|
48
|
+
path,
|
|
49
|
+
}))
|
|
50
|
+
.sort((a, b) => (a.file < b.file ? -1 : 1));
|
|
51
|
+
}
|
|
52
|
+
/** Runs every file of `src/`. A file that fails to run never throws. */
|
|
53
|
+
export async function loadSources(projectDir) {
|
|
54
|
+
const found = await listSources(projectDir);
|
|
55
|
+
const result = { modules: [], failed: [] };
|
|
56
|
+
await Promise.all(found.map(async ({ file, path }) => {
|
|
57
|
+
try {
|
|
58
|
+
result.modules.push({ file, exports: await importFile(path) });
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
result.failed.push({ file, error });
|
|
62
|
+
}
|
|
63
|
+
}));
|
|
64
|
+
const byFile = (a, b) => a.file < b.file ? -1 : 1;
|
|
65
|
+
result.modules.sort(byFile);
|
|
66
|
+
result.failed.sort(byFile);
|
|
67
|
+
return result;
|
|
68
|
+
}
|
|
69
|
+
/** The name of a file, without its folders and its extension. */
|
|
70
|
+
const baseName = (file) => file
|
|
71
|
+
.split('/')
|
|
72
|
+
.pop()
|
|
73
|
+
.replace(/\.[^.]+$/, '');
|
|
74
|
+
/**
|
|
75
|
+
* Reads the declarations of one kind from what the files export. Every
|
|
76
|
+
* export is looked at; the ones the kind recognises are read, the others
|
|
77
|
+
* are someone else's (another kind, or plain code). The same value
|
|
78
|
+
* exported twice (re-exported by another file) is one declaration, at the
|
|
79
|
+
* first place it is found. An export that can't be read is returned in
|
|
80
|
+
* `failed`, with its name, and never throws.
|
|
81
|
+
*/
|
|
82
|
+
export function readDeclarations(modules, declaration) {
|
|
83
|
+
const result = { loaded: [], failed: [] };
|
|
84
|
+
const seen = new Set();
|
|
85
|
+
const sites = [...modules]
|
|
86
|
+
.sort((a, b) => (a.file < b.file ? -1 : 1))
|
|
87
|
+
.flatMap(({ file, exports }) => Object.keys(exports)
|
|
88
|
+
.sort()
|
|
89
|
+
.map(name => ({ file, export: name, value: exports[name] })));
|
|
90
|
+
for (const { file, export: exported, value } of sites) {
|
|
91
|
+
const site = {
|
|
92
|
+
file,
|
|
93
|
+
export: exported,
|
|
94
|
+
name: exported === 'default' ? baseName(file) : exported,
|
|
95
|
+
};
|
|
96
|
+
const read = (one) => {
|
|
97
|
+
if (seen.has(one))
|
|
98
|
+
return;
|
|
99
|
+
seen.add(one);
|
|
100
|
+
result.loaded.push({ ...site, value: declaration.read(one, site) });
|
|
101
|
+
};
|
|
102
|
+
try {
|
|
103
|
+
if (declaration.is(value))
|
|
104
|
+
read(value);
|
|
105
|
+
else if (Array.isArray(value) && value.some(declaration.is)) {
|
|
106
|
+
if (!declaration.list) {
|
|
107
|
+
throw new TypeError(`This export is a list with a ${declaration.one} in it: export each ${declaration.one} on its own (export const ${site.name} = ...), its name is the name of its export.`);
|
|
108
|
+
}
|
|
109
|
+
for (const one of value)
|
|
110
|
+
if (declaration.is(one))
|
|
111
|
+
read(one);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
result.failed.push({ file, export: exported, error });
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return result;
|
|
119
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where in the project an error comes from: the first place of its stack
|
|
3
|
+
* that is a file of the project (not a package, not Node itself).
|
|
4
|
+
*/
|
|
5
|
+
export declare function locate(error: unknown, projectDir: string): {
|
|
6
|
+
file: string;
|
|
7
|
+
line: number;
|
|
8
|
+
} | null;
|
|
9
|
+
/** The message of an error, on one line, without hot reload noise. */
|
|
10
|
+
export declare function messageOf(error: unknown): string;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { relative, sep } from 'node:path';
|
|
2
|
+
import { fileURLToPath } from 'node:url';
|
|
3
|
+
import { cleanPath } from './hot.js';
|
|
4
|
+
/**
|
|
5
|
+
* Where in the project an error comes from: the first place of its stack
|
|
6
|
+
* that is a file of the project (not a package, not Node itself).
|
|
7
|
+
*/
|
|
8
|
+
export function locate(error, projectDir) {
|
|
9
|
+
if (!(error instanceof Error) || typeof error.stack !== 'string')
|
|
10
|
+
return null;
|
|
11
|
+
const stack = cleanPath(error.stack);
|
|
12
|
+
// `file:///project/src/a.ts:3:7` in a stack frame, or `/project/src/a.ts:3`
|
|
13
|
+
// on the first line of a syntax error.
|
|
14
|
+
const pattern = /(file:\/\/[^\s():]+|(?:\/|[A-Za-z]:\\)[^\s():]+):(\d+)/g;
|
|
15
|
+
for (const match of stack.matchAll(pattern)) {
|
|
16
|
+
let path = match[1];
|
|
17
|
+
try {
|
|
18
|
+
if (path.startsWith('file://'))
|
|
19
|
+
path = fileURLToPath(path);
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
const inside = relative(projectDir, path);
|
|
25
|
+
if (inside.startsWith('..') || inside.split(sep).includes('node_modules')) {
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
return { file: inside.split(sep).join('/'), line: Number(match[2]) };
|
|
29
|
+
}
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
/** The message of an error, on one line, without hot reload noise. */
|
|
33
|
+
export function messageOf(error) {
|
|
34
|
+
const text = error instanceof Error ? error.message : `Thrown value: ${String(error)}`;
|
|
35
|
+
return cleanPath(text).trim();
|
|
36
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every file under a folder looks like right now: taken before the
|
|
3
|
+
* files are loaded, it lets `watchFolder` notice what was saved since.
|
|
4
|
+
*/
|
|
5
|
+
export declare function snapshotFolder(dir: string): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Calls `onChange` when files under `dir` are saved, once per burst: an
|
|
8
|
+
* editor often writes a file in several steps, and saving several files at
|
|
9
|
+
* once is one change.
|
|
10
|
+
*/
|
|
11
|
+
export declare function watchFolder(dir: string, onChange: () => void, { delay, loaded, }?: {
|
|
12
|
+
delay?: number;
|
|
13
|
+
/** The folder as it was when its files were loaded. */
|
|
14
|
+
loaded?: Promise<string>;
|
|
15
|
+
}): {
|
|
16
|
+
close(): void;
|
|
17
|
+
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { watch } from 'node:fs';
|
|
2
|
+
import { readdir, stat } from 'node:fs/promises';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
/**
|
|
5
|
+
* What every file under a folder looks like right now: taken before the
|
|
6
|
+
* files are loaded, it lets `watchFolder` notice what was saved since.
|
|
7
|
+
*/
|
|
8
|
+
export async function snapshotFolder(dir) {
|
|
9
|
+
const entries = await readdir(dir, {
|
|
10
|
+
recursive: true,
|
|
11
|
+
withFileTypes: true,
|
|
12
|
+
}).catch(() => []);
|
|
13
|
+
const files = await Promise.all(entries
|
|
14
|
+
.filter(entry => entry.isFile())
|
|
15
|
+
.map(async (entry) => {
|
|
16
|
+
const path = join(entry.parentPath, entry.name);
|
|
17
|
+
const info = await stat(path).catch(() => null);
|
|
18
|
+
return `${path}:${info?.mtimeMs ?? 0}:${info?.size ?? 0}`;
|
|
19
|
+
}));
|
|
20
|
+
return files.sort().join('\n');
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Calls `onChange` when files under `dir` are saved, once per burst: an
|
|
24
|
+
* editor often writes a file in several steps, and saving several files at
|
|
25
|
+
* once is one change.
|
|
26
|
+
*/
|
|
27
|
+
export function watchFolder(dir, onChange, { delay = 60, loaded = snapshotFolder(dir), } = {}) {
|
|
28
|
+
let timer = null;
|
|
29
|
+
let closed = false;
|
|
30
|
+
const changed = () => {
|
|
31
|
+
if (closed)
|
|
32
|
+
return;
|
|
33
|
+
if (timer)
|
|
34
|
+
clearTimeout(timer);
|
|
35
|
+
timer = setTimeout(() => {
|
|
36
|
+
timer = null;
|
|
37
|
+
onChange();
|
|
38
|
+
}, delay);
|
|
39
|
+
};
|
|
40
|
+
const watcher = watch(dir, { recursive: true }, changed);
|
|
41
|
+
// The folder being deleted is not a reason to crash the bot.
|
|
42
|
+
watcher.on('error', () => { });
|
|
43
|
+
// The system takes a moment to really start watching: a file saved
|
|
44
|
+
// between the load and that moment would be missed. The folder is
|
|
45
|
+
// compared, a little later, with what it was when it was loaded.
|
|
46
|
+
const before = loaded;
|
|
47
|
+
const catchUps = [300, 1500].map(wait => setTimeout(() => {
|
|
48
|
+
void Promise.all([before, snapshotFolder(dir)]).then(([then, now]) => {
|
|
49
|
+
if (then !== now && lastSeen !== now) {
|
|
50
|
+
lastSeen = now;
|
|
51
|
+
changed();
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
}, wait));
|
|
55
|
+
let lastSeen = null;
|
|
56
|
+
return {
|
|
57
|
+
close() {
|
|
58
|
+
closed = true;
|
|
59
|
+
if (timer)
|
|
60
|
+
clearTimeout(timer);
|
|
61
|
+
for (const catchUp of catchUps)
|
|
62
|
+
clearTimeout(catchUp);
|
|
63
|
+
watcher.close();
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
}
|
package/dist/main.d.ts
ADDED
package/dist/main.js
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
// What `import ... from 'chapterjs'` loads at runtime: the public API, plus
|
|
2
|
+
// `asset()`, whose type depends on the project it is imported from. Its
|
|
3
|
+
// type is not here but in the `.chapterjs/` folder of each project.
|
|
4
|
+
export * from './index.js';
|
|
5
|
+
export { asset } from './assets/asset.js';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type LoadedCommand } from '../commands/declaration.js';
|
|
2
|
+
import type { FailedFile } from '../loader/loader.js';
|
|
3
|
+
import type { LoadedMessages } from './translate.js';
|
|
4
|
+
/** A command given its texts by the language files. */
|
|
5
|
+
export interface TranslatedCommand {
|
|
6
|
+
/** The command, described; `null` when it can't be, said in `failed`. */
|
|
7
|
+
readonly command: LoadedCommand | null;
|
|
8
|
+
/** What is wrong, on the file it is wrong in. */
|
|
9
|
+
readonly failed: readonly FailedFile[];
|
|
10
|
+
}
|
|
11
|
+
/** The names the languages translate that no command has, by file. */
|
|
12
|
+
export declare function unknownCommands(messages: LoadedMessages, known: ReadonlySet<string>): {
|
|
13
|
+
file: string;
|
|
14
|
+
path: string;
|
|
15
|
+
}[];
|
|
16
|
+
/** Where the default language file is, or would be. */
|
|
17
|
+
export declare const defaultLanguageFile: (messages: LoadedMessages | null) => string;
|
|
18
|
+
/**
|
|
19
|
+
* Gives a command its texts from the languages, when its file does not
|
|
20
|
+
* describe it; refuses the languages that describe a command its file
|
|
21
|
+
* already does. What is wrong is reported on the file it is wrong in.
|
|
22
|
+
*/
|
|
23
|
+
export declare function translateCommand(file: string, command: LoadedCommand, messages: LoadedMessages | null): TranslatedCommand;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
// The `commands` of the language files: what Discord shows of each command
|
|
2
|
+
// in each language. A command has its texts in one place: in
|
|
3
|
+
// its file (`description`, `locales`), or in the language files, where the
|
|
4
|
+
// default language gives what Discord shows to everyone and the others
|
|
5
|
+
// their translations. Which one is decided by `description` in the file.
|
|
6
|
+
import { checkLocales, } from '../commands/declaration.js';
|
|
7
|
+
import { commandName } from '../commands/tree.js';
|
|
8
|
+
/** The names the languages translate that no command has, by file. */
|
|
9
|
+
export function unknownCommands(messages, known) {
|
|
10
|
+
const unknown = [];
|
|
11
|
+
for (const [locale, section] of messages.commands) {
|
|
12
|
+
for (const path of Object.keys(section)) {
|
|
13
|
+
if (!known.has(path)) {
|
|
14
|
+
unknown.push({ file: messages.files.get(locale), path });
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return unknown;
|
|
19
|
+
}
|
|
20
|
+
/** Where the default language file is, or would be. */
|
|
21
|
+
export const defaultLanguageFile = (messages) => messages?.files.get(messages.default) ?? 'the default language file';
|
|
22
|
+
/**
|
|
23
|
+
* Gives a command its texts from the languages, when its file does not
|
|
24
|
+
* describe it; refuses the languages that describe a command its file
|
|
25
|
+
* already does. What is wrong is reported on the file it is wrong in.
|
|
26
|
+
*/
|
|
27
|
+
export function translateCommand(file, command, messages) {
|
|
28
|
+
const path = command.path.join(' ');
|
|
29
|
+
const name = commandName(command.path);
|
|
30
|
+
const failed = [];
|
|
31
|
+
const languages = [...(messages?.commands ?? [])].filter(([, section]) => path in section);
|
|
32
|
+
if (command.described) {
|
|
33
|
+
for (const [locale] of languages) {
|
|
34
|
+
failed.push({
|
|
35
|
+
file: messages.files.get(locale),
|
|
36
|
+
error: new TypeError(`${name} is described in ${file}: remove its description there to translate it here, or remove it here.`),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return { command, failed };
|
|
40
|
+
}
|
|
41
|
+
const where = defaultLanguageFile(messages);
|
|
42
|
+
const example = (inside) => `${where} (commands: { ${JSON.stringify(path)}: { ${inside} } })`;
|
|
43
|
+
// Each language is checked on its own, so an error names its file.
|
|
44
|
+
const given = new Map();
|
|
45
|
+
for (const [locale, section] of languages) {
|
|
46
|
+
try {
|
|
47
|
+
given.set(locale, checkLocales({ [locale]: section[path] }, command.options));
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
failed.push({
|
|
51
|
+
file: messages.files.get(locale),
|
|
52
|
+
error: new TypeError(`In "commands", for ${name}: ${error instanceof Error ? error.message : String(error)}`),
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// The default language describes the command; when it does not, the
|
|
57
|
+
// first language that does (en-US first) is what Discord shows to all.
|
|
58
|
+
const order = messages
|
|
59
|
+
? [...given.keys()].sort((a, b) => a === messages.default
|
|
60
|
+
? -1
|
|
61
|
+
: b === messages.default
|
|
62
|
+
? 1
|
|
63
|
+
: a === 'en-US'
|
|
64
|
+
? -1
|
|
65
|
+
: b === 'en-US'
|
|
66
|
+
? 1
|
|
67
|
+
: a < b
|
|
68
|
+
? -1
|
|
69
|
+
: 1)
|
|
70
|
+
: [];
|
|
71
|
+
const mainLocale = order.find(locale => given.get(locale).descriptions[locale]) ??
|
|
72
|
+
messages?.default;
|
|
73
|
+
const main = mainLocale ? given.get(mainLocale) : undefined;
|
|
74
|
+
const description = mainLocale ? main?.descriptions[mainLocale] : undefined;
|
|
75
|
+
if (description === undefined) {
|
|
76
|
+
failed.push({
|
|
77
|
+
file,
|
|
78
|
+
error: new TypeError(`This command has no description: write it in ${example("description: '...'")}, or in the file (description: '...').`),
|
|
79
|
+
});
|
|
80
|
+
return { command: null, failed };
|
|
81
|
+
}
|
|
82
|
+
const options = [];
|
|
83
|
+
for (const option of command.options) {
|
|
84
|
+
const text = option.description ||
|
|
85
|
+
(mainLocale
|
|
86
|
+
? main?.optionLocales[option.name]?.descriptions[mainLocale]
|
|
87
|
+
: undefined);
|
|
88
|
+
if (!text) {
|
|
89
|
+
failed.push({
|
|
90
|
+
file,
|
|
91
|
+
error: new TypeError(`The option "${option.name}" of ${name} has no description: write it in ${example(`options: { ${option.name}: { description: '...' } }`)}, or in the file.`),
|
|
92
|
+
});
|
|
93
|
+
return { command: null, failed };
|
|
94
|
+
}
|
|
95
|
+
options.push({ ...option, description: text });
|
|
96
|
+
}
|
|
97
|
+
// The other languages are translations; the default one is what Discord
|
|
98
|
+
// shows to everyone, and needs none.
|
|
99
|
+
const names = {};
|
|
100
|
+
const descriptions = {};
|
|
101
|
+
const optionLocales = {};
|
|
102
|
+
for (const [locale, texts] of given) {
|
|
103
|
+
if (locale === mainLocale)
|
|
104
|
+
continue;
|
|
105
|
+
const text = texts.names[locale];
|
|
106
|
+
if (text !== undefined)
|
|
107
|
+
names[locale] = text;
|
|
108
|
+
const about = texts.descriptions[locale];
|
|
109
|
+
if (about !== undefined)
|
|
110
|
+
descriptions[locale] = about;
|
|
111
|
+
for (const [option, theirs] of Object.entries(texts.optionLocales)) {
|
|
112
|
+
const target = (optionLocales[option] ??= {
|
|
113
|
+
names: {},
|
|
114
|
+
descriptions: {},
|
|
115
|
+
choices: {},
|
|
116
|
+
});
|
|
117
|
+
const optionName = theirs.names[locale];
|
|
118
|
+
if (optionName !== undefined)
|
|
119
|
+
target.names[locale] = optionName;
|
|
120
|
+
const optionAbout = theirs.descriptions[locale];
|
|
121
|
+
if (optionAbout !== undefined)
|
|
122
|
+
target.descriptions[locale] = optionAbout;
|
|
123
|
+
for (const [choice, choiceTexts] of Object.entries(theirs.choices)) {
|
|
124
|
+
const choiceText = choiceTexts[locale];
|
|
125
|
+
if (choiceText !== undefined) {
|
|
126
|
+
(target.choices[choice] ??= {})[locale] = choiceText;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return {
|
|
132
|
+
command: {
|
|
133
|
+
...command,
|
|
134
|
+
description,
|
|
135
|
+
options: Object.freeze(options),
|
|
136
|
+
names,
|
|
137
|
+
descriptions,
|
|
138
|
+
optionLocales,
|
|
139
|
+
},
|
|
140
|
+
failed,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import type { Locale } from '../discord/types/common.js';
|
|
2
|
+
import { type Declaration, type ExportSite, type FailedFile } from '../loader/loader.js';
|
|
3
|
+
import { type LoadedMessages, type Template } from './translate.js';
|
|
4
|
+
/** A language, checked: what the languages are assembled from. */
|
|
5
|
+
export interface LoadedLanguage {
|
|
6
|
+
/** The language. */
|
|
7
|
+
readonly locale: Locale;
|
|
8
|
+
/** Whether it says it is the default language. */
|
|
9
|
+
readonly isDefault: boolean;
|
|
10
|
+
/** The texts, compiled. */
|
|
11
|
+
readonly texts: ReadonlyMap<string, Template>;
|
|
12
|
+
/** The phrases of the framework this file translates, compiled. */
|
|
13
|
+
readonly framework: ReadonlyMap<string, Template>;
|
|
14
|
+
/** The `commands` section, by the name of the command, not checked yet. */
|
|
15
|
+
readonly commands: Readonly<Record<string, unknown>> | undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A language, declared anywhere in `src/` with `language()`: `locale` says
|
|
19
|
+
* which one, `texts` what the bot says in it.
|
|
20
|
+
*/
|
|
21
|
+
export declare const languageDeclaration: Declaration<LoadedLanguage>;
|
|
22
|
+
/** A language as the project loaded it, with where it is declared. */
|
|
23
|
+
export interface LanguageEntry extends ExportSite {
|
|
24
|
+
readonly language: LoadedLanguage;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Puts the languages together: one default, which `t` is typed from and
|
|
28
|
+
* gives a text to the languages that do not have it, and every other
|
|
29
|
+
* language with texts the default has, the same placeholders included. A
|
|
30
|
+
* language that does not match is left out and reported on its file: the
|
|
31
|
+
* others still work. `null` when there is no language at all.
|
|
32
|
+
*/
|
|
33
|
+
export declare function assembleMessages(entries: readonly LanguageEntry[]): {
|
|
34
|
+
messages: LoadedMessages | null;
|
|
35
|
+
failed: FailedFile[];
|
|
36
|
+
};
|
|
37
|
+
/** A language, where it is declared. */
|
|
38
|
+
export interface DeclaredLanguage extends ExportSite {
|
|
39
|
+
readonly locale: Locale;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* The augmentation that types `t` from the files themselves: the editor
|
|
43
|
+
* reads every declaration of the default language directly, so the keys
|
|
44
|
+
* and placeholders follow every keystroke; the other languages take the
|
|
45
|
+
* texts they do not have from it. `languages` is every language declared,
|
|
46
|
+
* `defaultLocale` the one `t` is typed from (the first one when it is not
|
|
47
|
+
* known yet: `sync`, which runs nothing). Nothing when the project has no
|
|
48
|
+
* language.
|
|
49
|
+
*/
|
|
50
|
+
export declare function messagesDeclarations(languages: readonly DeclaredLanguage[], defaultLocale?: Locale): string;
|
|
51
|
+
/**
|
|
52
|
+
* The augmentation that underlines a second default language in the
|
|
53
|
+
* editor: when more than one language says `default: true` (`defaults`,
|
|
54
|
+
* the ones that do, known once the files ran), `language()` refuses
|
|
55
|
+
* `default: true` for each of them, so they are both underlined and not
|
|
56
|
+
* only reported in the console. Nothing when at most one says it.
|
|
57
|
+
*/
|
|
58
|
+
export declare function languageDefaultsDeclaration(defaults: readonly Locale[]): string;
|
|
59
|
+
/**
|
|
60
|
+
* The languages of a project, found without running its files: a text
|
|
61
|
+
* search for `language({ locale: '...' })` in the exports of each file.
|
|
62
|
+
* Approximate on purpose, for `sync`, which runs nothing: `dev` and
|
|
63
|
+
* `build` then write the exact ones. Returns the languages with the one
|
|
64
|
+
* that says `default: true`, when one does.
|
|
65
|
+
*/
|
|
66
|
+
export declare function scanLanguages(cwd: string): Promise<{
|
|
67
|
+
languages: DeclaredLanguage[];
|
|
68
|
+
defaultLocale?: Locale;
|
|
69
|
+
}>;
|
|
70
|
+
/** A command, and whether it has its own `description`. */
|
|
71
|
+
export interface DeclaredCommand {
|
|
72
|
+
/** `'ping'`, `'mod ban'` */
|
|
73
|
+
readonly name: string;
|
|
74
|
+
/**
|
|
75
|
+
* Whether the command gives its own texts; `false` when it is not
|
|
76
|
+
* known, like before the files ran: the language files may then
|
|
77
|
+
* describe it.
|
|
78
|
+
*/
|
|
79
|
+
readonly described: boolean;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* The augmentation that offers the commands of the project in the
|
|
83
|
+
* `commands` of a language: the name of each command, `true` when the
|
|
84
|
+
* language files describe it and `false` when the command has its own
|
|
85
|
+
* `description`, so that the editor only offers the first ones. Both come
|
|
86
|
+
* from running the files (`dev` and `build` know them, `sync` does not and
|
|
87
|
+
* offers any name). Nothing when the project has no command.
|
|
88
|
+
*/
|
|
89
|
+
export declare function commandsDeclarations(commands: readonly DeclaredCommand[]): string;
|