@helyx/cli 1.5.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,26 @@
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
+
14
+ ## 1.6.0
15
+
16
+ ### Minor Changes
17
+
18
+ - b698422: Add the optional `helyx envbuilder` command and generated starter npm script.
19
+ Preserve platform builder selections in build manifests and include standalone
20
+ batch, PowerShell or POSIX scripts only when selected. The guided builder runs
21
+ locally, checks input format, masks saved credentials and preserves encryption
22
+ keys and custom settings until the operator confirms saving.
23
+
3
24
  ## 1.5.0
4
25
 
5
26
  ### Minor Changes
package/README.md CHANGED
@@ -20,6 +20,12 @@ operation supports a local or hosted PostgreSQL or MySQL-compatible database.
20
20
  and performs the bot bootstrap, including core and installed-module migrations.
21
21
  `migrate` applies only core migrations and exits.
22
22
 
23
+ Generated starters also include the optional `npm run envbuilder` command.
24
+ After `npm ci`, it runs `helyx envbuilder`, a local guided `.env` builder with
25
+ no connection tests. Additional standalone Windows batch, PowerShell and
26
+ macOS/Linux scripts are included only when selected for the download. Setup
27
+ and startup remain independent.
28
+
23
29
  `doctor` checks the complete bot environment, connectivity, immutable core
24
30
  migration history, package metadata and selected module/engine compatibility
25
31
  without logging in to Discord or changing the database. It inspects module
package/dist/cli.js CHANGED
@@ -24,6 +24,10 @@ try {
24
24
  else if (command === "setup") {
25
25
  await setup();
26
26
  }
27
+ else if (command === "envbuilder") {
28
+ const builder = (await import(new URL("../templates/self-host/env-builder.mjs", import.meta.url).href));
29
+ await builder.runEnvironmentBuilder(process.argv[3]);
30
+ }
27
31
  else if (command === "self-host") {
28
32
  await runSelfHostCommand(process.argv.slice(3));
29
33
  }
@@ -141,6 +145,7 @@ function printHelp() {
141
145
 
142
146
  Commands:
143
147
  setup Create .env safely and explain the available hosting paths
148
+ envbuilder Optionally create or update .env with a local guided builder
144
149
  start Start the Helyx Discord bot
145
150
  migrate Apply core migrations for the selected database engine and exit
146
151
  doctor Validate environment, database schema and module packages
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./self-host/catalogue.js";
2
2
  export * from "./self-host/command.js";
3
3
  export * from "./self-host/database-adapters.js";
4
+ export * from "./self-host/environment-builders.js";
4
5
  export * from "./self-host/manifest.js";
5
6
  export * from "./self-host/project-generator.js";
6
7
  export * from "./self-host/update.js";
package/dist/index.js CHANGED
@@ -1,6 +1,7 @@
1
1
  export * from "./self-host/catalogue.js";
2
2
  export * from "./self-host/command.js";
3
3
  export * from "./self-host/database-adapters.js";
4
+ export * from "./self-host/environment-builders.js";
4
5
  export * from "./self-host/manifest.js";
5
6
  export * from "./self-host/project-generator.js";
6
7
  export * from "./self-host/update.js";
@@ -0,0 +1,12 @@
1
+ import { z } from "zod";
2
+ export declare const selfHostEnvironmentBuilderSchema: z.ZodEnum<{
3
+ none: "none";
4
+ windows: "windows";
5
+ powershell: "powershell";
6
+ unix: "unix";
7
+ all: "all";
8
+ }>;
9
+ export type SelfHostEnvironmentBuilder = z.infer<typeof selfHostEnvironmentBuilderSchema>;
10
+ export type SelfHostEnvironmentBuilderFile = "env-builder.mjs" | "env-builder.bat" | "env-builder.ps1" | "env-builder.sh";
11
+ export declare function selfHostEnvironmentBuilderFiles(selection?: SelfHostEnvironmentBuilder): SelfHostEnvironmentBuilderFile[];
12
+ //# sourceMappingURL=environment-builders.d.ts.map
@@ -0,0 +1,25 @@
1
+ import { z } from "zod";
2
+ export const selfHostEnvironmentBuilderSchema = z.enum([
3
+ "none",
4
+ "windows",
5
+ "powershell",
6
+ "unix",
7
+ "all",
8
+ ]);
9
+ export function selfHostEnvironmentBuilderFiles(selection = "none") {
10
+ selfHostEnvironmentBuilderSchema.parse(selection);
11
+ if (selection === "none")
12
+ return [];
13
+ const launchers = {
14
+ windows: "env-builder.bat",
15
+ powershell: "env-builder.ps1",
16
+ unix: "env-builder.sh",
17
+ };
18
+ return [
19
+ "env-builder.mjs",
20
+ ...(selection === "all"
21
+ ? Object.values(launchers)
22
+ : [launchers[selection]]),
23
+ ];
24
+ }
25
+ //# sourceMappingURL=environment-builders.js.map
@@ -1,7 +1,15 @@
1
1
  import { z } from "zod";
2
+ import { type SelfHostEnvironmentBuilder } from "./environment-builders.js";
2
3
  import { type SelfHostCatalogue, type SelfHostDatabaseEngine } from "./catalogue.js";
3
4
  export declare const selfHostBuildManifestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
4
5
  schemaVersion: z.ZodLiteral<1>;
6
+ environmentBuilder: z.ZodOptional<z.ZodEnum<{
7
+ none: "none";
8
+ windows: "windows";
9
+ powershell: "powershell";
10
+ unix: "unix";
11
+ all: "all";
12
+ }>>;
5
13
  catalogueVersion: z.ZodNumber;
6
14
  core: z.ZodObject<{
7
15
  package: z.ZodString;
@@ -18,6 +26,13 @@ export declare const selfHostBuildManifestSchema: z.ZodDiscriminatedUnion<[z.Zod
18
26
  }, z.core.$strict>>;
19
27
  }, z.core.$strict>, z.ZodObject<{
20
28
  schemaVersion: z.ZodLiteral<2>;
29
+ environmentBuilder: z.ZodOptional<z.ZodEnum<{
30
+ none: "none";
31
+ windows: "windows";
32
+ powershell: "powershell";
33
+ unix: "unix";
34
+ all: "all";
35
+ }>>;
21
36
  databaseEngine: z.ZodOptional<z.ZodEnum<{
22
37
  postgresql: "postgresql";
23
38
  mysql: "mysql";
@@ -52,6 +67,6 @@ export declare const selfHostBuildManifestSchema: z.ZodDiscriminatedUnion<[z.Zod
52
67
  }, z.core.$strict>>;
53
68
  }, z.core.$strict>], "schemaVersion">;
54
69
  export type SelfHostBuildManifest = z.infer<typeof selfHostBuildManifestSchema>;
55
- export declare function createSelfHostBuildManifest(catalogue: SelfHostCatalogue, selectedModuleIds: readonly string[], databaseEngine?: SelfHostDatabaseEngine): SelfHostBuildManifest;
70
+ export declare function createSelfHostBuildManifest(catalogue: SelfHostCatalogue, selectedModuleIds: readonly string[], databaseEngine?: SelfHostDatabaseEngine, environmentBuilder?: SelfHostEnvironmentBuilder): SelfHostBuildManifest;
56
71
  export declare function parseSelfHostBuildManifest(input: unknown, catalogue: SelfHostCatalogue): SelfHostBuildManifest;
57
72
  //# sourceMappingURL=manifest.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import semver from "semver";
2
2
  import { isDeepStrictEqual } from "node:util";
3
3
  import { z } from "zod";
4
+ import { selfHostEnvironmentBuilderSchema, } from "./environment-builders.js";
4
5
  import { isSelfHostModuleCustomerSelectable, selfHostDatabaseEngineSchema, } from "./catalogue.js";
5
6
  const exactVersion = z
6
7
  .string()
@@ -23,6 +24,7 @@ const buildModuleSchema = z
23
24
  const selfHostBuildManifestV1Schema = z
24
25
  .object({
25
26
  schemaVersion: z.literal(1),
27
+ environmentBuilder: selfHostEnvironmentBuilderSchema.optional(),
26
28
  catalogueVersion: z.number().int().positive(),
27
29
  core: buildComponentSchema,
28
30
  generator: buildComponentSchema,
@@ -48,6 +50,7 @@ const buildModuleV2Schema = buildModuleSchema
48
50
  const selfHostBuildManifestV2Schema = z
49
51
  .object({
50
52
  schemaVersion: z.literal(2),
53
+ environmentBuilder: selfHostEnvironmentBuilderSchema.optional(),
51
54
  databaseEngine: selfHostDatabaseEngineSchema.optional(),
52
55
  catalogueVersion: z.number().int().positive(),
53
56
  core: buildComponentSchema,
@@ -82,15 +85,16 @@ export const selfHostBuildManifestSchema = z
82
85
  packages.add(module.package);
83
86
  }
84
87
  });
85
- export function createSelfHostBuildManifest(catalogue, selectedModuleIds, databaseEngine = "postgresql") {
88
+ export function createSelfHostBuildManifest(catalogue, selectedModuleIds, databaseEngine = "postgresql", environmentBuilder = "none") {
86
89
  selfHostDatabaseEngineSchema.parse(databaseEngine);
90
+ selfHostEnvironmentBuilderSchema.parse(environmentBuilder);
87
91
  assertPublishedComponent(catalogue.core, "Helyx runtime");
88
92
  assertPublishedComponent(catalogue.generator, "Helyx generator");
89
93
  if (new Set(selectedModuleIds).size !== selectedModuleIds.length) {
90
94
  throw new Error("Self-host selection contains duplicate module IDs");
91
95
  }
92
96
  if (catalogue.schemaVersion === 2) {
93
- return createSelfHostBuildManifestV2(catalogue, selectedModuleIds, databaseEngine);
97
+ return createSelfHostBuildManifestV2(catalogue, selectedModuleIds, databaseEngine, environmentBuilder);
94
98
  }
95
99
  if (databaseEngine !== "postgresql") {
96
100
  throw new Error("Legacy self-host catalogue supports PostgreSQL only");
@@ -115,6 +119,7 @@ export function createSelfHostBuildManifest(catalogue, selectedModuleIds, databa
115
119
  });
116
120
  return {
117
121
  schemaVersion: 1,
122
+ ...(environmentBuilder !== "none" ? { environmentBuilder } : {}),
118
123
  catalogueVersion: catalogue.catalogueVersion,
119
124
  core: {
120
125
  package: catalogue.core.package,
@@ -127,7 +132,7 @@ export function createSelfHostBuildManifest(catalogue, selectedModuleIds, databa
127
132
  modules,
128
133
  };
129
134
  }
130
- function createSelfHostBuildManifestV2(catalogue, selectedModuleIds, databaseEngine) {
135
+ function createSelfHostBuildManifestV2(catalogue, selectedModuleIds, databaseEngine, environmentBuilder = "none") {
131
136
  const byId = new Map(catalogue.modules.map((module) => [module.id, module]));
132
137
  const explicitlySelected = new Set(selectedModuleIds);
133
138
  const modules = [];
@@ -189,6 +194,7 @@ function createSelfHostBuildManifestV2(catalogue, selectedModuleIds, databaseEng
189
194
  include(id);
190
195
  return {
191
196
  schemaVersion: 2,
197
+ ...(environmentBuilder !== "none" ? { environmentBuilder } : {}),
192
198
  ...(databaseEngine === "mysql" ? { databaseEngine } : {}),
193
199
  catalogueVersion: catalogue.catalogueVersion,
194
200
  core: {
@@ -218,13 +224,20 @@ export function parseSelfHostBuildManifest(input, catalogue) {
218
224
  const selectedModuleIds = manifest.modules
219
225
  .filter(({ moduleKind }) => moduleKind === "customer_feature")
220
226
  .map(({ id }) => id);
221
- const expected = createSelfHostBuildManifestV2(catalogue, selectedModuleIds, manifest.databaseEngine ?? "postgresql");
227
+ const expected = createSelfHostBuildManifestV2(catalogue, selectedModuleIds, manifest.databaseEngine ?? "postgresql", manifest.environmentBuilder ?? "none");
222
228
  if (!isDeepStrictEqual({
223
229
  ...manifest,
230
+ environmentBuilder: manifest.environmentBuilder === "none"
231
+ ? undefined
232
+ : manifest.environmentBuilder,
224
233
  databaseEngine: manifest.databaseEngine === "postgresql"
225
234
  ? undefined
226
235
  : manifest.databaseEngine,
227
- }, { ...expected, databaseEngine: expected.databaseEngine })) {
236
+ }, {
237
+ ...expected,
238
+ databaseEngine: expected.databaseEngine,
239
+ environmentBuilder: expected.environmentBuilder,
240
+ })) {
228
241
  throw new Error("Build manifest modules do not match the trusted catalogue dependency graph");
229
242
  }
230
243
  return expected;
@@ -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 {};
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
2
2
  import { spawn } from "node:child_process";
3
3
  import { mkdir, readFile, readdir, rm, stat, writeFile, } from "node:fs/promises";
4
4
  import { dirname, parse, resolve } from "node:path";
5
+ import { selfHostEnvironmentBuilderFiles, } from "./environment-builders.js";
5
6
  import { isSelfHostModuleCustomerSelectable, } from "./catalogue.js";
6
7
  import { parseSelfHostBuildManifest, } from "./manifest.js";
7
8
  import { databaseAdaptersForCatalogue, } from "./database-adapters.js";
@@ -80,6 +81,7 @@ async function writeGeneratedFiles(targetDirectory, manifest, catalogue, databas
80
81
  engines: { node: ">=24 <27", npm: ">=11" },
81
82
  scripts: {
82
83
  setup: "helyx setup",
84
+ envbuilder: "helyx envbuilder",
83
85
  start: "helyx start",
84
86
  doctor: "helyx doctor",
85
87
  migrate: "helyx migrate",
@@ -95,7 +97,10 @@ async function writeGeneratedFiles(targetDirectory, manifest, catalogue, databas
95
97
  };
96
98
  await writeFile(resolve(targetDirectory, "package.json"), formatJson(packageJson), "utf8");
97
99
  await writeFile(resolve(targetDirectory, "helyx.modules.json"), formatJson(moduleCatalogue), "utf8");
98
- for (const fileName of generatedFileNames) {
100
+ for (const fileName of [
101
+ ...generatedFileNames,
102
+ ...selfHostEnvironmentBuilderFiles(manifest.environmentBuilder),
103
+ ]) {
99
104
  const template = await readFile(fileName === "compose.yaml" && databaseEngine === "mysql"
100
105
  ? mysqlComposeTemplateUrl()
101
106
  : templateUrl(fileName), "utf8");
@@ -106,8 +111,13 @@ async function writeGeneratedFiles(targetDirectory, manifest, catalogue, databas
106
111
  : template;
107
112
  if (fileName === ".env.example")
108
113
  validateEnvironmentTemplate(rendered, databaseEngine);
109
- const content = normalizeCrLf(rendered);
110
- await writeFile(resolve(targetDirectory, fileName), content, "utf8");
114
+ const content = fileName.endsWith(".sh")
115
+ ? rendered.replaceAll("\r\n", "\n")
116
+ : normalizeCrLf(rendered);
117
+ await writeFile(resolve(targetDirectory, fileName), content, {
118
+ encoding: "utf8",
119
+ mode: fileName.endsWith(".sh") ? 0o755 : 0o644,
120
+ });
111
121
  }
112
122
  }
113
123
  function renderEnvironmentExample(template, databaseEngine) {
@@ -170,6 +180,12 @@ function validateEnvironmentTemplate(template, databaseEngine) {
170
180
  .split("\n")
171
181
  .map((line) => line.trim()));
172
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
+ }
173
189
  const value = key === "DATABASE_ENGINE"
174
190
  ? databaseEngine
175
191
  : key === "DATABASE_URL" && databaseEngine === "mysql"
@@ -323,25 +339,15 @@ export const selfHostEnvironmentContract = {
323
339
  DISCORD_TOKEN: { value: "replace-me", optional: false },
324
340
  DISCORD_CLIENT_ID: { value: "12345678901234567", optional: false },
325
341
  HELYX_MESSAGE_CONTENT_ENABLED: { value: "false", optional: false },
326
- HELYX_AUTOMOD_EMBEDDED_WORKERS: { value: "1", optional: false },
327
- HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS: { value: "5000", optional: true },
328
- HELYX_AUTOMOD_EMBEDDED_QUEUE_BYTES: { value: "67108864", optional: true },
329
- HELYX_AUTOMOD_EMBEDDED_QUEUE_ITEMS_PER_GUILD: {
330
- value: "100",
331
- optional: true,
332
- },
333
- HELYX_AUTOMOD_EMBEDDED_REFRESH_SECONDS: {
334
- value: "300",
335
- optional: true,
336
- },
337
- DISCORD_INTERNAL_GUILD_ID: {
338
- value: "12345678901234567",
339
- optional: true,
340
- },
341
- APPROVED_ROLES: {
342
- value: "12345678901234567,12345678901234568",
343
- optional: true,
344
- },
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 },
345
351
  HELYX_MODULE_PACKAGES: {
346
352
  value: "",
347
353
  optional: true,
@@ -354,16 +360,10 @@ export const selfHostEnvironmentContract = {
354
360
  value: "https://app.helyx.gg",
355
361
  optional: true,
356
362
  },
357
- HELYX_BOT_CONTROL_SECRET: {
358
- value: "replace-with-a-base64-encoded-32-byte-key",
359
- optional: true,
360
- },
361
- HELYX_BOT_CONTROL_PORT: { value: "3001", optional: true },
362
- HELYX_GUILD_RECONCILIATION_INTERVAL_SECONDS: {
363
- value: "900",
364
- optional: true,
365
- },
366
- 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 },
367
367
  HELYX_GUILD_COMMAND_WRITES_ENABLED: { value: "false", optional: false },
368
368
  HELYX_GUILD_COMMAND_WRITE_SCOPE: { value: "allowlist", optional: false },
369
369
  HELYX_GUILD_COMMAND_RELEASE_ID: { value: "", optional: true },
@@ -371,31 +371,16 @@ export const selfHostEnvironmentContract = {
371
371
  HELYX_GUILD_COMMAND_WRITE_GUILD_IDS: { value: "", optional: true },
372
372
  HELYX_GUILD_MEMBERS_ENABLED: { value: "false", optional: false },
373
373
  HELYX_CLOUD_CONNECT_ENABLED: { value: "true", optional: false },
374
- HELYX_CLOUD_ENROLMENT_TOKEN: {
375
- value: "replace-with-a-short-lived-enrolment-code",
376
- optional: true,
377
- },
378
- HELYX_CLOUD_ENROLMENT_FILE: {
379
- value: "./helyx.cloud-enrolment.json",
380
- optional: true,
381
- },
374
+ HELYX_CLOUD_ENROLMENT_TOKEN: { omit: true },
375
+ HELYX_CLOUD_ENROLMENT_FILE: { omit: true },
382
376
  HELYX_DATA_ENCRYPTION_KEY: {
383
377
  value: "replace-with-a-base64-encoded-32-byte-key",
384
378
  optional: true,
385
379
  },
386
- HELYX_CLOUD_API_URL: {
387
- value: "https://api.helyx.gg",
388
- optional: true,
389
- },
390
- HELYX_OAUTH_ENABLED: { value: "false", optional: false },
391
- HELYX_OAUTH_INTERNAL_SECRET: {
392
- value: "replace-with-a-base64-encoded-32-byte-key",
393
- optional: true,
394
- },
395
- HELYX_CLOUD_ENDPOINT: {
396
- value: "wss://connect.helyx.gg/v1/connect",
397
- optional: true,
398
- },
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 },
399
384
  HELYX_OWNER_USER_IDS: {
400
385
  value: "12345678901234567",
401
386
  optional: true,
@@ -428,35 +413,14 @@ export const selfHostEnvironmentContract = {
428
413
  value: "4",
429
414
  optional: true,
430
415
  },
431
- HELYX_CLOUD_AUDIT_RETENTION_DAYS: {
432
- value: "90",
433
- optional: true,
434
- },
435
- HELYX_CLOUD_CREDENTIAL_AUDIT_RETENTION_DAYS: {
436
- value: "365",
437
- optional: true,
438
- },
439
- HELYX_STATUS_ENABLED: { value: "false", optional: false },
440
- HELYX_STATUS_URL: {
441
- value: "https://status.helyx.gg",
442
- optional: true,
443
- },
444
- HELYX_STATUS_HEARTBEAT_SECRET: {
445
- value: "replace-with-a-base64-encoded-32-byte-key",
446
- optional: true,
447
- },
448
- HELYX_STATUS_HEARTBEAT_INTERVAL_SECONDS: {
449
- value: "60",
450
- optional: true,
451
- },
452
- CF_ACCESS_CLIENT_ID: {
453
- value: "replace-with-access-client-id",
454
- optional: true,
455
- },
456
- CF_ACCESS_CLIENT_SECRET: {
457
- value: "replace-with-access-client-secret",
458
- optional: true,
459
- },
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 },
460
424
  LOG_LEVEL: { value: "info", optional: false },
461
425
  NODE_ENV: { value: "production", optional: false },
462
426
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helyx/cli",
3
- "version": "1.5.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": 85,
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.5.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
@@ -20,6 +20,31 @@ The matching offline operator and module-author documentation is listed in
20
20
 
21
21
  ## Choose a runtime path
22
22
 
23
+ ### Optional guided environment builder
24
+
25
+ Run `npm run envbuilder` to create or update `.env` by answering questions.
26
+ This optional command is available after `npm ci`; normal setup and startup do
27
+ not run it. If you selected additional environment builders when downloading
28
+ your starter, you can also use these included files before package installation:
29
+
30
+ - Windows: double-click `env-builder.bat`, or run `.\env-builder.ps1` in PowerShell.
31
+ - macOS and Linux: run `sh ./env-builder.sh` in a terminal.
32
+
33
+ No additional builder files are included by default. Each platform selection
34
+ includes its matching script and the shared `env-builder.mjs`; selecting all
35
+ builders includes every platform script. The npm command is always included.
36
+
37
+ The builder detects the starter's database selection, checks input format, and
38
+ asks whether to enable server-specific slash commands for your server IDs.
39
+ Database URLs and bot tokens are visible while you type or paste; saved values
40
+ remain masked in prompts and the review summary. Database passwords are hidden
41
+ while typing. Existing encryption keys and custom settings are retained.
42
+
43
+ Nothing is saved until you type `SAVE`. The builder makes no connection tests,
44
+ installs no packages and starts no services. It is optional: `setup`, `doctor`,
45
+ installation and startup do not launch it. You may still edit `.env` manually.
46
+ Continue with the installation and runtime checks for your chosen path below.
47
+
23
48
  ### Node.js and PowerShell or another shell
24
49
 
25
50
  Use this path on a local machine or VPS without Docker. It requires Node.js `>=24 <27`, npm `>=11`, and one local or hosted supported database. Helyx does not require Docker.
@@ -0,0 +1,14 @@
1
+ @echo off
2
+ setlocal DisableDelayedExpansion
3
+ title Helyx Environment Builder
4
+ where node >nul 2>nul
5
+ if errorlevel 1 (
6
+ echo Node.js 24 or newer is required. Install Node.js and run this file again.
7
+ pause
8
+ exit /b 1
9
+ )
10
+ node "%~dp0env-builder.mjs" %*
11
+ set "builder_exit=%errorlevel%"
12
+ echo.
13
+ pause
14
+ exit /b %builder_exit%