@helyx/cli 1.6.0 → 1.6.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,16 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - Remove unused internal development, status reporting, OAuth, private control,
8
+ advanced Cloud Connect and Auto Moderation tuning examples from the self-host
9
+ environment template and portable documentation. The environment builder also
10
+ omits these examples from older templates while preserving existing active
11
+ custom settings. Keep Discord intent settings, basic Cloud Connect and data
12
+ encryption configuration; runtime defaults and scanning behavior are unchanged.
13
+
3
14
  ## 1.6.0
4
15
 
5
16
  ### Minor Changes
@@ -22,6 +22,8 @@ type HostedOnlyBotEnvironment = "HELYX_PRIVACY_ENABLED" | "HELYX_PRIVACY_EXECUTO
22
22
  type EnvironmentExample = Record<Exclude<keyof BotEnvironmentInput, HostedOnlyBotEnvironment>, {
23
23
  value: string;
24
24
  optional: boolean;
25
+ } | {
26
+ omit: true;
25
27
  }>;
26
28
  export declare const selfHostEnvironmentContract: EnvironmentExample;
27
29
  export {};
@@ -180,6 +180,12 @@ function validateEnvironmentTemplate(template, databaseEngine) {
180
180
  .split("\n")
181
181
  .map((line) => line.trim()));
182
182
  for (const [key, definition] of Object.entries(selfHostEnvironmentContract)) {
183
+ if ("omit" in definition) {
184
+ const setting = new RegExp(`^(?:#\\s*)?${key}\\s*=`, "u");
185
+ if ([...lines].some((line) => setting.test(line)))
186
+ throw new Error(`Self-host environment template contains an omitted setting: ${key}`);
187
+ continue;
188
+ }
183
189
  const value = key === "DATABASE_ENGINE"
184
190
  ? databaseEngine
185
191
  : key === "DATABASE_URL" && databaseEngine === "mysql"
@@ -333,25 +339,15 @@ export const selfHostEnvironmentContract = {
333
339
  DISCORD_TOKEN: { value: "replace-me", optional: false },
334
340
  DISCORD_CLIENT_ID: { value: "12345678901234567", optional: false },
335
341
  HELYX_MESSAGE_CONTENT_ENABLED: { value: "false", optional: false },
336
- HELYX_AUTOMOD_EMBEDDED_WORKERS: { value: "1", optional: false },
337
- HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS: { value: "5000", optional: true },
338
- HELYX_AUTOMOD_EMBEDDED_QUEUE_BYTES: { value: "67108864", optional: true },
339
- HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS_PER_GUILD: {
340
- value: "100",
341
- optional: true,
342
- },
343
- HELYX_AUTOMOD_EMBEDDED_REFRESH_SECONDS: {
344
- value: "300",
345
- optional: true,
346
- },
347
- DISCORD_INTERNAL_GUILD_ID: {
348
- value: "12345678901234567",
349
- optional: true,
350
- },
351
- APPROVED_ROLES: {
352
- value: "12345678901234567,12345678901234568",
353
- optional: true,
354
- },
342
+ // Advanced self-host options use runtime defaults; internal/hosted settings
343
+ // are deliberately absent from the customer example.
344
+ HELYX_AUTOMOD_EMBEDDED_WORKERS: { omit: true },
345
+ HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS: { omit: true },
346
+ HELYX_AUTOMOD_EMBEDDED_QUEUE_BYTES: { omit: true },
347
+ HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS_PER_GUILD: { omit: true },
348
+ HELYX_AUTOMOD_EMBEDDED_REFRESH_SECONDS: { omit: true },
349
+ DISCORD_INTERNAL_GUILD_ID: { omit: true },
350
+ APPROVED_ROLES: { omit: true },
355
351
  HELYX_MODULE_PACKAGES: {
356
352
  value: "",
357
353
  optional: true,
@@ -364,16 +360,10 @@ export const selfHostEnvironmentContract = {
364
360
  value: "https://app.helyx.gg",
365
361
  optional: true,
366
362
  },
367
- HELYX_BOT_CONTROL_SECRET: {
368
- value: "replace-with-a-base64-encoded-32-byte-key",
369
- optional: true,
370
- },
371
- HELYX_BOT_CONTROL_PORT: { value: "3001", optional: true },
372
- HELYX_GUILD_RECONCILIATION_INTERVAL_SECONDS: {
373
- value: "900",
374
- optional: true,
375
- },
376
- HELYX_HOSTED_MODERATION_ENABLED: { value: "false", optional: false },
363
+ HELYX_BOT_CONTROL_SECRET: { omit: true },
364
+ HELYX_BOT_CONTROL_PORT: { omit: true },
365
+ HELYX_GUILD_RECONCILIATION_INTERVAL_SECONDS: { omit: true },
366
+ HELYX_HOSTED_MODERATION_ENABLED: { omit: true },
377
367
  HELYX_GUILD_COMMAND_WRITES_ENABLED: { value: "false", optional: false },
378
368
  HELYX_GUILD_COMMAND_WRITE_SCOPE: { value: "allowlist", optional: false },
379
369
  HELYX_GUILD_COMMAND_RELEASE_ID: { value: "", optional: true },
@@ -381,31 +371,16 @@ export const selfHostEnvironmentContract = {
381
371
  HELYX_GUILD_COMMAND_WRITE_GUILD_IDS: { value: "", optional: true },
382
372
  HELYX_GUILD_MEMBERS_ENABLED: { value: "false", optional: false },
383
373
  HELYX_CLOUD_CONNECT_ENABLED: { value: "true", optional: false },
384
- HELYX_CLOUD_ENROLMENT_TOKEN: {
385
- value: "replace-with-a-short-lived-enrolment-code",
386
- optional: true,
387
- },
388
- HELYX_CLOUD_ENROLMENT_FILE: {
389
- value: "./helyx.cloud-enrolment.json",
390
- optional: true,
391
- },
374
+ HELYX_CLOUD_ENROLMENT_TOKEN: { omit: true },
375
+ HELYX_CLOUD_ENROLMENT_FILE: { omit: true },
392
376
  HELYX_DATA_ENCRYPTION_KEY: {
393
377
  value: "replace-with-a-base64-encoded-32-byte-key",
394
378
  optional: true,
395
379
  },
396
- HELYX_CLOUD_API_URL: {
397
- value: "https://api.helyx.gg",
398
- optional: true,
399
- },
400
- HELYX_OAUTH_ENABLED: { value: "false", optional: false },
401
- HELYX_OAUTH_INTERNAL_SECRET: {
402
- value: "replace-with-a-base64-encoded-32-byte-key",
403
- optional: true,
404
- },
405
- HELYX_CLOUD_ENDPOINT: {
406
- value: "wss://connect.helyx.gg/v1/connect",
407
- optional: true,
408
- },
380
+ HELYX_CLOUD_API_URL: { omit: true },
381
+ HELYX_OAUTH_ENABLED: { omit: true },
382
+ HELYX_OAUTH_INTERNAL_SECRET: { omit: true },
383
+ HELYX_CLOUD_ENDPOINT: { omit: true },
409
384
  HELYX_OWNER_USER_IDS: {
410
385
  value: "12345678901234567",
411
386
  optional: true,
@@ -438,35 +413,14 @@ export const selfHostEnvironmentContract = {
438
413
  value: "4",
439
414
  optional: true,
440
415
  },
441
- HELYX_CLOUD_AUDIT_RETENTION_DAYS: {
442
- value: "90",
443
- optional: true,
444
- },
445
- HELYX_CLOUD_CREDENTIAL_AUDIT_RETENTION_DAYS: {
446
- value: "365",
447
- optional: true,
448
- },
449
- HELYX_STATUS_ENABLED: { value: "false", optional: false },
450
- HELYX_STATUS_URL: {
451
- value: "https://status.helyx.gg",
452
- optional: true,
453
- },
454
- HELYX_STATUS_HEARTBEAT_SECRET: {
455
- value: "replace-with-a-base64-encoded-32-byte-key",
456
- optional: true,
457
- },
458
- HELYX_STATUS_HEARTBEAT_INTERVAL_SECONDS: {
459
- value: "60",
460
- optional: true,
461
- },
462
- CF_ACCESS_CLIENT_ID: {
463
- value: "replace-with-access-client-id",
464
- optional: true,
465
- },
466
- CF_ACCESS_CLIENT_SECRET: {
467
- value: "replace-with-access-client-secret",
468
- optional: true,
469
- },
416
+ HELYX_CLOUD_AUDIT_RETENTION_DAYS: { omit: true },
417
+ HELYX_CLOUD_CREDENTIAL_AUDIT_RETENTION_DAYS: { omit: true },
418
+ HELYX_STATUS_ENABLED: { omit: true },
419
+ HELYX_STATUS_URL: { omit: true },
420
+ HELYX_STATUS_HEARTBEAT_SECRET: { omit: true },
421
+ HELYX_STATUS_HEARTBEAT_INTERVAL_SECONDS: { omit: true },
422
+ CF_ACCESS_CLIENT_ID: { omit: true },
423
+ CF_ACCESS_CLIENT_SECRET: { omit: true },
470
424
  LOG_LEVEL: { value: "info", optional: false },
471
425
  NODE_ENV: { value: "production", optional: false },
472
426
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helyx/cli",
3
- "version": "1.6.0",
3
+ "version": "1.6.1",
4
4
  "description": "Command-line tools for running and generating self-hosted Helyx deployments.",
5
5
  "keywords": [
6
6
  "helyx",
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
- "catalogueVersion": 86,
3
+ "catalogueVersion": 87,
4
4
  "core": {
5
5
  "package": "@helyx/bot",
6
- "version": "1.5.3",
6
+ "version": "1.5.4",
7
7
  "availability": "published"
8
8
  },
9
9
  "generator": {
10
10
  "package": "@helyx/cli",
11
- "version": "1.6.0",
11
+ "version": "1.6.1",
12
12
  "command": "helyx",
13
13
  "availability": "published"
14
14
  },
@@ -9,16 +9,6 @@ DISCORD_CLIENT_ID=12345678901234567
9
9
  # Explicit privileged gateway opt-in. Keep false unless a reviewed loaded module
10
10
  # requires message content and it is enabled in the Discord developer portal.
11
11
  HELYX_MESSAGE_CONTENT_ENABLED=false
12
- # Enhanced Auto Moderation stays inside this bot process. One worker is the
13
- # recommended default (range 1-4); increase only after measuring CPU and memory.
14
- # Hosted scanning uses the separate Helyx Ecko service, not these settings.
15
- HELYX_AUTOMOD_EMBEDDED_WORKERS=1
16
- # Optional conservative queue overrides (hard ceilings: 5000 items, 64 MiB,
17
- # 100 items per server). Defaults are used when these remain commented.
18
- # HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS=5000
19
- # HELYX_AUTOMOD_EMBEDDED_QUEUE_BYTES=67108864
20
- # HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS_PER_GUILD=100
21
- # HELYX_AUTOMOD_EMBEDDED_REFRESH_SECONDS=300
22
12
  # Enable for loaded member workflows such as Welcome, Access Control or Levels,
23
13
  # with Server Members Intent also enabled in the Discord developer portal.
24
14
  HELYX_GUILD_MEMBERS_ENABLED=false
@@ -51,10 +41,6 @@ HELYX_CLOUD_CONNECT_ENABLED=true
51
41
  # trace, debug, info, warn, error, fatal or silent
52
42
  LOG_LEVEL=info
53
43
 
54
- # Guild-scoped development commands only
55
- # DISCORD_INTERNAL_GUILD_ID=12345678901234567
56
- # APPROVED_ROLES=12345678901234567,12345678901234568
57
-
58
44
  # SHARDING: OFF BY DEFAULT
59
45
 
60
46
  # `off` is the compatible self-host default. Keep shard-only values commented
@@ -80,12 +66,6 @@ HELYX_SHARD_MODE=off
80
66
  # Additional reviewed module packages
81
67
  # HELYX_MODULE_PACKAGES=
82
68
 
83
- # Private dashboard control endpoint — configure both together
84
- # HELYX_BOT_CONTROL_SECRET=replace-with-a-base64-encoded-32-byte-key
85
- # HELYX_BOT_CONTROL_PORT=3001
86
- # HELYX_GUILD_RECONCILIATION_INTERVAL_SECONDS=900
87
- HELYX_HOSTED_MODERATION_ENABLED=false
88
-
89
69
  # Guild command writes remain off until explicitly enabled for known guild IDs.
90
70
  # For enabled-module server commands, set writes=true, retain allowlist scope,
91
71
  # add comma-separated Discord server IDs below, and use global mode platform-only.
@@ -96,14 +76,6 @@ HELYX_GUILD_COMMAND_WRITE_SCOPE=allowlist
96
76
  HELYX_GLOBAL_COMMAND_MODE=legacy
97
77
  # HELYX_GUILD_COMMAND_WRITE_GUILD_IDS=
98
78
 
99
- # Alternative Cloud Connect enrolment — the Discord command is preferred
100
- # HELYX_CLOUD_ENROLMENT_TOKEN=replace-with-a-short-lived-enrolment-code
101
- # HELYX_CLOUD_ENROLMENT_FILE=./helyx.cloud-enrolment.json
102
-
103
- # Hosted OAuth bridge. Keep disabled unless the API and bot share this secret.
104
- HELYX_OAUTH_ENABLED=false
105
- # HELYX_OAUTH_INTERNAL_SECRET=replace-with-a-base64-encoded-32-byte-key
106
-
107
79
  # DANGER ZONE — HELYX-MANAGED VALUES, DO NOT EDIT
108
80
 
109
81
  # Generated module selection
@@ -113,22 +85,5 @@ HELYX_MODULE_CATALOGUE_PATH=./helyx.modules.json
113
85
  # and Invite Tracking; retain it unchanged across restarts and deployments.
114
86
  # HELYX_DATA_ENCRYPTION_KEY=replace-with-a-base64-encoded-32-byte-key
115
87
 
116
- # Official Cloud Connect endpoints
117
- # HELYX_CLOUD_API_URL=https://api.helyx.gg
118
- # HELYX_CLOUD_ENDPOINT=wss://connect.helyx.gg/v1/connect
119
-
120
- # Security audit retention
121
- # HELYX_CLOUD_AUDIT_RETENTION_DAYS=90
122
- # HELYX_CLOUD_CREDENTIAL_AUDIT_RETENTION_DAYS=365
123
-
124
- # Optional public status reporting. Keep disabled unless this installation has
125
- # its own approved Helyx status credentials.
126
- HELYX_STATUS_ENABLED=false
127
- # HELYX_STATUS_URL=https://status.helyx.gg
128
- # HELYX_STATUS_HEARTBEAT_SECRET=replace-with-a-base64-encoded-32-byte-key
129
- # HELYX_STATUS_HEARTBEAT_INTERVAL_SECONDS=60
130
- # CF_ACCESS_CLIENT_ID=replace-with-access-client-id
131
- # CF_ACCESS_CLIENT_SECRET=replace-with-access-client-secret
132
-
133
88
  # Runtime mode
134
89
  NODE_ENV=production
@@ -208,23 +208,19 @@ const environmentGroups = [
208
208
  ],
209
209
  ["DATA ENCRYPTION - KEEP THIS KEY", /^HELYX_DATA_ENCRYPTION_KEY$/u],
210
210
  ["LOGGING", /^LOG_LEVEL$/u],
211
- ["AUTO MODERATION", /^HELYX_AUTOMOD_/u],
212
211
  ["SHARDING - ADVANCED", /^HELYX_SHARD_/u],
213
212
  ["MODULE SELECTION", /^HELYX_MODULE_/u],
214
- [
215
- "PRIVATE CONTROL - ADVANCED",
216
- /^HELYX_BOT_CONTROL_|^HELYX_HOSTED_MODERATION_ENABLED$|^HELYX_GUILD_RECONCILIATION_INTERVAL_SECONDS$/u,
217
- ],
218
- ["CLOUD CONNECT - ADVANCED", /^HELYX_CLOUD_/u],
219
- ["OAUTH - ADVANCED", /^HELYX_OAUTH_/u],
220
- ["STATUS REPORTING - OPTIONAL", /^HELYX_STATUS_|^CF_ACCESS_/u],
221
- [
222
- "INTERNAL DEVELOPMENT - OPTIONAL",
223
- /^(?:DISCORD_INTERNAL_GUILD_ID|APPROVED_ROLES)$/u,
224
- ],
225
213
  ["CUSTOM SETTINGS", /./u],
226
214
  ];
215
+ const omittedExampleSetting =
216
+ /^(?:HELYX_AUTOMOD_|HELYX_BOT_CONTROL_|HELYX_HOSTED_MODERATION_ENABLED$|HELYX_GUILD_RECONCILIATION_INTERVAL_SECONDS$|HELYX_CLOUD_(?!CONNECT_ENABLED$)|HELYX_OAUTH_|HELYX_STATUS_|CF_ACCESS_|DISCORD_INTERNAL_GUILD_ID$|APPROVED_ROLES$)/u;
227
217
  const oldHeadings = new Set([
218
+ "AUTO MODERATION",
219
+ "PRIVATE CONTROL - ADVANCED",
220
+ "CLOUD CONNECT - ADVANCED",
221
+ "OAUTH - ADVANCED",
222
+ "STATUS REPORTING - OPTIONAL",
223
+ "INTERNAL DEVELOPMENT - OPTIONAL",
228
224
  "REQUIRED — EDIT THESE VALUES",
229
225
  "Discord",
230
226
  "Database",
@@ -237,7 +233,7 @@ const oldHeadings = new Set([
237
233
  "Keep this file private. Lines starting with # are comments.",
238
234
  ]);
239
235
 
240
- export function formatEnvironment(content) {
236
+ export function formatEnvironment(content, { template = false } = {}) {
241
237
  const newline = content.includes("\r\n") ? "\r\n" : "\n";
242
238
  const groups = environmentGroups.map(() => []);
243
239
  let pending = [];
@@ -265,6 +261,10 @@ export function formatEnvironment(content) {
265
261
  continue;
266
262
  const key =
267
263
  record.key ?? text.match(/^\s*#\s*([A-Za-z_][A-Za-z0-9_]*)\s*=/u)?.[1];
264
+ if (key && omittedExampleSetting.test(key) && (template || !record.key)) {
265
+ pending = [];
266
+ continue;
267
+ }
268
268
  if (!key) {
269
269
  if (!text.trim() && pending.length && previousGroup !== undefined) {
270
270
  append(previousGroup, pending);
@@ -295,6 +295,9 @@ export function formatEnvironment(content) {
295
295
  ].join("\n\n\n") + "\n";
296
296
  const formatted = output.replace(/\n/gu, newline);
297
297
  const before = parseEnv(content);
298
+ if (template)
299
+ for (const key of Object.keys(before))
300
+ if (omittedExampleSetting.test(key)) delete before[key];
298
301
  const after = parseEnv(formatted);
299
302
  if (
300
303
  Object.keys(before).length !== Object.keys(after).length ||
@@ -420,7 +423,10 @@ export async function runWizard({
420
423
  "Choose a downloaded Helyx starter folder containing package.json and .env.example.",
421
424
  );
422
425
  const original = await optionalRead(join(directory, ".env"));
423
- const template = await readFile(join(directory, ".env.example"), "utf8");
426
+ const template = formatEnvironment(
427
+ await readFile(join(directory, ".env.example"), "utf8"),
428
+ { template: true },
429
+ );
424
430
  const existing = parseEnv(original ?? "");
425
431
  const defaults = parseEnv(template);
426
432
  const values = { ...defaults, ...existing };