create-seedcord 0.3.2 → 0.4.0

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/README.md CHANGED
@@ -6,10 +6,10 @@
6
6
  </div>
7
7
 
8
8
  <div align="center">
9
- <h3>The whole Discord bot, wired and typed</h3>
9
+ <h3>The whole Discord bot, typed end to end</h3>
10
10
  <a href="https://seedcord.org">Website</a> ·
11
- <a href="https://guide.seedcord.org">Guide</a> ·
12
- <a href="https://docs.seedcord.org">Reference</a> ·
11
+ <a href="https://seedcord.org/guide">Guide</a> ·
12
+ <a href="https://seedcord.org/docs">Reference</a> ·
13
13
  <a href="https://discord.gg/DzFxY58WXf">Discord</a>
14
14
  </div>
15
15
 
@@ -35,7 +35,9 @@ npm create seedcord my-bot
35
35
  yarn create seedcord my-bot
36
36
  ```
37
37
 
38
- It asks where the project goes, how Discord reaches your bot, what the bot should react to, your bot token, and an accent color. Then it writes the project, installs, formats, generates your command types, and makes the first commit. A step that fails after the write becomes a warning. The summary still prints.
38
+ It asks where the project goes, how Discord reaches your bot, what the bot should react to, your bot token, your app public key on http, and an accent color. Then it writes the project, installs dependencies, formats, generates your command types, and makes the first commit. If a step after the write fails, you get a warning and the summary still prints.
39
+
40
+ If you don't have the token or key yet, press Enter twice on its prompt to skip it. Fill it into `.env` before you start the bot.
39
41
 
40
42
  On Windows, run it from Windows Terminal. The prompts fall back to ASCII in `cmd.exe` making the boxes draw as `T`, `|`, and `o`.
41
43
 
@@ -50,7 +52,7 @@ npm create seedcord my-bot -- --transport gateway --capabilities reactions
50
52
  pnpm create seedcord my-bot --transport gateway --capabilities reactions
51
53
  ```
52
54
 
53
- `--no-install` and `--no-git` turn off those two steps. `-v` prints the version and `-h` prints the flag list.
55
+ `--no-install` and `--no-git` turn off those two steps. `--no-token` and `--no-public-key` leave those keys empty without asking. `-v` prints the version and `-h` prints the flag list.
54
56
 
55
57
  With no terminal to ask on, it reads the flags alone. It prints the flag that would supply any answer you left out.
56
58
 
package/dist/index.mjs CHANGED
@@ -1922,7 +1922,7 @@ const chalk = createChalk();
1922
1922
  const chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
1923
1923
 
1924
1924
  //#endregion
1925
- //#region ../../packages/errors/dist/SeedcordError-BsqYDjQD.mjs
1925
+ //#region ../../packages/errors/dist/SeedcordError-CFERGyXK.mjs
1926
1926
  /**
1927
1927
  * All Seedcord error codes.
1928
1928
  */
@@ -1995,6 +1995,8 @@ let SeedcordErrorCode = /* @__PURE__ */ function(SeedcordErrorCode) {
1995
1995
  SeedcordErrorCode[SeedcordErrorCode["CorePluginKeyHoldsGroup"] = 1216] = "CorePluginKeyHoldsGroup";
1996
1996
  /** A plugin key is empty, has an empty part, or carries more than one dot. */
1997
1997
  SeedcordErrorCode[SeedcordErrorCode["CorePluginKeyMalformed"] = 1217] = "CorePluginKeyMalformed";
1998
+ /** An attached plugin doesn't extend the `Plugin` class of the bot's `@seedcord/core`. */
1999
+ SeedcordErrorCode[SeedcordErrorCode["CorePluginFromOtherCore"] = 1218] = "CorePluginFromOtherCore";
1998
2000
  /** A command decorator attempted to re-register an existing command scope. */
1999
2001
  SeedcordErrorCode[SeedcordErrorCode["DecoratorCommandAlreadyRegistered"] = 1301] = "DecoratorCommandAlreadyRegistered";
2000
2002
  /** A global command decorator specified guild IDs, which is not allowed. */
@@ -2011,12 +2013,10 @@ let SeedcordErrorCode = /* @__PURE__ */ function(SeedcordErrorCode) {
2011
2013
  SeedcordErrorCode[SeedcordErrorCode["InteractionDuplicateRoute"] = 1401] = "InteractionDuplicateRoute";
2012
2014
  /** Two different middleware classes share a class name. */
2013
2015
  SeedcordErrorCode[SeedcordErrorCode["DuplicateMiddleware"] = 1402] = "DuplicateMiddleware";
2014
- /** A route manifest row gives an export name its module does not have. */
2015
- SeedcordErrorCode[SeedcordErrorCode["InteractionRouteExportMissing"] = 1403] = "InteractionRouteExportMissing";
2016
- /** A subscriber manifest row specifies an export that does not extend `Subscriber`. */
2017
- SeedcordErrorCode[SeedcordErrorCode["SubscriberRouteNotASubscriber"] = 1404] = "SubscriberRouteNotASubscriber";
2018
- /** A manifest row's module threw while importing. */
2019
- SeedcordErrorCode[SeedcordErrorCode["RouteModuleLoadFailed"] = 1405] = "RouteModuleLoadFailed";
2016
+ /** A manifest array lists a class that does not extend the base for that array. */
2017
+ SeedcordErrorCode[SeedcordErrorCode["ManifestEntryWrongClass"] = 1403] = "ManifestEntryWrongClass";
2018
+ /** A manifest array lists a class whose decorator is missing. Nothing registered. */
2019
+ SeedcordErrorCode[SeedcordErrorCode["ManifestEntryNoRoutes"] = 1404] = "ManifestEntryNoRoutes";
2020
2020
  /** A reply method was called in an ack state where it is illegal. */
2021
2021
  SeedcordErrorCode[SeedcordErrorCode["ReplyIllegalAckState"] = 1501] = "ReplyIllegalAckState";
2022
2022
  /** A reply component failed to serialize to raw API data. */
@@ -2242,6 +2242,7 @@ const messages = {
2242
2242
  [1207]: (dir) => `${dir} could not be read.`,
2243
2243
  [1215]: (head, key) => `${paint.sky(head)} is already taken on this bot, so ${paint.sky(key)} cannot nest under it. Pick another group name.`,
2244
2244
  [1217]: (key, reason) => `${paint.sky(key)} ${reason} Write a group and a plugin name around one dot, like 'services.users'.`,
2245
+ [1218]: (plugin) => `${paint.sky(plugin)} doesn't extend the ${paint.bold("Plugin")} class your bot uses. That usually means two copies of ${paint.bold("@seedcord/core")} are installed. Update the plugin and your ${paint.bold("@seedcord")} packages to versions that need the same ${paint.bold("@seedcord/core")}. Your package manager can list each installed copy and the package that pulled it in.`,
2245
2246
  [1216]: (key) => `${paint.sky(key)} already holds a group of plugins. Attach this one under a name of its own.`,
2246
2247
  [1208]: (key) => `Plugin key "${key}" is a channel the framework logs on. Pick another key.`,
2247
2248
  [1209]: () => "The bot's application id resolves during startup. You read it before that. Read it inside a handler, inside a plugin's ready(), or after start() resolves.",
@@ -2258,9 +2259,8 @@ const messages = {
2258
2259
  [1306]: (key) => `\`${key}\` was given an empty array. Drop the key to run the middleware on everything.`,
2259
2260
  [1401]: (route, first, second) => `Two interaction handlers resolve to the same route \`${route}\`. Registered by ${first} and ${second}. Rename one.`,
2260
2261
  [1402]: (name) => `Two different middleware classes share the name \`${name}\`. Rename one so they do not collide.`,
2261
- [1403]: (route, exportName, from) => `Route \`${route}\` loads \`${exportName}\` from ${from}, which exports no such name.`,
2262
- [1404]: (keys, exportName, from) => `Subscriber row for \`${keys}\` loads \`${exportName}\` from ${from}, which does not extend Subscriber.`,
2263
- [1405]: (route, from) => `Route \`${route}\` failed to import ${from}.`,
2262
+ [1403]: (array, className, base) => `The manifest lists \`${className}\` under \`${array}\`, but \`${className}\` doesn't extend ${base}. Move it to the array for its own base, or drop it.`,
2263
+ [1404]: (array, className, decorator) => `The manifest lists \`${className}\` under \`${array}\`, but \`${className}\` carries no ${decorator}. Add the decorator, or drop the entry.`,
2264
2264
  [1501]: (method, reason, alternative, routeId) => `${paint.sky(`${method}()`)} was called when ${reason}.\n${alternative} (route ${paint.mute(routeId)})`,
2265
2265
  [1502]: (componentClass, index, detail, routeId) => `${paint.sky(componentClass)} at components[${index}] failed to serialize: ${detail.replace(/\.$/, "")}. (route ${paint.mute(routeId)})`,
2266
2266
  [1503]: (method, targetId, routeId) => `${paint.sky(`${method}()`)} was passed message ${targetId}, which this interaction did not send.\nPass a message this interaction sent, returned by reply(), followUp(), edit(), or update(). (route ${paint.mute(routeId)})`,
@@ -2465,7 +2465,7 @@ function isSeedcordError(error, type, code) {
2465
2465
 
2466
2466
  //#endregion
2467
2467
  //#region src/cli/banner.ts
2468
- function banner(version = "0.3.2") {
2468
+ function banner(version = "0.4.0") {
2469
2469
  const wordmark = `${paint.flesh.bold("seed")}${paint.rind.bold("cord")}${paint.mute(" create")}`;
2470
2470
  if (version === void 0) return wordmark;
2471
2471
  return `${wordmark}${paint.pith(` • v${version}`)}`;
@@ -2484,6 +2484,25 @@ function validateDiscordToken(raw) {
2484
2484
  return value;
2485
2485
  }
2486
2486
 
2487
+ //#endregion
2488
+ //#region src/interview/applyFlags.ts
2489
+ function noFlagName(name) {
2490
+ return `no-${name}`;
2491
+ }
2492
+ function applyFlags(steps, raw) {
2493
+ const answers = {};
2494
+ const assign = answers;
2495
+ for (const step of steps) {
2496
+ const value = raw[step.flag.name];
2497
+ const noName = noFlagName(step.flag.name);
2498
+ const answeredNull = step.flag.noFlag !== void 0 && raw[noName] === true;
2499
+ if (answeredNull && value !== void 0) throw new SeedcordError(SeedcordErrorCode.CreateBadUsage, [`Pass --${step.flag.name} or --${noName}, not both.`]);
2500
+ if (answeredNull) assign[step.key] = null;
2501
+ else if (typeof value === "string") assign[step.key] = step.flag.parse(value);
2502
+ }
2503
+ return answers;
2504
+ }
2505
+
2487
2506
  //#endregion
2488
2507
  //#region src/interview/steps/requireAnswer.ts
2489
2508
  function requireAnswer(value) {
@@ -2785,6 +2804,34 @@ const languageStep = {
2785
2804
  }
2786
2805
  };
2787
2806
 
2807
+ //#endregion
2808
+ //#region src/interview/steps/skippable.ts
2809
+ const SKIP_WARNING = "Nothing pasted. Press Enter again to leave it empty in .env for now.";
2810
+ const SKIP_HINT = "or press Enter to add it to .env later";
2811
+ function isEmptyPaste(value) {
2812
+ return (value ?? "").trim() === "";
2813
+ }
2814
+ function answerOf(pasted, parse) {
2815
+ return isEmptyPaste(pasted) ? null : parse(pasted);
2816
+ }
2817
+ function skippable(parse, fallback) {
2818
+ let warned = false;
2819
+ return (value) => {
2820
+ if (isEmptyPaste(value)) {
2821
+ if (warned) return void 0;
2822
+ warned = true;
2823
+ return SKIP_WARNING;
2824
+ }
2825
+ warned = false;
2826
+ try {
2827
+ parse(value ?? "");
2828
+ return;
2829
+ } catch (error) {
2830
+ return Error.isError(error) ? error.message : fallback;
2831
+ }
2832
+ };
2833
+ }
2834
+
2788
2835
  //#endregion
2789
2836
  //#region src/interview/steps/publicKey.ts
2790
2837
  const PUBLIC_KEY_CHARS = 64;
@@ -2799,20 +2846,17 @@ const publicKeyStep = {
2799
2846
  flag: {
2800
2847
  name: "public-key",
2801
2848
  description: "your app public key, http only",
2802
- parse: parsePublicKey
2849
+ parse: parsePublicKey,
2850
+ noFlag: "leave the public key empty in .env to fill in later, http only"
2803
2851
  },
2804
2852
  skip: (answers) => answers.transport === "gateway",
2805
- ask: async () => parsePublicKey(requireAnswer(await text({
2806
- message: "Paste your app public key",
2807
- validate: (value) => {
2808
- try {
2809
- parsePublicKey(value ?? "");
2810
- return;
2811
- } catch (error) {
2812
- return Error.isError(error) ? error.message : "Invalid public key.";
2813
- }
2814
- }
2815
- })))
2853
+ ask: async () => {
2854
+ const pasted = requireAnswer(await text({
2855
+ message: `Paste your app public key ${paint.mute(SKIP_HINT)}`,
2856
+ validate: skippable(parsePublicKey, "Invalid public key.")
2857
+ }));
2858
+ return answerOf(pasted, parsePublicKey);
2859
+ }
2816
2860
  };
2817
2861
 
2818
2862
  //#endregion
@@ -2829,19 +2873,16 @@ const tokenStep = {
2829
2873
  flag: {
2830
2874
  name: "token",
2831
2875
  description: "your bot token",
2832
- parse: parseToken
2876
+ parse: parseToken,
2877
+ noFlag: "leave the bot token empty in .env to fill in later"
2833
2878
  },
2834
- ask: async () => parseToken(requireAnswer(await password({
2835
- message: "Paste your bot token",
2836
- validate: (value) => {
2837
- try {
2838
- parseToken(value ?? "");
2839
- return;
2840
- } catch (error) {
2841
- return Error.isError(error) ? error.message : "Invalid token.";
2842
- }
2843
- }
2844
- })))
2879
+ ask: async () => {
2880
+ const pasted = requireAnswer(await password({
2881
+ message: `Paste your bot token ${paint.mute(SKIP_HINT)}`,
2882
+ validate: skippable(parseToken, "Invalid token.")
2883
+ }));
2884
+ return answerOf(pasted, parseToken);
2885
+ }
2845
2886
  };
2846
2887
 
2847
2888
  //#endregion
@@ -2908,11 +2949,19 @@ const EXTRA = [
2908
2949
  description: "print this"
2909
2950
  }
2910
2951
  ];
2952
+ function flagsOf(step) {
2953
+ const { noFlag } = step.flag;
2954
+ if (noFlag === void 0) return [step.flag];
2955
+ return [step.flag, {
2956
+ name: noFlagName(step.flag.name),
2957
+ description: noFlag
2958
+ }];
2959
+ }
2911
2960
  function spelling(flag) {
2912
2961
  return flag.short === void 0 ? `--${flag.name}` : `-${flag.short}, --${flag.name}`;
2913
2962
  }
2914
2963
  function helpText() {
2915
- const flags = [...STEPS.map((step) => step.flag), ...EXTRA];
2964
+ const flags = [...STEPS.flatMap(flagsOf), ...EXTRA];
2916
2965
  const width = Math.max(...flags.map((flag) => spelling(flag).length));
2917
2966
  return [
2918
2967
  "Usage: create-seedcord [directory] [flags]",
@@ -2930,7 +2979,7 @@ function helpText() {
2930
2979
  const AUTHORIZE = "https://discord.com/oauth2/authorize";
2931
2980
  const SNOWFLAKE = /^\d{17,20}$/;
2932
2981
  function inviteUrl(token) {
2933
- const [encoded] = token.split(".");
2982
+ const encoded = token?.split(".")[0];
2934
2983
  if (encoded === void 0 || encoded === "") return null;
2935
2984
  const applicationId = Buffer.from(encoded, "base64").toString("utf8");
2936
2985
  if (!SNOWFLAKE.test(applicationId)) return null;
@@ -3539,22 +3588,11 @@ function execCommand(agent, args) {
3539
3588
  };
3540
3589
  }
3541
3590
 
3542
- //#endregion
3543
- //#region src/interview/applyFlags.ts
3544
- function applyFlags(steps, raw) {
3545
- const answers = {};
3546
- for (const step of steps) {
3547
- const value = raw[step.flag.name];
3548
- if (value === void 0) continue;
3549
- answers[step.key] = step.flag.parse(value);
3550
- }
3551
- return answers;
3552
- }
3553
-
3554
3591
  //#endregion
3555
3592
  //#region src/cli/parseInput.ts
3556
3593
  const OPTIONS = {
3557
3594
  ...Object.fromEntries(STEPS.map((step) => [step.flag.name, { type: "string" }])),
3595
+ ...Object.fromEntries(STEPS.filter((step) => step.flag.noFlag !== void 0).map((step) => [noFlagName(step.flag.name), { type: "boolean" }])),
3558
3596
  "no-install": { type: "boolean" },
3559
3597
  "no-git": { type: "boolean" }
3560
3598
  };
@@ -3590,7 +3628,7 @@ function parseInput(argv) {
3590
3628
  const raw = Object.fromEntries(Object.entries({
3591
3629
  ...values,
3592
3630
  dir: directory
3593
- }).filter((entry) => typeof entry[1] === "string"));
3631
+ }).filter((entry) => typeof entry[1] === "string" || typeof entry[1] === "boolean"));
3594
3632
  return {
3595
3633
  supplied: applyFlags(STEPS, raw),
3596
3634
  install: values["no-install"] !== true,
@@ -3644,7 +3682,7 @@ function silentSteps() {
3644
3682
 
3645
3683
  //#endregion
3646
3684
  //#region src/cli/version.ts
3647
- const version = "0.3.2";
3685
+ const version = "0.4.0";
3648
3686
 
3649
3687
  //#endregion
3650
3688
  //#region src/cli/summary.ts
@@ -3654,15 +3692,24 @@ const TOGGLE_LABELS = {
3654
3692
  GuildPresences: "Presence Intent",
3655
3693
  MessageContent: "Message Content Intent"
3656
3694
  };
3695
+ function keysLeftEmpty(answers) {
3696
+ return [...answers.token === null ? ["DISCORD_BOT_TOKEN"] : [], ...answers.publicKey === null ? ["DISCORD_PUBLIC_KEY"] : []];
3697
+ }
3657
3698
  function nextSteps(answers, run) {
3658
3699
  const prefix = runPrefix(run.agent);
3659
3700
  const install = run.installed ? [] : [`${run.agent} install`];
3701
+ const empty = keysLeftEmpty(answers);
3702
+ const fill = empty.length === 0 ? [] : [`fill in ${empty.join(" and ")} in .env`];
3660
3703
  return [
3661
3704
  `cd ${answers.directory}`,
3662
3705
  ...install,
3706
+ ...fill,
3663
3707
  `${prefix} dev`
3664
3708
  ];
3665
3709
  }
3710
+ function secretFlag(value, flag, placeholder) {
3711
+ return value === null ? `--${noFlagName(flag)}` : `--${flag} ${placeholder}`;
3712
+ }
3666
3713
  function dashboardToggles(capabilities) {
3667
3714
  const privileged = privilegedFor(capabilities);
3668
3715
  if (privileged.length === 0) return [];
@@ -3678,8 +3725,8 @@ function reproducingCommand(answers, agent) {
3678
3725
  `--language ${answers.language}`,
3679
3726
  `--transport ${answers.transport}`,
3680
3727
  ...answers.capabilities === void 0 ? [] : [`--capabilities ${answers.capabilities.join(",")}`],
3681
- "--token YOUR_TOKEN",
3682
- ...answers.publicKey === void 0 ? [] : ["--public-key YOUR_PUBLIC_KEY"],
3728
+ secretFlag(answers.token, "token", "YOUR_TOKEN"),
3729
+ ...answers.publicKey === void 0 ? [] : [secretFlag(answers.publicKey, "public-key", "YOUR_PUBLIC_KEY")],
3683
3730
  `--color ${answers.botColor}`
3684
3731
  ];
3685
3732
  const separator = agent === "npm" ? "-- " : "";
@@ -3688,15 +3735,23 @@ function reproducingCommand(answers, agent) {
3688
3735
 
3689
3736
  //#endregion
3690
3737
  //#region src/interview/runFlow.ts
3738
+ function unansweredReason(step) {
3739
+ const reason = "Required when there is no terminal to ask on.";
3740
+ if (step.flag.noFlag === void 0) return reason;
3741
+ return `${reason} Pass --${noFlagName(step.flag.name)} to fill it in .env later.`;
3742
+ }
3691
3743
  async function runFlow(steps, supplied, options) {
3692
3744
  const answers = { ...supplied };
3693
3745
  for (const step of steps) {
3694
3746
  if (step.skip?.(answers)) {
3695
- if (step.key in supplied) throw new SeedcordError(SeedcordErrorCode.CreateFlagNotApplicable, [step.flag.name]);
3747
+ if (step.key in supplied) {
3748
+ const flag = supplied[step.key] === null ? noFlagName(step.flag.name) : step.flag.name;
3749
+ throw new SeedcordError(SeedcordErrorCode.CreateFlagNotApplicable, [flag]);
3750
+ }
3696
3751
  continue;
3697
3752
  }
3698
3753
  if (answers[step.key] !== void 0) continue;
3699
- if (!options.interactive) throw new SeedcordError(SeedcordErrorCode.CreateInvalidAnswer, [step.flag.name, "Required when there is no terminal to ask on."]);
3754
+ if (!options.interactive) throw new SeedcordError(SeedcordErrorCode.CreateInvalidAnswer, [step.flag.name, unansweredReason(step)]);
3700
3755
  answers[step.key] = await step.ask(answers);
3701
3756
  }
3702
3757
  return answers;
@@ -3885,7 +3940,7 @@ function buildContext(answers, extras) {
3885
3940
  intents: isGateway ? intentsFor(capabilities) : [],
3886
3941
  partials: isGateway ? partialsFor(capabilities) : [],
3887
3942
  hasMessages: capabilities.some((id) => MESSAGE_CAPABILITIES.has(id)),
3888
- token: answers.token,
3943
+ token: answers.token ?? "",
3889
3944
  publicKey: answers.publicKey ?? "",
3890
3945
  botColor: answers.botColor,
3891
3946
  developerUsername: extras.developerUsername,
@@ -4033,11 +4088,12 @@ var require_block_helper_missing = /* @__PURE__ */ __commonJSMin(((exports, modu
4033
4088
  var inverse = options.inverse, fn = options.fn;
4034
4089
  if (context === true) return fn(this);
4035
4090
  else if (context === false || context == null) return inverse(this);
4036
- else if (_utils.isArray(context)) if (context.length > 0) {
4037
- if (options.ids) options.ids = [options.name];
4038
- return instance.helpers.each(context, options);
4039
- } else return inverse(this);
4040
- else {
4091
+ else if (_utils.isArray(context)) {
4092
+ if (context.length > 0) {
4093
+ if (options.ids) options.ids = [options.name];
4094
+ return instance.helpers.each(context, options);
4095
+ } else return inverse(this);
4096
+ } else {
4041
4097
  if (options.data && options.ids) {
4042
4098
  var data = _utils.createFrame(options.data);
4043
4099
  data.contextPath = _utils.appendContextPath(options.data.contextPath, options.name);
@@ -4080,23 +4136,25 @@ var require_each = /* @__PURE__ */ __commonJSMin(((exports, module) => {
4080
4136
  blockParams: _utils.blockParams([context[field], field], [contextPath + field, null])
4081
4137
  });
4082
4138
  }
4083
- if (context && typeof context === "object") if (_utils.isArray(context)) {
4084
- for (var j = context.length; i < j; i++) if (i in context) execIteration(i, i, i === context.length - 1);
4085
- } else if (typeof Symbol === "function" && context[Symbol.iterator]) {
4086
- var newContext = [];
4087
- var iterator = context[Symbol.iterator]();
4088
- for (var it = iterator.next(); !it.done; it = iterator.next()) newContext.push(it.value);
4089
- context = newContext;
4090
- for (var j = context.length; i < j; i++) execIteration(i, i, i === context.length - 1);
4091
- } else (function() {
4092
- var priorKey = void 0;
4093
- Object.keys(context).forEach(function(key) {
4094
- if (priorKey !== void 0) execIteration(priorKey, i - 1);
4095
- priorKey = key;
4096
- i++;
4097
- });
4098
- if (priorKey !== void 0) execIteration(priorKey, i - 1, true);
4099
- })();
4139
+ if (context && typeof context === "object") {
4140
+ if (_utils.isArray(context)) {
4141
+ for (var j = context.length; i < j; i++) if (i in context) execIteration(i, i, i === context.length - 1);
4142
+ } else if (typeof Symbol === "function" && context[Symbol.iterator]) {
4143
+ var newContext = [];
4144
+ var iterator = context[Symbol.iterator]();
4145
+ for (var it = iterator.next(); !it.done; it = iterator.next()) newContext.push(it.value);
4146
+ context = newContext;
4147
+ for (var j = context.length; i < j; i++) execIteration(i, i, i === context.length - 1);
4148
+ } else (function() {
4149
+ var priorKey = void 0;
4150
+ Object.keys(context).forEach(function(key) {
4151
+ if (priorKey !== void 0) execIteration(priorKey, i - 1);
4152
+ priorKey = key;
4153
+ i++;
4154
+ });
4155
+ if (priorKey !== void 0) execIteration(priorKey, i - 1, true);
4156
+ })();
4157
+ }
4100
4158
  if (i === 0) ret = inverse(this);
4101
4159
  return ret;
4102
4160
  });
@@ -4622,8 +4680,10 @@ var require_runtime = /* @__PURE__ */ __commonJSMin(((exports) => {
4622
4680
  ret._setup(options);
4623
4681
  if (!options.partial && templateSpec.useData) data = initData(context, data);
4624
4682
  var depths = void 0, blockParams = templateSpec.useBlockParams ? [] : void 0;
4625
- if (templateSpec.useDepths) if (options.depths) depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
4626
- else depths = [context];
4683
+ if (templateSpec.useDepths) {
4684
+ if (options.depths) depths = context != options.depths[0] ? [context].concat(options.depths) : options.depths;
4685
+ else depths = [context];
4686
+ }
4627
4687
  function main(context) {
4628
4688
  return "" + templateSpec.main(container, context, container.helpers, container.partials, data, blockParams, depths);
4629
4689
  }
@@ -4676,9 +4736,10 @@ var require_runtime = /* @__PURE__ */ __commonJSMin(((exports) => {
4676
4736
  * This is currently part of the official API, therefore implementation details should not be changed.
4677
4737
  */
4678
4738
  function resolvePartial(partial, context, options) {
4679
- if (!partial) if (options.name === "@partial-block") partial = lookupOwnProperty(options.data, "partial-block");
4680
- else partial = lookupOwnProperty(options.partials, options.name);
4681
- else if (!partial.call && !options.name) {
4739
+ if (!partial) {
4740
+ if (options.name === "@partial-block") partial = lookupOwnProperty(options.data, "partial-block");
4741
+ else partial = lookupOwnProperty(options.partials, options.name);
4742
+ } else if (!partial.call && !options.name) {
4682
4743
  options.name = partial;
4683
4744
  partial = lookupOwnProperty(options.partials, partial);
4684
4745
  }
@@ -7831,12 +7892,14 @@ var require_compiler = /* @__PURE__ */ __commonJSMin(((exports) => {
7831
7892
  if (program) program = this.compileProgram(partial.program);
7832
7893
  var params = partial.params;
7833
7894
  if (params.length > 1) throw new _exception2["default"]("Unsupported number of partial arguments: " + params.length, partial);
7834
- else if (!params.length) if (this.options.explicitPartialContext) this.opcode("pushLiteral", "undefined");
7835
- else params.push({
7836
- type: "PathExpression",
7837
- parts: [],
7838
- depth: 0
7839
- });
7895
+ else if (!params.length) {
7896
+ if (this.options.explicitPartialContext) this.opcode("pushLiteral", "undefined");
7897
+ else params.push({
7898
+ type: "PathExpression",
7899
+ parts: [],
7900
+ depth: 0
7901
+ });
7902
+ }
7840
7903
  var partialName = partial.name.original, isDynamic = partial.name.type === "SubExpression";
7841
7904
  if (isDynamic) this.accept(partial.name);
7842
7905
  this.setupFullMustacheParams(partial, program, void 0, true);
@@ -8221,12 +8284,14 @@ var require_util = /* @__PURE__ */ __commonJSMin(((exports) => {
8221
8284
  part = parts[i];
8222
8285
  if (part === ".") parts.splice(i, 1);
8223
8286
  else if (part === "..") up++;
8224
- else if (up > 0) if (part === "") {
8225
- parts.splice(i + 1, up);
8226
- up = 0;
8227
- } else {
8228
- parts.splice(i, 2);
8229
- up--;
8287
+ else if (up > 0) {
8288
+ if (part === "") {
8289
+ parts.splice(i + 1, up);
8290
+ up = 0;
8291
+ } else {
8292
+ parts.splice(i, 2);
8293
+ up--;
8294
+ }
8230
8295
  }
8231
8296
  }
8232
8297
  path = parts.join("/");
@@ -8479,8 +8544,10 @@ var require_array_set = /* @__PURE__ */ __commonJSMin(((exports) => {
8479
8544
  var isDuplicate = hasNativeMap ? this.has(aStr) : has.call(this._set, sStr);
8480
8545
  var idx = this._array.length;
8481
8546
  if (!isDuplicate || aAllowDuplicates) this._array.push(aStr);
8482
- if (!isDuplicate) if (hasNativeMap) this._set.set(aStr, idx);
8483
- else this._set[sStr] = idx;
8547
+ if (!isDuplicate) {
8548
+ if (hasNativeMap) this._set.set(aStr, idx);
8549
+ else this._set[sStr] = idx;
8550
+ }
8484
8551
  };
8485
8552
  /**
8486
8553
  * Is the given string a member of this set?
@@ -9228,8 +9295,8 @@ var require_source_map_consumer = /* @__PURE__ */ __commonJSMin(((exports) => {
9228
9295
  var relativeSource = aSource;
9229
9296
  if (this.sourceRoot != null) relativeSource = util.relative(this.sourceRoot, relativeSource);
9230
9297
  if (this._sources.has(relativeSource)) return this._sources.indexOf(relativeSource);
9231
- var i;
9232
- for (i = 0; i < this._absoluteSources.length; ++i) if (this._absoluteSources[i] == aSource) return i;
9298
+ var i = 0;
9299
+ for (; i < this._absoluteSources.length; ++i) if (this._absoluteSources[i] == aSource) return i;
9233
9300
  return -1;
9234
9301
  };
9235
9302
  /**
@@ -9802,18 +9869,20 @@ var require_source_node = /* @__PURE__ */ __commonJSMin(((exports) => {
9802
9869
  var lastGeneratedLine = 1, lastGeneratedColumn = 0;
9803
9870
  var lastMapping = null;
9804
9871
  aSourceMapConsumer.eachMapping(function(mapping) {
9805
- if (lastMapping !== null) if (lastGeneratedLine < mapping.generatedLine) {
9806
- addMappingWithCode(lastMapping, shiftNextLine());
9807
- lastGeneratedLine++;
9808
- lastGeneratedColumn = 0;
9809
- } else {
9810
- var nextLine = remainingLines[remainingLinesIndex] || "";
9811
- var code = nextLine.substr(0, mapping.generatedColumn - lastGeneratedColumn);
9812
- remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - lastGeneratedColumn);
9813
- lastGeneratedColumn = mapping.generatedColumn;
9814
- addMappingWithCode(lastMapping, code);
9815
- lastMapping = mapping;
9816
- return;
9872
+ if (lastMapping !== null) {
9873
+ if (lastGeneratedLine < mapping.generatedLine) {
9874
+ addMappingWithCode(lastMapping, shiftNextLine());
9875
+ lastGeneratedLine++;
9876
+ lastGeneratedColumn = 0;
9877
+ } else {
9878
+ var nextLine = remainingLines[remainingLinesIndex] || "";
9879
+ var code = nextLine.substr(0, mapping.generatedColumn - lastGeneratedColumn);
9880
+ remainingLines[remainingLinesIndex] = nextLine.substr(mapping.generatedColumn - lastGeneratedColumn);
9881
+ lastGeneratedColumn = mapping.generatedColumn;
9882
+ addMappingWithCode(lastMapping, code);
9883
+ lastMapping = mapping;
9884
+ return;
9885
+ }
9817
9886
  }
9818
9887
  while (lastGeneratedLine < mapping.generatedLine) {
9819
9888
  node.add(shiftNextLine());
@@ -10538,8 +10607,10 @@ var require_javascript_compiler = /* @__PURE__ */ __commonJSMin(((exports, modul
10538
10607
  pushStringParam: function pushStringParam(string, type) {
10539
10608
  this.pushContext();
10540
10609
  this.pushString(type);
10541
- if (type !== "SubExpression") if (typeof string === "string") this.pushString(string);
10542
- else this.pushStackLiteral(string);
10610
+ if (type !== "SubExpression") {
10611
+ if (typeof string === "string") this.pushString(string);
10612
+ else this.pushStackLiteral(string);
10613
+ }
10543
10614
  },
10544
10615
  emptyHash: function emptyHash(omitEmpty) {
10545
10616
  if (this.trackIds) this.push("{}");
@@ -11353,7 +11424,7 @@ async function reportOutcome(answers, agent, installed, interactive) {
11353
11424
  const invite = inviteUrl(answers.token);
11354
11425
  if (invite !== null) copyable("Add the bot to a server", paint.sky(invite));
11355
11426
  copyable("Run this setup again", paint.mute(reproducingCommand(answers, agent)));
11356
- outro(paint.sky("https://guide.seedcord.org"));
11427
+ outro(paint.sky("https://seedcord.org/guide"));
11357
11428
  }
11358
11429
  try {
11359
11430
  await main();