@helyx/module-reactionroles 1.0.21 → 1.1.1

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 CHANGED
@@ -1,5 +1,33 @@
1
1
  # @helyx/module-reactionroles
2
2
 
3
+ ## 1.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [7034a9c]
8
+ - @helyx/sdk@0.16.0
9
+
10
+ ## 1.1.0
11
+
12
+ ### Minor Changes
13
+
14
+ - Prepare the coordinated Phase 8 minor release and align internal package dependencies. Existing deployment and database-support restrictions are unchanged.
15
+
16
+ ### Patch Changes
17
+
18
+ - Defer owned-message recovery until Discord is ready so restarts do not consume cleanup retries before login.
19
+
20
+ - Updated dependencies
21
+ - @helyx/module-manifest@0.13.0
22
+ - @helyx/sdk@0.15.0
23
+
24
+ ## 1.0.22
25
+
26
+ ### Patch Changes
27
+
28
+ - Bound internal dependencies to compatible releases while preserving each
29
+ consumer's required minimum API version.
30
+
3
31
  ## 1.0.21
4
32
 
5
33
  ### Patch Changes
@@ -97,25 +125,7 @@
97
125
 
98
126
  ### Patch Changes
99
127
 
100
- - Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.---
101
- "@helyx/bot": patch
102
- "@helyx/cli": patch
103
- "@helyx/core": patch
104
- "@helyx/framework": patch
105
- "@helyx/platform": patch
106
- "@helyx/sdk": patch
107
- "@helyx/module-account-gate": patch
108
- "@helyx/module-feedback": patch
109
- "@helyx/module-giveaways": patch
110
- "@helyx/module-levels": patch
111
- "@helyx/module-logging": patch
112
- "@helyx/module-polls": patch
113
- "@helyx/module-reactionroles": patch
114
- "@helyx/module-suggestions": patch
115
- "@helyx/module-welcome": patch
116
- ---
117
-
118
- Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.
128
+ - Accept compatible internal Helyx releases within explicit minor-safe pre-1.0 or major-safe stable ranges, preventing dependency-only patch cascades.
119
129
 
120
130
  ## 1.0.8
121
131
 
package/README.md CHANGED
@@ -28,7 +28,7 @@ Helyx stores panel and entry configuration, Helyx-owned message references, life
28
28
 
29
29
  ## Operations and failure behavior
30
30
 
31
- Every owned-message cleanup record atomically schedules a bounded one-shot retry through the core scheduler; startup also reconciles paginated pending work before warming the bounded active-panel cache. Exhausted cleanup remains durable for operator review. Unknown message reactions use a short negative cache and coalesced lookups. Deleted or invalid Discord resources move affected panels to `message_missing` or `needs_attention`; repair or repost restores them. Health is unhealthy while stopped, when required services are missing, or after a recent primary operation failure, and degraded for cold-cache startup, cache saturation, or pending cleanup failure.
31
+ Every owned-message cleanup record atomically schedules a bounded one-shot retry through the core scheduler. Startup reconciles paginated pending work when Discord is ready and warms the bounded active-panel cache; otherwise the normal worker handles cleanup after connection without consuming a pre-login attempt. Exhausted cleanup remains durable for operator review. Unknown message reactions use a short negative cache and coalesced lookups. Deleted or invalid Discord resources move affected panels to `message_missing` or `needs_attention`; repair or repost restores them. Health is unhealthy while stopped, when required services are missing, or after a recent primary operation failure, and degraded for cold-cache startup, cache saturation, or pending cleanup failure.
32
32
 
33
33
  Disablement stops new interactions without deleting configuration. Re-enable only after checking channel access, role hierarchy, and emoji availability. Rollback may restore compatible application code, but must not reverse migrations or delete panel data.
34
34
 
@@ -31,8 +31,10 @@ export class PanelLifecycleService {
31
31
  async recoverMessageCleanup(services) {
32
32
  if (!services.has(HELYX_SERVICE_NAMES.discordOwnedMessages))
33
33
  return { completed: 0, failed: 0, abandoned: 0 };
34
- const repository = this.repositoryFor(services);
35
34
  const messages = services.get(HELYX_SERVICE_NAMES.discordOwnedMessages);
35
+ if (messages.isReady?.() === false)
36
+ return { completed: 0, failed: 0, abandoned: 0 };
37
+ const repository = this.repositoryFor(services);
36
38
  let completed = 0;
37
39
  let failed = 0;
38
40
  let abandoned = 0;
@@ -75,6 +77,16 @@ export class PanelLifecycleService {
75
77
  },
76
78
  recovered: false,
77
79
  };
80
+ const messages = services.get(HELYX_SERVICE_NAMES.discordOwnedMessages);
81
+ if (messages.isReady?.() === false)
82
+ return {
83
+ result: {
84
+ outcome: "deferred",
85
+ delayMs: 60_000,
86
+ safeCode: "reaction_role_cleanup_discord_not_ready",
87
+ },
88
+ recovered: false,
89
+ };
78
90
  const repository = this.repositoryFor(services);
79
91
  let cleanup;
80
92
  try {
@@ -134,7 +146,7 @@ export class PanelLifecycleService {
134
146
  recovered: false,
135
147
  };
136
148
  try {
137
- await this.completeClaimedCleanup(repository, services.get(HELYX_SERVICE_NAMES.discordOwnedMessages), claimed);
149
+ await this.completeClaimedCleanup(repository, messages, claimed);
138
150
  return { result: { outcome: "completed" }, recovered: true };
139
151
  }
140
152
  catch {
package/manifest.json CHANGED
@@ -1,5 +1,6 @@
1
1
  {
2
2
  "manifestVersion": "0.4",
3
+ "databaseEngines": ["postgresql", "mysql"],
3
4
  "releaseStatus": "live",
4
5
  "deploymentSupport": "both",
5
6
  "credentialRisk": "none",
@@ -10,10 +11,10 @@
10
11
  "healthExposure": "direct",
11
12
  "id": "helyx.reactionroles",
12
13
  "name": "Reaction Roles",
13
- "version": "1.0.21",
14
+ "version": "1.1.1",
14
15
  "description": "Let members select approved roles themselves.",
15
16
  "entry": "./dist/index.js",
16
- "framework": "^0.1.0",
17
+ "framework": "^0.2.0",
17
18
  "dependencies": [],
18
19
  "permissions": [
19
20
  "ADD_REACTIONS",
@@ -0,0 +1,89 @@
1
+ CREATE TABLE reactionroles_panels (
2
+ panel_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin PRIMARY KEY,
3
+ guild_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
4
+ channel_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
5
+ message_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
6
+ title VARCHAR(80) COLLATE utf8mb4_bin NOT NULL,
7
+ message_body VARCHAR(1000) COLLATE utf8mb4_bin NOT NULL,
8
+ message_style VARCHAR(5) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
9
+ control_type VARCHAR(9) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
10
+ selection_mode VARCHAR(8) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
11
+ embed_colour INT NULL,
12
+ dropdown_placeholder VARCHAR(100) COLLATE utf8mb4_bin NULL,
13
+ status VARCHAR(15) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
14
+ revision BIGINT NOT NULL DEFAULT 1,
15
+ created_by_user_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
16
+ updated_by_user_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
17
+ created_at DATETIME(3) NOT NULL,
18
+ updated_at DATETIME(3) NOT NULL,
19
+ persistent_reactions BOOLEAN NOT NULL DEFAULT TRUE,
20
+ CONSTRAINT reactionroles_panels_message_unique UNIQUE (guild_id, message_id),
21
+ KEY reactionroles_panels_guild_status_idx (guild_id, status, updated_at DESC, panel_id),
22
+ CHECK (CHAR_LENGTH(title) BETWEEN 1 AND 80),
23
+ CHECK (CHAR_LENGTH(message_body) BETWEEN 1 AND 1000),
24
+ CHECK (message_style IN ('text', 'embed')),
25
+ CHECK (control_type IN ('buttons', 'dropdown', 'reactions')),
26
+ CHECK (selection_mode IN ('multiple', 'one_only')),
27
+ CHECK (embed_colour IS NULL OR embed_colour BETWEEN 0 AND 16777215),
28
+ CHECK (dropdown_placeholder IS NULL OR CHAR_LENGTH(dropdown_placeholder) BETWEEN 1 AND 100),
29
+ CHECK (status IN ('pending', 'active', 'disabled', 'message_missing',
30
+ 'needs_attention', 'cleanup_pending', 'deleting')),
31
+ CHECK (revision > 0),
32
+ CHECK (persistent_reactions IN (0, 1)),
33
+ CONSTRAINT reactionroles_panels_reaction_selection_check CHECK (
34
+ control_type <> 'reactions' OR selection_mode <> 'one_only'
35
+ OR persistent_reactions = FALSE
36
+ )
37
+ ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin;
38
+
39
+ CREATE TABLE reactionroles_entries (
40
+ entry_id VARCHAR(100) CHARACTER SET ascii COLLATE ascii_bin PRIMARY KEY,
41
+ panel_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
42
+ position INT NOT NULL,
43
+ role_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
44
+ nameplate VARCHAR(80) COLLATE utf8mb4_bin NOT NULL,
45
+ emoji_kind VARCHAR(7) CHARACTER SET ascii COLLATE ascii_bin NULL,
46
+ emoji_name VARCHAR(80) COLLATE utf8mb4_bin NULL,
47
+ emoji_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NULL,
48
+ emoji_animated BOOLEAN NULL,
49
+ button_style VARCHAR(9) CHARACTER SET ascii COLLATE ascii_bin NULL,
50
+ created_at DATETIME(3) NOT NULL,
51
+ updated_at DATETIME(3) NOT NULL,
52
+ emoji_id_unique VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin
53
+ GENERATED ALWAYS AS (COALESCE(emoji_id, '')) STORED,
54
+ CONSTRAINT reactionroles_entries_panel_fk FOREIGN KEY (panel_id)
55
+ REFERENCES reactionroles_panels (panel_id) ON DELETE CASCADE,
56
+ CONSTRAINT reactionroles_entries_panel_position_unique UNIQUE (panel_id, position),
57
+ CONSTRAINT reactionroles_entries_panel_role_unique UNIQUE (panel_id, role_id),
58
+ CONSTRAINT reactionroles_entries_emoji_unique UNIQUE
59
+ (panel_id, emoji_kind, emoji_name, emoji_id_unique),
60
+ KEY reactionroles_entries_panel_idx (panel_id, position),
61
+ KEY reactionroles_entries_role_panel_idx (role_id, panel_id),
62
+ KEY reactionroles_entries_emoji_panel_idx (emoji_id, panel_id),
63
+ CHECK (position BETWEEN 0 AND 24),
64
+ CHECK (CHAR_LENGTH(nameplate) BETWEEN 1 AND 80),
65
+ CHECK (emoji_kind IS NULL OR emoji_kind IN ('unicode', 'custom')),
66
+ CHECK (emoji_animated IS NULL OR emoji_animated IN (0, 1)),
67
+ CHECK (button_style IS NULL OR button_style IN ('primary', 'secondary', 'success', 'danger')),
68
+ CHECK ((emoji_kind IS NULL AND emoji_name IS NULL AND emoji_id IS NULL)
69
+ OR (emoji_kind = 'unicode' AND emoji_name IS NOT NULL AND emoji_id IS NULL)
70
+ OR (emoji_kind = 'custom' AND emoji_name IS NOT NULL AND emoji_id IS NOT NULL))
71
+ ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin;
72
+
73
+ CREATE TABLE reactionroles_message_cleanup (
74
+ cleanup_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin PRIMARY KEY,
75
+ guild_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
76
+ panel_id CHAR(36) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
77
+ channel_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
78
+ message_id VARCHAR(20) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
79
+ reason VARCHAR(11) CHARACTER SET ascii COLLATE ascii_bin NOT NULL,
80
+ attempts INT NOT NULL DEFAULT 0,
81
+ next_attempt_at DATETIME(3) NOT NULL,
82
+ created_at DATETIME(3) NOT NULL,
83
+ completed_at DATETIME(3) NULL,
84
+ CONSTRAINT reactionroles_cleanup_message_reason_unique UNIQUE
85
+ (guild_id, channel_id, message_id, reason),
86
+ KEY reactionroles_cleanup_pending_idx (completed_at, next_attempt_at, created_at),
87
+ CHECK (reason IN ('replacement', 'rollback', 'delete')),
88
+ CHECK (attempts BETWEEN 0 AND 10)
89
+ ) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8mb4 COLLATE=utf8mb4_bin;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helyx/module-reactionroles",
3
- "version": "1.0.21",
3
+ "version": "1.1.1",
4
4
  "description": "Configurable self-service Discord role panels for Helyx.",
5
5
  "keywords": [
6
6
  "helyx",
@@ -25,7 +25,7 @@
25
25
  },
26
26
  "publishConfig": {
27
27
  "access": "public",
28
- "provenance": true
28
+ "provenance": false
29
29
  },
30
30
  "type": "module",
31
31
  "files": [
@@ -33,6 +33,7 @@
33
33
  "!dist/*.tsbuildinfo",
34
34
  "!dist/**/*.map",
35
35
  "migrations",
36
+ "migrations-mysql",
36
37
  "manifest.json",
37
38
  "README.md",
38
39
  "CHANGELOG.md",
@@ -49,7 +50,7 @@
49
50
  "build": "tsc -b"
50
51
  },
51
52
  "dependencies": {
52
- "@helyx/module-manifest": ">=0.11.0 <0.12.0",
53
- "@helyx/sdk": ">=0.14.0"
53
+ "@helyx/module-manifest": ">=0.13.0 <0.14.0",
54
+ "@helyx/sdk": ">=0.16.0 <0.17.0"
54
55
  }
55
56
  }