@jchat/addon-sdk 1.0.0-alpha.3 → 1.0.0-alpha.31
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/CHANGELOG.md +248 -0
- package/LICENSE +18 -196
- package/README.md +384 -20
- package/dist/cli.d.mts +54 -0
- package/dist/cli.mjs +154 -0
- package/dist/contracts.d.mts +2 -130
- package/dist/contracts.mjs +64 -0
- package/dist/contracts2.d.mts +282 -0
- package/dist/diagnostics.d.mts +55 -9
- package/dist/diagnostics.mjs +67 -2
- package/dist/i18n-validator.d.mts +23 -0
- package/dist/i18n-validator.mjs +95 -0
- package/dist/i18n.mjs +169 -0
- package/dist/index.d.mts +668 -90
- package/dist/index.mjs +5 -105
- package/dist/signing.d.mts +2 -0
- package/dist/signing.mjs +136 -0
- package/dist/signing2.d.mts +76 -0
- package/dist/src.mjs +493 -0
- package/dist/state.d.mts +1 -0
- package/dist/state.mjs +2 -0
- package/dist/testing.d.mts +2 -0
- package/dist/testing.mjs +2 -0
- package/dist/ui.d.mts +48 -0
- package/dist/ui.mjs +39 -0
- package/dist/vite.d.mts +64 -10
- package/dist/vite.mjs +231 -38
- package/package.json +125 -23
- package/skills/create-jchat-addon/SKILL.md +140 -0
- package/skills/jchat-addon-development/SKILL.md +260 -0
- package/src/tailwind.css +1 -0
- package/tsconfig.addon.json +20 -0
package/dist/contracts.d.mts
CHANGED
|
@@ -1,130 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Defines a single configuration field for an addon's settings panel. These are shown to site
|
|
5
|
-
* admins in the Jchat dashboard.
|
|
6
|
-
*/
|
|
7
|
-
interface ConfigSchemaField {
|
|
8
|
-
/** Unique key used to store and retrieve the value in `getConfig` */
|
|
9
|
-
key: string;
|
|
10
|
-
/** Data type for validation and UI rendering */
|
|
11
|
-
type: "string" | "number" | "boolean";
|
|
12
|
-
/** Human-readable label shown in the settings UI */
|
|
13
|
-
label: string;
|
|
14
|
-
/** If true, the admin must provide a value before saving */
|
|
15
|
-
required?: boolean;
|
|
16
|
-
/** Whether the value is sensitive (encrypted at rest and masked in the UI) */
|
|
17
|
-
secret?: boolean;
|
|
18
|
-
/** Default value pre-filled in the settings form for new installations */
|
|
19
|
-
default?: string | number | boolean;
|
|
20
|
-
}
|
|
21
|
-
/** Definition of a custom permission introduced by an addon. */
|
|
22
|
-
interface AddonPermissionDefinition {
|
|
23
|
-
/** Permission identifier (recommended: `addon.<id>.<action>`) */
|
|
24
|
-
name: string;
|
|
25
|
-
/** Short, human-readable name for the permission */
|
|
26
|
-
label: string;
|
|
27
|
-
/** Detailed description of what the permission grants (shown in Rank editor) */
|
|
28
|
-
description: string;
|
|
29
|
-
}
|
|
30
|
-
/** Valid locations where an addon can be rendered within the Jchat layout. */
|
|
31
|
-
declare const MOUNT_POINTS: {
|
|
32
|
-
/** Top of the main chat column */
|
|
33
|
-
readonly CHAT_HEADER: "chat-header";
|
|
34
|
-
/** Below the main chat header, above messages */
|
|
35
|
-
readonly CHAT_TOOLBAR: "chat-toolbar";
|
|
36
|
-
/** The persistent right-side sidebar */
|
|
37
|
-
readonly CHAT_SIDEBAR: "chat-sidebar";
|
|
38
|
-
/** Top of the left sidebar (room list) */
|
|
39
|
-
readonly SIDEBAR_TOP: "sidebar-top";
|
|
40
|
-
/** Bottom of the left sidebar */
|
|
41
|
-
readonly SIDEBAR_BOTTOM: "sidebar-bottom";
|
|
42
|
-
/** Action list shown when clicking a user's avatar */
|
|
43
|
-
readonly USER_POPOVER_ACTIONS: "user-popover-actions";
|
|
44
|
-
/** Menu shown when right-clicking a message */
|
|
45
|
-
readonly MESSAGE_CONTEXT_MENU: "message-context-menu";
|
|
46
|
-
/** Floating overlay rendered on top of the message stream */
|
|
47
|
-
readonly MESSAGE_FEED_OVERLAY: "message-feed-overlay";
|
|
48
|
-
/** Main admin dashboard area */
|
|
49
|
-
readonly ADMIN_PANEL: "admin-panel";
|
|
50
|
-
/** User or site settings dashboard area */
|
|
51
|
-
readonly SETTINGS_PANEL: "settings-panel";
|
|
52
|
-
/** The 'plus' (+) menu in the message composer */
|
|
53
|
-
readonly CHAT_PLUS_MENU: "chat-plus-menu";
|
|
54
|
-
/** Custom tab in the emoji/gif selection panel */
|
|
55
|
-
readonly EMOJI_PICKER_GIF_TAB: "emoji-picker-gif-tab";
|
|
56
|
-
/** Full-screen or modal dialog specifically for TubeScan */
|
|
57
|
-
readonly TUBESCAN_DIALOG: "tubescan-dialog";
|
|
58
|
-
};
|
|
59
|
-
/** Union type of all valid addon mount points. */
|
|
60
|
-
type MountPoint = (typeof MOUNT_POINTS)[keyof typeof MOUNT_POINTS];
|
|
61
|
-
/**
|
|
62
|
-
* The `manifest.json` schema required for every Jchat addon. This file describes how the addon is
|
|
63
|
-
* identified and mounted.
|
|
64
|
-
*/
|
|
65
|
-
interface AddonManifest {
|
|
66
|
-
/** Unique kebab-case addon identifier (must match the folder name) */
|
|
67
|
-
id: string;
|
|
68
|
-
/** Human-readable addon name */
|
|
69
|
-
name: string;
|
|
70
|
-
/** Semver version string (e.g. `1.2.0`) */
|
|
71
|
-
version: string;
|
|
72
|
-
/** Brief summary of what the addon does */
|
|
73
|
-
description?: string;
|
|
74
|
-
/** Author name, organization, or GitHub handle */
|
|
75
|
-
author?: string;
|
|
76
|
-
/** Support or documentation URL */
|
|
77
|
-
homepage?: string;
|
|
78
|
-
/** SPDX license identifier (e.g. `MIT`) */
|
|
79
|
-
license?: string;
|
|
80
|
-
/** Host and SDK versions this directly executed plugin was built and tested against */
|
|
81
|
-
compatibility: {
|
|
82
|
-
/** Supported JChat versions as a semantic-version range, for example `^1.0.0` */
|
|
83
|
-
jchat: string;
|
|
84
|
-
/** Supported `@jchat/addon-sdk` versions as a semantic-version range */
|
|
85
|
-
addonSdk: string;
|
|
86
|
-
};
|
|
87
|
-
/** Identity of the trusted publisher that signed this package. Required when migrations exist */
|
|
88
|
-
publisher?: {
|
|
89
|
-
id: string;
|
|
90
|
-
};
|
|
91
|
-
/** Signature over the canonical archive digest. Required when migrations exist */
|
|
92
|
-
signature?: {
|
|
93
|
-
algorithm: "rsa-sha256";
|
|
94
|
-
digest: string;
|
|
95
|
-
value: string;
|
|
96
|
-
};
|
|
97
|
-
/** Configuration for the React-based frontend bundle */
|
|
98
|
-
frontend?: {
|
|
99
|
-
/** Relative path to the pre-compiled ESM bundle (created by Vite) */
|
|
100
|
-
bundle: string;
|
|
101
|
-
/** List of UI locations where this addon should be active */
|
|
102
|
-
mountPoints: MountPoint[];
|
|
103
|
-
/** Optional path to a specific UI for the settings panel */
|
|
104
|
-
settings?: string;
|
|
105
|
-
/** Additional shared packages this addon imports from the host */
|
|
106
|
-
externals?: string[];
|
|
107
|
-
};
|
|
108
|
-
/** Configuration for the server-side API bundle */
|
|
109
|
-
server?: {
|
|
110
|
-
/** Relative path to the pre-compiled server bundle */
|
|
111
|
-
bundle?: string;
|
|
112
|
-
/** List of SQL files to run (in order) to set up the addon's database tables */
|
|
113
|
-
migrations?: string[];
|
|
114
|
-
/** List of declarative JSON master-data files to apply once, in order */
|
|
115
|
-
seeds?: string[];
|
|
116
|
-
};
|
|
117
|
-
/**
|
|
118
|
-
* The minimum permission required to see or use this addon. If provided, the host gates
|
|
119
|
-
* visibility in the UI and access to all server routes.
|
|
120
|
-
*/
|
|
121
|
-
accessPermission?: AddonPermission;
|
|
122
|
-
/** Full list of all permissions used by this addon for informational purposes */
|
|
123
|
-
permissions?: AddonPermission[];
|
|
124
|
-
/** Custom permissions that should be registered with the host application on installation */
|
|
125
|
-
permissionDefinitions?: AddonPermissionDefinition[];
|
|
126
|
-
/** Settings form structure shown to site admins. Values are stored encrypted per site */
|
|
127
|
-
configSchema?: ConfigSchemaField[];
|
|
128
|
-
}
|
|
129
|
-
//#endregion
|
|
130
|
-
export { MOUNT_POINTS as a, ConfigSchemaField as i, AddonPermission as n, MountPoint as o, AddonPermissionDefinition as r, AddonManifest as t };
|
|
1
|
+
import { S as ResilientFetchOptions, _ as AddonUser, a as AddonChatMessage, b as MOUNT_POINTS, c as AddonDistribution, d as AddonRequestUser, f as AddonResilientFetch, g as AddonRuntimeLogSource, h as AddonRuntimeLogLevel, i as AddonAttachment, l as AddonManifest, m as AddonRuntimeLogFilter, n as ActiveAddonFrontend, o as AddonCommandDefinition, p as AddonRuntimeLog, r as AddonArchiveFile, s as AddonCommandParameter, t as ActiveAddon, u as AddonPermissionDefinition, v as HOST_LOCALES, x as MountPoint, y as HostLocale } from "./contracts2.mjs";
|
|
2
|
+
export { ActiveAddon, ActiveAddonFrontend, AddonArchiveFile, AddonAttachment, AddonChatMessage, AddonCommandDefinition, AddonCommandParameter, AddonDistribution, AddonManifest, AddonPermissionDefinition, AddonRequestUser, AddonResilientFetch, AddonRuntimeLog, AddonRuntimeLogFilter, AddonRuntimeLogLevel, AddonRuntimeLogSource, AddonUser, HOST_LOCALES, HostLocale, MOUNT_POINTS, MountPoint, ResilientFetchOptions };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
//#region src/contracts.ts
|
|
2
|
+
/** Valid locations where an addon can be rendered within the Jchat layout. */
|
|
3
|
+
const MOUNT_POINTS = {
|
|
4
|
+
/** Top of the main chat column */
|
|
5
|
+
CHAT_HEADER: "chat-header",
|
|
6
|
+
/** Below the main chat header, above messages */
|
|
7
|
+
CHAT_TOOLBAR: "chat-toolbar",
|
|
8
|
+
/** The persistent right-side sidebar */
|
|
9
|
+
CHAT_SIDEBAR: "chat-sidebar",
|
|
10
|
+
/** Top of the left sidebar (room list) */
|
|
11
|
+
SIDEBAR_TOP: "sidebar-top",
|
|
12
|
+
/** Bottom of the left sidebar */
|
|
13
|
+
SIDEBAR_BOTTOM: "sidebar-bottom",
|
|
14
|
+
/** Action list shown when clicking a user's avatar */
|
|
15
|
+
USER_POPOVER_ACTIONS: "user-popover-actions",
|
|
16
|
+
/** Menu shown when right-clicking a message */
|
|
17
|
+
MESSAGE_CONTEXT_MENU: "message-context-menu",
|
|
18
|
+
/** Floating overlay rendered on top of the message stream */
|
|
19
|
+
MESSAGE_FEED_OVERLAY: "message-feed-overlay",
|
|
20
|
+
/** Main admin dashboard area */
|
|
21
|
+
ADMIN_PANEL: "admin-panel",
|
|
22
|
+
/** User or site settings dashboard area */
|
|
23
|
+
SETTINGS_PANEL: "settings-panel",
|
|
24
|
+
/** The 'plus' (+) menu in the message composer */
|
|
25
|
+
CHAT_PLUS_MENU: "chat-plus-menu",
|
|
26
|
+
/** Custom tab in the emoji/gif selection panel */
|
|
27
|
+
EMOJI_PICKER_GIF_TAB: "emoji-picker-gif-tab",
|
|
28
|
+
/** Custom tab in the emoji/sticker selection panel */
|
|
29
|
+
EMOJI_PICKER_STICKER_TAB: "emoji-picker-sticker-tab",
|
|
30
|
+
/** Dedicated settings panel rendered in the Owner Dashboard */
|
|
31
|
+
OWNER_SETTINGS: "owner-settings",
|
|
32
|
+
/** Dedicated settings panel rendered in the Site Admin Dashboard */
|
|
33
|
+
ADDON_SETTINGS: "addon-settings",
|
|
34
|
+
/** Custom interactive card rendered inside an enriched chat message */
|
|
35
|
+
CHAT_MESSAGE_CARD: "chat-message-card",
|
|
36
|
+
/** Custom badge, audio equalizer, or particle aura rendered on a chat bubble */
|
|
37
|
+
CHAT_MESSAGE_FLAIR: "chat-message-flair",
|
|
38
|
+
/** Custom interactive preview card rendered in the message composer */
|
|
39
|
+
CHAT_COMPOSER_PREVIEW: "chat-composer-preview"
|
|
40
|
+
};
|
|
41
|
+
const HOST_LOCALES = [
|
|
42
|
+
"ar",
|
|
43
|
+
"bg",
|
|
44
|
+
"hr",
|
|
45
|
+
"de",
|
|
46
|
+
"el",
|
|
47
|
+
"en",
|
|
48
|
+
"es",
|
|
49
|
+
"fr",
|
|
50
|
+
"he",
|
|
51
|
+
"hi",
|
|
52
|
+
"kn",
|
|
53
|
+
"ml",
|
|
54
|
+
"nl",
|
|
55
|
+
"pt",
|
|
56
|
+
"ro",
|
|
57
|
+
"ru",
|
|
58
|
+
"ta",
|
|
59
|
+
"te",
|
|
60
|
+
"tr",
|
|
61
|
+
"ur"
|
|
62
|
+
];
|
|
63
|
+
//#endregion
|
|
64
|
+
export { HOST_LOCALES, MOUNT_POINTS };
|
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
//#region src/contracts.d.ts
|
|
2
|
+
/** Definition of a custom permission introduced by an addon. */
|
|
3
|
+
interface AddonPermissionDefinition {
|
|
4
|
+
/** Permission identifier (recommended: `addon.<id>.<action>`) */
|
|
5
|
+
name: string;
|
|
6
|
+
/** Short, human-readable name for the permission */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Detailed description of what the permission grants (shown in Rank editor) */
|
|
9
|
+
description: string;
|
|
10
|
+
}
|
|
11
|
+
/** Valid locations where an addon can be rendered within the Jchat layout. */
|
|
12
|
+
declare const MOUNT_POINTS: {
|
|
13
|
+
/** Top of the main chat column */
|
|
14
|
+
readonly CHAT_HEADER: "chat-header";
|
|
15
|
+
/** Below the main chat header, above messages */
|
|
16
|
+
readonly CHAT_TOOLBAR: "chat-toolbar";
|
|
17
|
+
/** The persistent right-side sidebar */
|
|
18
|
+
readonly CHAT_SIDEBAR: "chat-sidebar";
|
|
19
|
+
/** Top of the left sidebar (room list) */
|
|
20
|
+
readonly SIDEBAR_TOP: "sidebar-top";
|
|
21
|
+
/** Bottom of the left sidebar */
|
|
22
|
+
readonly SIDEBAR_BOTTOM: "sidebar-bottom";
|
|
23
|
+
/** Action list shown when clicking a user's avatar */
|
|
24
|
+
readonly USER_POPOVER_ACTIONS: "user-popover-actions";
|
|
25
|
+
/** Menu shown when right-clicking a message */
|
|
26
|
+
readonly MESSAGE_CONTEXT_MENU: "message-context-menu";
|
|
27
|
+
/** Floating overlay rendered on top of the message stream */
|
|
28
|
+
readonly MESSAGE_FEED_OVERLAY: "message-feed-overlay";
|
|
29
|
+
/** Main admin dashboard area */
|
|
30
|
+
readonly ADMIN_PANEL: "admin-panel";
|
|
31
|
+
/** User or site settings dashboard area */
|
|
32
|
+
readonly SETTINGS_PANEL: "settings-panel";
|
|
33
|
+
/** The 'plus' (+) menu in the message composer */
|
|
34
|
+
readonly CHAT_PLUS_MENU: "chat-plus-menu";
|
|
35
|
+
/** Custom tab in the emoji/gif selection panel */
|
|
36
|
+
readonly EMOJI_PICKER_GIF_TAB: "emoji-picker-gif-tab";
|
|
37
|
+
/** Custom tab in the emoji/sticker selection panel */
|
|
38
|
+
readonly EMOJI_PICKER_STICKER_TAB: "emoji-picker-sticker-tab";
|
|
39
|
+
/** Dedicated settings panel rendered in the Owner Dashboard */
|
|
40
|
+
readonly OWNER_SETTINGS: "owner-settings";
|
|
41
|
+
/** Dedicated settings panel rendered in the Site Admin Dashboard */
|
|
42
|
+
readonly ADDON_SETTINGS: "addon-settings";
|
|
43
|
+
/** Custom interactive card rendered inside an enriched chat message */
|
|
44
|
+
readonly CHAT_MESSAGE_CARD: "chat-message-card";
|
|
45
|
+
/** Custom badge, audio equalizer, or particle aura rendered on a chat bubble */
|
|
46
|
+
readonly CHAT_MESSAGE_FLAIR: "chat-message-flair";
|
|
47
|
+
/** Custom interactive preview card rendered in the message composer */
|
|
48
|
+
readonly CHAT_COMPOSER_PREVIEW: "chat-composer-preview";
|
|
49
|
+
};
|
|
50
|
+
/** Union type of all valid addon mount points. */
|
|
51
|
+
type MountPoint = (typeof MOUNT_POINTS)[keyof typeof MOUNT_POINTS];
|
|
52
|
+
/** Parameter specification for an addon slash command. */
|
|
53
|
+
interface AddonCommandParameter {
|
|
54
|
+
name: string;
|
|
55
|
+
description?: string;
|
|
56
|
+
required?: boolean;
|
|
57
|
+
}
|
|
58
|
+
/** Declaration of an addon slash command available in the chat composer. */
|
|
59
|
+
interface AddonCommandDefinition {
|
|
60
|
+
/** The command keyword without leading slash (e.g. 'yt', 'roll', 'poll') */
|
|
61
|
+
name: string;
|
|
62
|
+
/** Short summary of what the command does, displayed in autocomplete */
|
|
63
|
+
description: string;
|
|
64
|
+
/** Usage syntax displayed as a hint (e.g. '<query | url>') */
|
|
65
|
+
syntax?: string;
|
|
66
|
+
/** Parameters accepted by this command */
|
|
67
|
+
parameters?: AddonCommandParameter[];
|
|
68
|
+
}
|
|
69
|
+
/** Distribution model for an addon package. Defaults to `'free'` if omitted. */
|
|
70
|
+
type AddonDistribution = "free" | "commercial";
|
|
71
|
+
/**
|
|
72
|
+
* The `manifest.json` schema required for every Jchat addon. This file describes how the addon is
|
|
73
|
+
* identified and mounted.
|
|
74
|
+
*/
|
|
75
|
+
interface AddonManifest {
|
|
76
|
+
/** Unique kebab-case addon identifier (must match the folder name) */
|
|
77
|
+
id: string;
|
|
78
|
+
/** Human-readable addon name */
|
|
79
|
+
name: string;
|
|
80
|
+
/** Semver version string (e.g. `1.2.0`) */
|
|
81
|
+
version: string;
|
|
82
|
+
/**
|
|
83
|
+
* Relative path to the addon's logo image asset (e.g. `./assets/logo.svg`, `./assets/logo.png`,
|
|
84
|
+
* or `./assets/logo.webp`). Recommended square 1:1 aspect ratio, max 512 KB.
|
|
85
|
+
*/
|
|
86
|
+
logo: string;
|
|
87
|
+
/** Brief summary of what the addon does */
|
|
88
|
+
description?: string;
|
|
89
|
+
/** Author name, organization, or GitHub handle */
|
|
90
|
+
author?: string;
|
|
91
|
+
/** Support or documentation URL */
|
|
92
|
+
homepage?: string;
|
|
93
|
+
/** SPDX license identifier (e.g. `MIT`) */
|
|
94
|
+
license?: string;
|
|
95
|
+
/**
|
|
96
|
+
* Distribution model: `'free'` (default) for open/free addons, or `'commercial'` for paid addons
|
|
97
|
+
* requiring purchase entitlement verification.
|
|
98
|
+
*/
|
|
99
|
+
distribution?: AddonDistribution;
|
|
100
|
+
/**
|
|
101
|
+
* Supported language codes (e.g. ["ar", "de", "en", "es", "fr", "hi", "kn", "ml", "ta", "te",
|
|
102
|
+
* "ur"])
|
|
103
|
+
*/
|
|
104
|
+
locales?: string[];
|
|
105
|
+
/** Default fallback language code (e.g. "en") */
|
|
106
|
+
defaultLocale?: string;
|
|
107
|
+
/** Host and SDK versions this directly executed plugin was built and tested against */
|
|
108
|
+
compatibility: {
|
|
109
|
+
/** Supported JChat versions as a semantic-version range, for example `^1.0.0` */
|
|
110
|
+
jchat: string;
|
|
111
|
+
/** Supported `@jchat/addon-sdk` versions as a semantic-version range */
|
|
112
|
+
addonSdk: string;
|
|
113
|
+
};
|
|
114
|
+
/** Identity of the trusted publisher that signed this package. Required when migrations exist */
|
|
115
|
+
publisher?: {
|
|
116
|
+
id: string;
|
|
117
|
+
};
|
|
118
|
+
/** Signature over the canonical archive digest. Required when migrations exist */
|
|
119
|
+
signature?: {
|
|
120
|
+
algorithm: "rsa-sha256";
|
|
121
|
+
digest: string;
|
|
122
|
+
value: string;
|
|
123
|
+
};
|
|
124
|
+
/** Configuration for the React-based frontend bundle */
|
|
125
|
+
frontend?: {
|
|
126
|
+
/** Relative path to the pre-compiled ESM bundle (created by Vite) */
|
|
127
|
+
bundle: string;
|
|
128
|
+
/** List of UI locations where this addon should be active */
|
|
129
|
+
mountPoints: MountPoint[];
|
|
130
|
+
/** Optional path to a specific UI for the settings panel */
|
|
131
|
+
settings?: string;
|
|
132
|
+
/** Additional shared packages this addon imports from the host */
|
|
133
|
+
externals?: string[];
|
|
134
|
+
};
|
|
135
|
+
/** Configuration for the server-side API bundle */
|
|
136
|
+
server?: {
|
|
137
|
+
/** Relative path to the pre-compiled server bundle */
|
|
138
|
+
bundle?: string;
|
|
139
|
+
/** List of SQL files to run (in order) to set up the addon's database tables */
|
|
140
|
+
migrations?: string[];
|
|
141
|
+
/** List of declarative JSON master-data files to apply once, in order */
|
|
142
|
+
seeds?: string[];
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* The minimum permission required to see or use this addon. If provided, the host gates
|
|
146
|
+
* visibility in the UI and access to all server routes.
|
|
147
|
+
*/
|
|
148
|
+
accessPermission?: string;
|
|
149
|
+
/** Full list of all permissions used by this addon for informational purposes */
|
|
150
|
+
permissions?: string[];
|
|
151
|
+
/** Custom permissions that should be registered with the host application on installation */
|
|
152
|
+
permissionDefinitions?: AddonPermissionDefinition[];
|
|
153
|
+
/** Interactive slash commands exposed in the chat composer */
|
|
154
|
+
commands?: AddonCommandDefinition[];
|
|
155
|
+
}
|
|
156
|
+
declare const HOST_LOCALES: readonly ["ar", "bg", "hr", "de", "el", "en", "es", "fr", "he", "hi", "kn", "ml", "nl", "pt", "ro", "ru", "ta", "te", "tr", "ur"];
|
|
157
|
+
type HostLocale = (typeof HOST_LOCALES)[number];
|
|
158
|
+
/** Minimal user profile accessible to addon backends and UI slots. */
|
|
159
|
+
interface AddonUser {
|
|
160
|
+
/** Unique user identifier */
|
|
161
|
+
id: string;
|
|
162
|
+
/** Display name */
|
|
163
|
+
name: string;
|
|
164
|
+
/** Full display name */
|
|
165
|
+
displayName: string;
|
|
166
|
+
/** Full URL to the user's avatar image */
|
|
167
|
+
avatar: string;
|
|
168
|
+
/** User's gender identifier */
|
|
169
|
+
gender: string;
|
|
170
|
+
}
|
|
171
|
+
/** Options for resilient HTTP fetch requests issued by addons or host services. */
|
|
172
|
+
interface ResilientFetchOptions extends RequestInit {
|
|
173
|
+
/** Maximum number of retry attempts on transient network or 5xx server errors. Defaults to 2. */
|
|
174
|
+
retries?: number;
|
|
175
|
+
/** Initial exponential retry backoff in milliseconds. Defaults to 150. */
|
|
176
|
+
initialDelayMs?: number;
|
|
177
|
+
/** Request timeout in milliseconds per attempt. Defaults to 10000. */
|
|
178
|
+
timeoutMs?: number;
|
|
179
|
+
}
|
|
180
|
+
/** Resilient fetch function type provided to addon server backends. */
|
|
181
|
+
type AddonResilientFetch = (input: string | URL | Request, init?: ResilientFetchOptions) => Promise<Response>;
|
|
182
|
+
/** Authenticated request user context passed to addon server routes and message pipeline hooks. */
|
|
183
|
+
interface AddonRequestUser {
|
|
184
|
+
id: string;
|
|
185
|
+
permissions?: string[];
|
|
186
|
+
siteId?: string;
|
|
187
|
+
isOwner?: boolean;
|
|
188
|
+
}
|
|
189
|
+
/** Standard attachment contract for chat messages and addon file attachments. */
|
|
190
|
+
interface AddonAttachment {
|
|
191
|
+
url: string;
|
|
192
|
+
name: string;
|
|
193
|
+
type: string;
|
|
194
|
+
id?: string;
|
|
195
|
+
isUploading?: boolean;
|
|
196
|
+
}
|
|
197
|
+
/** Domain-agnostic message contract passed to addon slots (CHAT_MESSAGE_CARD, CHAT_MESSAGE_FLAIR). */
|
|
198
|
+
interface AddonChatMessage {
|
|
199
|
+
id: string;
|
|
200
|
+
roomId?: string;
|
|
201
|
+
senderId?: string;
|
|
202
|
+
sender?: Partial<AddonUser> & {
|
|
203
|
+
id: string;
|
|
204
|
+
name: string;
|
|
205
|
+
isOwner?: boolean;
|
|
206
|
+
isBot?: boolean;
|
|
207
|
+
rankName?: string;
|
|
208
|
+
};
|
|
209
|
+
content?: unknown;
|
|
210
|
+
attachments?: AddonAttachment[] | null;
|
|
211
|
+
metadata?: Record<string, unknown> | null;
|
|
212
|
+
createdAt?: string | Date;
|
|
213
|
+
}
|
|
214
|
+
/** Severity level classification for runtime addon logging. */
|
|
215
|
+
type AddonRuntimeLogLevel = "error" | "info" | "warn";
|
|
216
|
+
/** Operational lifecycle origin of a runtime log entry. */
|
|
217
|
+
type AddonRuntimeLogSource = "request" | "startup";
|
|
218
|
+
/** A diagnostic runtime log entry recorded during addon server startup or HTTP request execution. */
|
|
219
|
+
interface AddonRuntimeLog {
|
|
220
|
+
/** Unique auto-incrementing log entry sequence identifier */
|
|
221
|
+
id: number;
|
|
222
|
+
/** ISO-8601 UTC timestamp when the event was recorded */
|
|
223
|
+
timestamp: string;
|
|
224
|
+
/** Canonical identifier of the emitting addon */
|
|
225
|
+
addonId: string;
|
|
226
|
+
/** Log severity classification */
|
|
227
|
+
level: AddonRuntimeLogLevel;
|
|
228
|
+
/** Lifecycle stage where the log originated */
|
|
229
|
+
source: AddonRuntimeLogSource;
|
|
230
|
+
/** Descriptive log message or error description */
|
|
231
|
+
message: string;
|
|
232
|
+
/** HTTP method if the log was generated during request execution */
|
|
233
|
+
method?: string;
|
|
234
|
+
/** Request pathname if the log was generated during request execution */
|
|
235
|
+
path?: string;
|
|
236
|
+
/** HTTP response status code if the log was generated during request execution */
|
|
237
|
+
status?: number;
|
|
238
|
+
}
|
|
239
|
+
/** Query parameters for filtering and bounding addon developer runtime logs. */
|
|
240
|
+
interface AddonRuntimeLogFilter {
|
|
241
|
+
/** Filter logs by a specific addon identifier */
|
|
242
|
+
addonId?: string;
|
|
243
|
+
/** Filter logs by severity level */
|
|
244
|
+
level?: AddonRuntimeLogLevel;
|
|
245
|
+
/** Maximum number of recent log records to return */
|
|
246
|
+
limit?: number;
|
|
247
|
+
}
|
|
248
|
+
/** Frontend mounting and bundle distribution metadata for an active addon. */
|
|
249
|
+
interface ActiveAddonFrontend extends Pick<NonNullable<AddonManifest["frontend"]>, "mountPoints"> {
|
|
250
|
+
/** Relative web-accessible path to the compiled frontend bundle */
|
|
251
|
+
bundlePath?: string;
|
|
252
|
+
}
|
|
253
|
+
/** Public host runtime representation of an installed, active addon. */
|
|
254
|
+
interface ActiveAddon extends Pick<AddonManifest, "id" | "name" | "version" | "description" | "author" | "homepage" | "license" | "accessPermission" | "permissions" | "commands"> {
|
|
255
|
+
/** Whether the addon is globally activated on the host platform */
|
|
256
|
+
enabled: boolean;
|
|
257
|
+
/** Relative path to the compiled frontend bundle file */
|
|
258
|
+
bundlePath?: string;
|
|
259
|
+
/** Relative path or URL to the addon logo asset */
|
|
260
|
+
logoPath?: string | null;
|
|
261
|
+
/** Frontend mounting points and distribution information */
|
|
262
|
+
frontend?: ActiveAddonFrontend;
|
|
263
|
+
/** Timestamp when the addon was installed */
|
|
264
|
+
createdAt?: string | Date;
|
|
265
|
+
/** Timestamp when the addon configuration or files were last modified */
|
|
266
|
+
updatedAt?: string | Date;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* In-memory representation of an archive file entry used in canonical digest creation and package
|
|
270
|
+
* verification.
|
|
271
|
+
*/
|
|
272
|
+
interface AddonArchiveFile {
|
|
273
|
+
/**
|
|
274
|
+
* Canonical relative path inside the addon archive (e.g., 'manifest.json',
|
|
275
|
+
* 'migrations/001_init.sql')
|
|
276
|
+
*/
|
|
277
|
+
path: string;
|
|
278
|
+
/** Raw binary contents of the archive file */
|
|
279
|
+
contents: Buffer;
|
|
280
|
+
}
|
|
281
|
+
//#endregion
|
|
282
|
+
export { ResilientFetchOptions as S, AddonUser as _, AddonChatMessage as a, MOUNT_POINTS as b, AddonDistribution as c, AddonRequestUser as d, AddonResilientFetch as f, AddonRuntimeLogSource as g, AddonRuntimeLogLevel as h, AddonAttachment as i, AddonManifest as l, AddonRuntimeLogFilter as m, ActiveAddonFrontend as n, AddonCommandDefinition as o, AddonRuntimeLog as p, AddonArchiveFile as r, AddonCommandParameter as s, ActiveAddon as t, AddonPermissionDefinition as u, HOST_LOCALES as v, MountPoint as x, HostLocale as y };
|
package/dist/diagnostics.d.mts
CHANGED
|
@@ -1,22 +1,68 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { l as AddonManifest } from "./contracts2.mjs";
|
|
2
2
|
//#region src/diagnostics.d.ts
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Diagnostic result status indicator for addon validation checks. - `"pass"`: The diagnostic check
|
|
5
|
+
* passed successfully. - `"warning"`: Non-critical warning (e.g. source maps present in
|
|
6
|
+
* production). - `"error"`: Critical failure blocking addon installation or distribution.
|
|
7
|
+
*/
|
|
8
|
+
export type AddonDiagnosticStatus = "pass" | "warning" | "error";
|
|
9
|
+
/** Represents an individual diagnostic check result for an addon package. */
|
|
10
|
+
export interface AddonPackageDiagnostic {
|
|
11
|
+
/** Unique identifier for the diagnostic check (e.g. `"jchat"`, `"package-size"`). */
|
|
5
12
|
id: string;
|
|
13
|
+
/** Human-readable title for the diagnostic check. */
|
|
6
14
|
label: string;
|
|
15
|
+
/** Severity status outcome of the check. */
|
|
7
16
|
status: AddonDiagnosticStatus;
|
|
17
|
+
/** Descriptive message or metric value providing check details. */
|
|
8
18
|
message: string;
|
|
9
19
|
}
|
|
10
|
-
|
|
20
|
+
/** Options required to run diagnostic validation on an addon build package. */
|
|
21
|
+
export interface AddonPackageDiagnosticOptions {
|
|
22
|
+
/** Absolute path to the compiled addon build output directory (`build/`). */
|
|
11
23
|
buildDir: string;
|
|
24
|
+
/** Parsed addon manifest object (`manifest.json`). */
|
|
12
25
|
manifest: AddonManifest;
|
|
26
|
+
/** Semantic version of the host JChat platform instance. */
|
|
13
27
|
jchatVersion: string;
|
|
28
|
+
/** Semantic version of the `@jchat/addon-sdk` package. */
|
|
14
29
|
addonSdkVersion: string;
|
|
30
|
+
/** Whether the diagnostic target is a production `.zip` package build. Defaults to `false`. */
|
|
15
31
|
productionPackage?: boolean;
|
|
32
|
+
/** Maximum allowable package size in bytes. Defaults to 25MB (`26,214,400` bytes). */
|
|
16
33
|
maxBytes?: number;
|
|
17
34
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Constructs a semantic version compatibility range covering all minor/patch versions of the
|
|
37
|
+
* current major version.
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* ;```ts
|
|
41
|
+
* createCompatibleMajorRange("1.4.2") // returns ">=1.4.2 <2.0.0"
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* @param version - Valid semver string (e.g. `"1.2.0"`).
|
|
45
|
+
* @returns Semver range string matching the current major series (e.g. `">=1.2.0 <2.0.0"`).
|
|
46
|
+
* @throws {@link Error} If the input is not a valid semantic version string.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createCompatibleMajorRange(version: string): string;
|
|
49
|
+
/**
|
|
50
|
+
* Performs comprehensive diagnostic validation checks on an addon package build directory.
|
|
51
|
+
*
|
|
52
|
+
* Validates version compatibility ranges, verifies required build files (frontend/server bundles,
|
|
53
|
+
* migrations, seeds), checks total package size limits, flags production source maps, and verifies
|
|
54
|
+
* publisher digital signatures.
|
|
55
|
+
*
|
|
56
|
+
* @param options - Configuration options specifying build directory, manifest, and environment
|
|
57
|
+
* versions.
|
|
58
|
+
* @returns Array of {@link AddonPackageDiagnostic} results.
|
|
59
|
+
*/
|
|
60
|
+
export declare function diagnoseAddonPackage(options: AddonPackageDiagnosticOptions): AddonPackageDiagnostic[];
|
|
61
|
+
/**
|
|
62
|
+
* Checks whether any diagnostic check in a diagnostic list returned a critical error.
|
|
63
|
+
*
|
|
64
|
+
* @param diagnostics - Array of diagnostic check results to evaluate.
|
|
65
|
+
* @returns `true` if at least one check has `status === "error"`, otherwise `false`.
|
|
66
|
+
*/
|
|
67
|
+
export declare function hasAddonDiagnosticErrors(diagnostics: readonly AddonPackageDiagnostic[]): boolean;
|
|
68
|
+
//#endregion
|
package/dist/diagnostics.mjs
CHANGED
|
@@ -1,6 +1,19 @@
|
|
|
1
|
-
import * as fs$1 from "node:fs";
|
|
2
1
|
import * as path$1 from "node:path";
|
|
2
|
+
import * as fs$1 from "node:fs";
|
|
3
3
|
//#region src/diagnostics.ts
|
|
4
|
+
/**
|
|
5
|
+
* Constructs a semantic version compatibility range covering all minor/patch versions of the
|
|
6
|
+
* current major version.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ;```ts
|
|
10
|
+
* createCompatibleMajorRange("1.4.2") // returns ">=1.4.2 <2.0.0"
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @param version - Valid semver string (e.g. `"1.2.0"`).
|
|
14
|
+
* @returns Semver range string matching the current major series (e.g. `">=1.2.0 <2.0.0"`).
|
|
15
|
+
* @throws {@link Error} If the input is not a valid semantic version string.
|
|
16
|
+
*/
|
|
4
17
|
function createCompatibleMajorRange(version) {
|
|
5
18
|
try {
|
|
6
19
|
Bun.semver.order(version, version);
|
|
@@ -12,6 +25,17 @@ function createCompatibleMajorRange(version) {
|
|
|
12
25
|
if (!Number.isSafeInteger(major)) throw new Error(`Invalid semantic version: ${version}`);
|
|
13
26
|
return `>=${version} <${major + 1}.0.0`;
|
|
14
27
|
}
|
|
28
|
+
/**
|
|
29
|
+
* Performs comprehensive diagnostic validation checks on an addon package build directory.
|
|
30
|
+
*
|
|
31
|
+
* Validates version compatibility ranges, verifies required build files (frontend/server bundles,
|
|
32
|
+
* migrations, seeds), checks total package size limits, flags production source maps, and verifies
|
|
33
|
+
* publisher digital signatures.
|
|
34
|
+
*
|
|
35
|
+
* @param options - Configuration options specifying build directory, manifest, and environment
|
|
36
|
+
* versions.
|
|
37
|
+
* @returns Array of {@link AddonPackageDiagnostic} results.
|
|
38
|
+
*/
|
|
15
39
|
function diagnoseAddonPackage(options) {
|
|
16
40
|
const { buildDir, manifest } = options;
|
|
17
41
|
const diagnostics = [];
|
|
@@ -52,13 +76,25 @@ function diagnoseAddonPackage(options) {
|
|
|
52
76
|
const productionArchive = path$1.join(buildDir, `${manifest.id}-${manifest.version}.zip`);
|
|
53
77
|
const hasProductionArchive = fs$1.existsSync(productionArchive) && fs$1.statSync(productionArchive).isFile();
|
|
54
78
|
const totalBytes = options.productionPackage && hasProductionArchive ? fs$1.statSync(productionArchive).size : files.filter((file) => file !== productionArchive).reduce((total, file) => total + fs$1.statSync(file).size, 0);
|
|
55
|
-
const maxBytes = options.maxBytes ??
|
|
79
|
+
const maxBytes = options.maxBytes ?? 26214400;
|
|
56
80
|
diagnostics.push({
|
|
57
81
|
id: "package-size",
|
|
58
82
|
label: "Package size",
|
|
59
83
|
status: totalBytes <= maxBytes ? "pass" : "error",
|
|
60
84
|
message: `${totalBytes} of ${maxBytes} bytes`
|
|
61
85
|
});
|
|
86
|
+
const addonPermPrefix = `addon.${manifest.id}.`;
|
|
87
|
+
const invalidPerms = Array.from(/* @__PURE__ */ new Set([
|
|
88
|
+
...manifest.accessPermission ? [manifest.accessPermission] : [],
|
|
89
|
+
...manifest.permissions ?? [],
|
|
90
|
+
...manifest.permissionDefinitions?.map((d) => d.name) ?? []
|
|
91
|
+
])).filter((perm) => !perm.startsWith(addonPermPrefix));
|
|
92
|
+
diagnostics.push({
|
|
93
|
+
id: "permission-namespacing",
|
|
94
|
+
label: "Permission namespacing",
|
|
95
|
+
status: invalidPerms.length === 0 ? "pass" : "error",
|
|
96
|
+
message: invalidPerms.length === 0 ? `All declared permissions start with ${addonPermPrefix}` : `Permission(s) do not follow naming convention ${addonPermPrefix}*: ${invalidPerms.join(", ")}`
|
|
97
|
+
});
|
|
62
98
|
const sourceMaps = files.filter((file) => file.endsWith(".map"));
|
|
63
99
|
diagnostics.push({
|
|
64
100
|
id: "source-maps",
|
|
@@ -81,9 +117,24 @@ function diagnoseAddonPackage(options) {
|
|
|
81
117
|
});
|
|
82
118
|
return diagnostics;
|
|
83
119
|
}
|
|
120
|
+
/**
|
|
121
|
+
* Checks whether any diagnostic check in a diagnostic list returned a critical error.
|
|
122
|
+
*
|
|
123
|
+
* @param diagnostics - Array of diagnostic check results to evaluate.
|
|
124
|
+
* @returns `true` if at least one check has `status === "error"`, otherwise `false`.
|
|
125
|
+
*/
|
|
84
126
|
function hasAddonDiagnosticErrors(diagnostics) {
|
|
85
127
|
return diagnostics.some(({ status }) => status === "error");
|
|
86
128
|
}
|
|
129
|
+
/**
|
|
130
|
+
* Evaluates semantic version compatibility between a target version and a semver range string.
|
|
131
|
+
*
|
|
132
|
+
* @param id - Diagnostic check identifier.
|
|
133
|
+
* @param label - Diagnostic check label.
|
|
134
|
+
* @param version - Environment component version string.
|
|
135
|
+
* @param range - Expected semver range string from manifest compatibility declarations.
|
|
136
|
+
* @returns An {@link AddonPackageDiagnostic} result object.
|
|
137
|
+
*/
|
|
87
138
|
function compatibilityDiagnostic(id, label, version, range) {
|
|
88
139
|
const compatible = Boolean(range && Bun.semver.satisfies(version, range));
|
|
89
140
|
return {
|
|
@@ -93,12 +144,26 @@ function compatibilityDiagnostic(id, label, version, range) {
|
|
|
93
144
|
message: range ? `${version} ${compatible ? "satisfies" : "does not satisfy"} ${range}` : "Compatibility range is missing"
|
|
94
145
|
};
|
|
95
146
|
}
|
|
147
|
+
/**
|
|
148
|
+
* Safely resolves a relative build file reference within a target build directory, guarding against
|
|
149
|
+
* directory traversal attacks.
|
|
150
|
+
*
|
|
151
|
+
* @param buildDir - Absolute path to the build directory.
|
|
152
|
+
* @param reference - Relative file path declared in manifest.
|
|
153
|
+
* @returns Resolved absolute file path if safe and inside `buildDir`, or `null` if unsafe.
|
|
154
|
+
*/
|
|
96
155
|
function resolveBuildFile(buildDir, reference) {
|
|
97
156
|
if (path$1.isAbsolute(reference) || reference.includes("\\") || reference.split("/").includes("..")) return null;
|
|
98
157
|
const target = path$1.resolve(buildDir, ...reference.replace(/^\.\//, "").split("/"));
|
|
99
158
|
const relative = path$1.relative(path$1.resolve(buildDir), target);
|
|
100
159
|
return relative && !relative.startsWith("..") && !path$1.isAbsolute(relative) ? target : null;
|
|
101
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Recursively lists all regular files within a root directory.
|
|
163
|
+
*
|
|
164
|
+
* @param root - Path to search.
|
|
165
|
+
* @returns Array of absolute file paths.
|
|
166
|
+
*/
|
|
102
167
|
function listRegularFiles(root) {
|
|
103
168
|
if (!fs$1.existsSync(root)) return [];
|
|
104
169
|
return fs$1.readdirSync(root, {
|