@helyx/cli 0.4.36 → 0.4.38
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,22 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.38
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Refresh the embedded self-host catalogue for the Forms 1.0.2 interaction and permission fix.
|
|
8
|
+
|
|
9
|
+
## 0.4.37
|
|
10
|
+
|
|
11
|
+
### Patch Changes
|
|
12
|
+
|
|
13
|
+
- Harden dashboard authentication, privacy execution, control routing, database transactions, and self-host configuration.
|
|
14
|
+
|
|
15
|
+
Add bounded multi-value record reads and use them to batch Polls and Reaction Roles dashboard queries. Improve dashboard presentation, Forms workflows, release safety, and operational tooling across hosted and self-hosted deployments.
|
|
16
|
+
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
- @helyx/database@0.8.0
|
|
19
|
+
|
|
3
20
|
## 0.4.36
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { BotEnvironmentInput } from "@helyx/config";
|
|
2
2
|
import type { SelfHostCatalogue } from "./catalogue.js";
|
|
3
3
|
import { type SelfHostBuildManifest } from "./manifest.js";
|
|
4
|
-
export type SelfHostCommandRunner = (arguments_: readonly string[], workingDirectory: string) => Promise<void>;
|
|
4
|
+
export type SelfHostCommandRunner = (arguments_: readonly string[], workingDirectory: string, signal: AbortSignal) => Promise<void>;
|
|
5
5
|
export interface GenerateSelfHostProjectOptions {
|
|
6
6
|
catalogue: SelfHostCatalogue;
|
|
7
7
|
manifest: unknown;
|
|
8
8
|
targetDirectory: string;
|
|
9
9
|
install?: boolean;
|
|
10
10
|
commandRunner?: SelfHostCommandRunner;
|
|
11
|
+
signal?: AbortSignal;
|
|
11
12
|
}
|
|
12
13
|
export interface GeneratedSelfHostProject {
|
|
13
14
|
directory: string;
|
|
@@ -14,6 +14,8 @@ const generatedFileNames = [
|
|
|
14
14
|
export async function generateSelfHostProject(options) {
|
|
15
15
|
const manifest = parseSelfHostBuildManifest(options.manifest, options.catalogue);
|
|
16
16
|
const targetDirectory = resolve(options.targetDirectory);
|
|
17
|
+
const signal = options.signal ?? AbortSignal.timeout(120_000);
|
|
18
|
+
signal.throwIfAborted();
|
|
17
19
|
assertSafeTargetDirectory(targetDirectory);
|
|
18
20
|
await mkdir(dirname(targetDirectory), { recursive: true });
|
|
19
21
|
let created = false;
|
|
@@ -21,6 +23,7 @@ export async function generateSelfHostProject(options) {
|
|
|
21
23
|
await mkdir(targetDirectory);
|
|
22
24
|
created = true;
|
|
23
25
|
await writeGeneratedFiles(targetDirectory, manifest, options.catalogue);
|
|
26
|
+
signal.throwIfAborted();
|
|
24
27
|
const runner = options.commandRunner ?? runNpmCommand;
|
|
25
28
|
await runner([
|
|
26
29
|
"install",
|
|
@@ -28,10 +31,12 @@ export async function generateSelfHostProject(options) {
|
|
|
28
31
|
"--ignore-scripts",
|
|
29
32
|
"--no-audit",
|
|
30
33
|
"--no-fund",
|
|
31
|
-
], targetDirectory);
|
|
34
|
+
], targetDirectory, signal);
|
|
35
|
+
signal.throwIfAborted();
|
|
32
36
|
await validateGeneratedLockfile(targetDirectory, manifest);
|
|
37
|
+
signal.throwIfAborted();
|
|
33
38
|
if (options.install) {
|
|
34
|
-
await runner(["ci", "--no-audit", "--no-fund"], targetDirectory);
|
|
39
|
+
await runner(["ci", "--no-audit", "--no-fund"], targetDirectory, signal);
|
|
35
40
|
}
|
|
36
41
|
await writeChecksums(targetDirectory);
|
|
37
42
|
const files = (await readdir(targetDirectory)).sort((left, right) => left.localeCompare(right, "en"));
|
|
@@ -63,7 +68,7 @@ async function writeGeneratedFiles(targetDirectory, manifest, catalogue) {
|
|
|
63
68
|
private: true,
|
|
64
69
|
license: "UNLICENSED",
|
|
65
70
|
type: "module",
|
|
66
|
-
packageManager: "npm@11.
|
|
71
|
+
packageManager: "npm@11.19.0",
|
|
67
72
|
engines: { node: ">=24 <27", npm: ">=11" },
|
|
68
73
|
scripts: {
|
|
69
74
|
setup: "helyx setup",
|
|
@@ -177,7 +182,8 @@ function assertSafeTargetDirectory(targetDirectory) {
|
|
|
177
182
|
throw new Error("Refusing to generate a self-host project at a filesystem root");
|
|
178
183
|
}
|
|
179
184
|
}
|
|
180
|
-
async function runNpmCommand(arguments_, workingDirectory) {
|
|
185
|
+
async function runNpmCommand(arguments_, workingDirectory, signal) {
|
|
186
|
+
signal.throwIfAborted();
|
|
181
187
|
const npmCli = process.env.npm_execpath;
|
|
182
188
|
const executable = npmCli ? process.execPath : "npm";
|
|
183
189
|
const commandArguments = npmCli ? [npmCli, ...arguments_] : [...arguments_];
|
|
@@ -188,27 +194,66 @@ async function runNpmCommand(arguments_, workingDirectory) {
|
|
|
188
194
|
? { ...process.env, npm_config_ignore_scripts: "true" }
|
|
189
195
|
: process.env,
|
|
190
196
|
shell: process.platform === "win32" && npmCli === undefined,
|
|
197
|
+
detached: process.platform !== "win32",
|
|
191
198
|
stdio: ["ignore", "pipe", "pipe"],
|
|
192
199
|
});
|
|
193
200
|
child.stdout.resume();
|
|
194
201
|
child.stderr.resume();
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
}
|
|
202
|
+
let aborting = false;
|
|
203
|
+
const cleanup = () => {
|
|
204
|
+
signal.removeEventListener("abort", onAbort);
|
|
205
|
+
};
|
|
206
|
+
const onAbort = () => {
|
|
207
|
+
if (aborting)
|
|
208
|
+
return;
|
|
209
|
+
aborting = true;
|
|
210
|
+
if (process.platform === "win32" && child.pid) {
|
|
211
|
+
const killer = spawn("taskkill", ["/pid", String(child.pid), "/T", "/F"], { stdio: "ignore", windowsHide: true });
|
|
212
|
+
killer.once("error", () => child.kill("SIGTERM"));
|
|
213
|
+
killer.once("close", (code) => {
|
|
214
|
+
if (code !== 0)
|
|
215
|
+
child.kill("SIGTERM");
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
else {
|
|
219
|
+
killProcessGroup(child.pid, "SIGKILL", () => child.kill("SIGKILL"));
|
|
220
|
+
}
|
|
221
|
+
};
|
|
222
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
199
223
|
child.once("error", (error) => {
|
|
200
|
-
|
|
201
|
-
reject(error);
|
|
224
|
+
cleanup();
|
|
225
|
+
reject(aborting ? abortReason(signal) : error);
|
|
202
226
|
});
|
|
203
227
|
child.once("close", (code) => {
|
|
204
|
-
|
|
205
|
-
if (
|
|
228
|
+
cleanup();
|
|
229
|
+
if (aborting)
|
|
230
|
+
reject(abortReason(signal));
|
|
231
|
+
else if (code === 0)
|
|
206
232
|
resolvePromise();
|
|
207
233
|
else
|
|
208
234
|
reject(new Error(`npm command failed with exit code ${String(code)}; rerun it in the generated directory for detailed diagnostics`));
|
|
209
235
|
});
|
|
236
|
+
if (signal.aborted)
|
|
237
|
+
onAbort();
|
|
210
238
|
});
|
|
211
239
|
}
|
|
240
|
+
function abortReason(signal) {
|
|
241
|
+
return signal.reason instanceof Error
|
|
242
|
+
? signal.reason
|
|
243
|
+
: new Error("Self-host generation aborted");
|
|
244
|
+
}
|
|
245
|
+
function killProcessGroup(pid, signal, fallback) {
|
|
246
|
+
if (!pid) {
|
|
247
|
+
fallback();
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
try {
|
|
251
|
+
process.kill(-pid, signal);
|
|
252
|
+
}
|
|
253
|
+
catch {
|
|
254
|
+
fallback();
|
|
255
|
+
}
|
|
256
|
+
}
|
|
212
257
|
function isRecord(value) {
|
|
213
258
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
214
259
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@helyx/cli",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.38",
|
|
4
4
|
"description": "Command-line tools for running and generating self-hosted Helyx deployments.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"helyx",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"dependencies": {
|
|
55
55
|
"@helyx/bot": ">=0.4.0 <0.5.0",
|
|
56
56
|
"@helyx/config": ">=0.5.0 <0.6.0",
|
|
57
|
-
"@helyx/database": ">=0.
|
|
57
|
+
"@helyx/database": ">=0.8.0 <0.9.0",
|
|
58
58
|
"semver": "7.8.5",
|
|
59
59
|
"zod": "4.4.3"
|
|
60
60
|
},
|
package/self-host-catalogue.json
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"catalogueVersion":
|
|
3
|
+
"catalogueVersion": 36,
|
|
4
4
|
"core": {
|
|
5
5
|
"package": "@helyx/bot",
|
|
6
|
-
"version": "0.4.
|
|
6
|
+
"version": "0.4.29",
|
|
7
7
|
"availability": "published"
|
|
8
8
|
},
|
|
9
9
|
"generator": {
|
|
10
10
|
"package": "@helyx/cli",
|
|
11
|
-
"version": "0.4.
|
|
11
|
+
"version": "0.4.38",
|
|
12
12
|
"command": "helyx",
|
|
13
13
|
"availability": "published"
|
|
14
14
|
},
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
{
|
|
17
17
|
"id": "helyx.feedback",
|
|
18
18
|
"package": "@helyx/module-feedback",
|
|
19
|
-
"version": "1.1.
|
|
19
|
+
"version": "1.1.14",
|
|
20
20
|
"name": "Feedback",
|
|
21
21
|
"description": "Collects simple feedback from Discord server members.",
|
|
22
22
|
"category": "Community",
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
{
|
|
27
27
|
"id": "helyx.welcome",
|
|
28
28
|
"package": "@helyx/module-welcome",
|
|
29
|
-
"version": "1.1.
|
|
29
|
+
"version": "1.1.13",
|
|
30
30
|
"name": "Welcome",
|
|
31
31
|
"description": "Greets new members and can give them a starting role.",
|
|
32
32
|
"category": "Community",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
{
|
|
37
37
|
"id": "helyx.suggestions",
|
|
38
38
|
"package": "@helyx/module-suggestions",
|
|
39
|
-
"version": "1.1.
|
|
39
|
+
"version": "1.1.14",
|
|
40
40
|
"name": "Suggestions",
|
|
41
41
|
"description": "Collects community ideas with configurable reaction or button voting.",
|
|
42
42
|
"category": "Community",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
{
|
|
47
47
|
"id": "helyx.polls",
|
|
48
48
|
"package": "@helyx/module-polls",
|
|
49
|
-
"version": "1.0.
|
|
49
|
+
"version": "1.0.12",
|
|
50
50
|
"name": "Polls",
|
|
51
51
|
"description": "Run clear single or multiple-choice polls.",
|
|
52
52
|
"category": "Community",
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
{
|
|
67
67
|
"id": "helyx.levels",
|
|
68
68
|
"package": "@helyx/module-levels",
|
|
69
|
-
"version": "1.0.
|
|
69
|
+
"version": "1.0.9",
|
|
70
70
|
"name": "Levels",
|
|
71
71
|
"description": "Optional participation levels and rewards.",
|
|
72
72
|
"category": "Community",
|
|
@@ -146,7 +146,7 @@
|
|
|
146
146
|
{
|
|
147
147
|
"id": "helyx.account-gate",
|
|
148
148
|
"package": "@helyx/module-account-gate",
|
|
149
|
-
"version": "1.0.
|
|
149
|
+
"version": "1.0.11",
|
|
150
150
|
"name": "Access Control",
|
|
151
151
|
"description": "Require new members to complete configurable Discord interaction checks before gaining access.",
|
|
152
152
|
"category": "Safety",
|
|
@@ -176,12 +176,12 @@
|
|
|
176
176
|
{
|
|
177
177
|
"id": "helyx.forms",
|
|
178
178
|
"package": "@helyx/module-forms",
|
|
179
|
-
"version":
|
|
179
|
+
"version": "1.0.2",
|
|
180
180
|
"name": "Forms",
|
|
181
|
-
"description": "Collect structured
|
|
181
|
+
"description": "Collect reusable structured responses through Discord modals.",
|
|
182
182
|
"category": "Support & Staff",
|
|
183
|
-
"availability": "
|
|
184
|
-
"releaseStatus": "
|
|
183
|
+
"availability": "published",
|
|
184
|
+
"releaseStatus": "live"
|
|
185
185
|
},
|
|
186
186
|
{
|
|
187
187
|
"id": "helyx.faq",
|
|
@@ -296,7 +296,7 @@
|
|
|
296
296
|
{
|
|
297
297
|
"id": "helyx.reactionroles",
|
|
298
298
|
"package": "@helyx/module-reactionroles",
|
|
299
|
-
"version": "1.0.
|
|
299
|
+
"version": "1.0.10",
|
|
300
300
|
"name": "Reaction Roles",
|
|
301
301
|
"description": "Let members select approved roles themselves.",
|
|
302
302
|
"category": "Automation",
|
|
@@ -396,7 +396,7 @@
|
|
|
396
396
|
{
|
|
397
397
|
"id": "helyx.giveaways",
|
|
398
398
|
"package": "@helyx/module-giveaways",
|
|
399
|
-
"version": "1.0.
|
|
399
|
+
"version": "1.0.12",
|
|
400
400
|
"name": "Giveaways",
|
|
401
401
|
"description": "Run auditable giveaways with eligibility rules.",
|
|
402
402
|
"category": "Engagement",
|
|
@@ -416,7 +416,7 @@
|
|
|
416
416
|
{
|
|
417
417
|
"id": "helyx.counting",
|
|
418
418
|
"package": "@helyx/module-counting",
|
|
419
|
-
"version": "1.0.
|
|
419
|
+
"version": "1.0.2",
|
|
420
420
|
"name": "Counting",
|
|
421
421
|
"description": "A focused, server-scoped Discord counting game.",
|
|
422
422
|
"category": "Gaming",
|
|
@@ -426,7 +426,7 @@
|
|
|
426
426
|
{
|
|
427
427
|
"id": "helyx.trivia",
|
|
428
428
|
"package": "@helyx/module-trivia",
|
|
429
|
-
"version": "1.0.
|
|
429
|
+
"version": "1.0.2",
|
|
430
430
|
"name": "Trivia",
|
|
431
431
|
"description": "Play private trivia rounds from a saved question catalogue.",
|
|
432
432
|
"category": "Gaming",
|
|
@@ -486,7 +486,7 @@
|
|
|
486
486
|
{
|
|
487
487
|
"id": "helyx.achievements",
|
|
488
488
|
"package": "@helyx/module-achievements",
|
|
489
|
-
"version": "1.0.
|
|
489
|
+
"version": "1.0.2",
|
|
490
490
|
"name": "Achievements",
|
|
491
491
|
"description": "Configurable member milestones, scores and optional rewards.",
|
|
492
492
|
"category": "Gaming",
|
|
@@ -506,7 +506,7 @@
|
|
|
506
506
|
{
|
|
507
507
|
"id": "helyx.logging",
|
|
508
508
|
"package": "@helyx/module-logging",
|
|
509
|
-
"version": "1.1.
|
|
509
|
+
"version": "1.1.13",
|
|
510
510
|
"name": "Logging",
|
|
511
511
|
"description": "Posts configurable activity records from enabled Helyx modules.",
|
|
512
512
|
"category": "Insights",
|