@halospv3/hce.shared-config 3.5.3-develop.1 → 3.6.0-develop.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.
Files changed (136) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +33 -10
  3. package/dotnet/.github/workflows/_unit_test.yml +2 -2
  4. package/dotnet/.github/workflows/dotnet-release.yml +1 -1
  5. package/dotnet/.github/workflows/sample-dotnet-build.yml +1 -1
  6. package/dotnet/CleanupWpfTmp.targets +15 -0
  7. package/dotnet/HCE.Shared.targets +3 -0
  8. package/mjs/CaseInsensitiveMap.mjs.map +1 -1
  9. package/mjs/commitlintConfig.mjs.map +1 -1
  10. package/mjs/debug.mjs.map +1 -1
  11. package/mjs/dotnet/GithubNugetRegistryInfo.d.mts +5 -5
  12. package/mjs/dotnet/GithubNugetRegistryInfo.d.mts.map +1 -1
  13. package/mjs/dotnet/GithubNugetRegistryInfo.mjs +7 -7
  14. package/mjs/dotnet/GithubNugetRegistryInfo.mjs.map +1 -1
  15. package/mjs/dotnet/GitlabNugetRegistryInfo.d.mts +6 -6
  16. package/mjs/dotnet/GitlabNugetRegistryInfo.d.mts.map +1 -1
  17. package/mjs/dotnet/GitlabNugetRegistryInfo.mjs +14 -14
  18. package/mjs/dotnet/GitlabNugetRegistryInfo.mjs.map +1 -1
  19. package/mjs/dotnet/IsNextVersionAlreadyPublished.cli.mjs +5 -5
  20. package/mjs/dotnet/IsNextVersionAlreadyPublished.cli.mjs.map +1 -1
  21. package/mjs/dotnet/MSBuildProject.d.mts +28 -28
  22. package/mjs/dotnet/MSBuildProject.d.mts.map +1 -1
  23. package/mjs/dotnet/MSBuildProject.mjs +88 -66
  24. package/mjs/dotnet/MSBuildProject.mjs.map +1 -1
  25. package/mjs/dotnet/MSBuildProjectProperties.d.mts.map +1 -1
  26. package/mjs/dotnet/MSBuildProjectProperties.mjs +1 -1
  27. package/mjs/dotnet/MSBuildProjectProperties.mjs.map +1 -1
  28. package/mjs/dotnet/NugetProjectProperties.d.mts +3 -3
  29. package/mjs/dotnet/NugetProjectProperties.d.mts.map +1 -1
  30. package/mjs/dotnet/NugetProjectProperties.mjs +7 -9
  31. package/mjs/dotnet/NugetProjectProperties.mjs.map +1 -1
  32. package/mjs/dotnet/NugetRegistryInfo.d.mts +40 -40
  33. package/mjs/dotnet/NugetRegistryInfo.d.mts.map +1 -1
  34. package/mjs/dotnet/NugetRegistryInfo.mjs +170 -148
  35. package/mjs/dotnet/NugetRegistryInfo.mjs.map +1 -1
  36. package/mjs/dotnet/helpers.d.mts.map +1 -1
  37. package/mjs/dotnet/helpers.mjs +33 -34
  38. package/mjs/dotnet/helpers.mjs.map +1 -1
  39. package/mjs/eslintConfig.mjs.map +1 -1
  40. package/mjs/insertPlugins.mjs +2 -2
  41. package/mjs/insertPlugins.mjs.map +1 -1
  42. package/mjs/semantic-release__commit-analyzer.d.mts.map +1 -1
  43. package/mjs/semantic-release__exec.d.mts.map +1 -1
  44. package/mjs/semantic-release__git.d.mts.map +1 -1
  45. package/mjs/semantic-release__github.d.mts +1 -0
  46. package/mjs/semantic-release__github.d.mts.map +1 -1
  47. package/mjs/semanticReleaseConfig.d.mts.map +1 -1
  48. package/mjs/semanticReleaseConfig.mjs.map +1 -1
  49. package/mjs/semanticReleaseConfigDotnet.d.mts.map +1 -1
  50. package/mjs/semanticReleaseConfigDotnet.mjs +23 -16
  51. package/mjs/semanticReleaseConfigDotnet.mjs.map +1 -1
  52. package/mjs/setupGitPluginSpec.d.mts.map +1 -1
  53. package/mjs/setupGitPluginSpec.default.mjs.map +1 -1
  54. package/mjs/setupGitPluginSpec.mjs +19 -19
  55. package/mjs/setupGitPluginSpec.mjs.map +1 -1
  56. package/mjs/utils/Exact.d.mts.map +1 -1
  57. package/mjs/utils/GracefulRecursion.d.mts.map +1 -1
  58. package/mjs/utils/env.d.mts.map +1 -1
  59. package/mjs/utils/env.mjs.map +1 -1
  60. package/mjs/utils/execAsync.d.mts +3 -3
  61. package/mjs/utils/execAsync.d.mts.map +1 -1
  62. package/mjs/utils/execAsync.mjs +14 -12
  63. package/mjs/utils/execAsync.mjs.map +1 -1
  64. package/mjs/utils/isError.mjs.map +1 -1
  65. package/mjs/utils/miscTypes.d.mts.map +1 -1
  66. package/mjs/utils/miscTypes.mjs.map +1 -1
  67. package/mjs/utils/reflection/FunctionLike.d.mts +1 -0
  68. package/mjs/utils/reflection/FunctionLike.d.mts.map +1 -1
  69. package/mjs/utils/reflection/GetterDescriptor.d.mts.map +1 -1
  70. package/mjs/utils/reflection/InstancePropertyDescriptorMap.d.mts.map +1 -1
  71. package/mjs/utils/reflection/InstanceTypeOrSelfPropertyDescriptorMap.d.mts +1 -1
  72. package/mjs/utils/reflection/InstanceTypeOrSelfPropertyDescriptorMap.d.mts.map +1 -1
  73. package/mjs/utils/reflection/OwnGetterDescriptorMap.d.mts +1 -1
  74. package/mjs/utils/reflection/OwnGetterDescriptorMap.d.mts.map +1 -1
  75. package/mjs/utils/reflection/OwnKeyOf.d.mts +1 -1
  76. package/mjs/utils/reflection/OwnKeyOf.d.mts.map +1 -1
  77. package/mjs/utils/reflection/OwnPropertyDescriptorMap.d.mts.map +1 -1
  78. package/mjs/utils/reflection/PropertyDescriptorMap.d.mts +1 -1
  79. package/mjs/utils/reflection/PropertyDescriptorMap.d.mts.map +1 -1
  80. package/mjs/utils/reflection/filterForGetters.d.mts.map +1 -1
  81. package/mjs/utils/reflection/filterForGetters.mjs.map +1 -1
  82. package/mjs/utils/reflection/getOwnPropertyDescriptors.d.mts.map +1 -1
  83. package/mjs/utils/reflection/getOwnPropertyDescriptors.mjs.map +1 -1
  84. package/mjs/utils/reflection/getOwnPropertyDescriptorsRecursively.d.mts.map +1 -1
  85. package/mjs/utils/reflection/getOwnPropertyDescriptorsRecursively.mjs +3 -3
  86. package/mjs/utils/reflection/getOwnPropertyDescriptorsRecursively.mjs.map +1 -1
  87. package/mjs/utils/reflection/getPrototypeChainOf.d.mts +2 -2
  88. package/mjs/utils/reflection/getPrototypeChainOf.d.mts.map +1 -1
  89. package/mjs/utils/reflection/getPrototypeChainOf.mjs +1 -2
  90. package/mjs/utils/reflection/getPrototypeChainOf.mjs.map +1 -1
  91. package/mjs/utils/reflection/getPrototypeOf.d.mts.map +1 -1
  92. package/mjs/utils/reflection/getPrototypeOf.mjs.map +1 -1
  93. package/mjs/utils/reflection/inheritance.d.mts +4 -4
  94. package/mjs/utils/reflection/inheritance.d.mts.map +1 -1
  95. package/mjs/utils/reflection/inheritance.mjs.map +1 -1
  96. package/mjs/utils/reflection/isConstructor.d.mts +3 -3
  97. package/mjs/utils/reflection/isConstructor.d.mts.map +1 -1
  98. package/mjs/utils/reflection/isConstructor.mjs +7 -7
  99. package/mjs/utils/reflection/isConstructor.mjs.map +1 -1
  100. package/mjs/utils/reflection/isGetterDescriptor.d.mts.map +1 -1
  101. package/mjs/utils/reflection/isGetterDescriptor.mjs.map +1 -1
  102. package/mjs/utils/reflection/listOwnGetters.d.mts.map +1 -1
  103. package/mjs/utils/reflection/listOwnGetters.mjs +4 -2
  104. package/mjs/utils/reflection/listOwnGetters.mjs.map +1 -1
  105. package/mjs/utils/reflection.d.mts +1 -1
  106. package/package.json +26 -25
  107. package/src/dotnet/GithubNugetRegistryInfo.ts +18 -15
  108. package/src/dotnet/GitlabNugetRegistryInfo.ts +28 -26
  109. package/src/dotnet/IsNextVersionAlreadyPublished.cli.ts +6 -6
  110. package/src/dotnet/MSBuildProject.ts +103 -106
  111. package/src/dotnet/MSBuildProjectProperties.ts +1 -1
  112. package/src/dotnet/NugetProjectProperties.ts +13 -18
  113. package/src/dotnet/NugetRegistryInfo.ts +287 -243
  114. package/src/dotnet/helpers.ts +58 -58
  115. package/src/insertPlugins.ts +3 -3
  116. package/src/semantic-release__github.d.ts +1 -0
  117. package/src/semanticReleaseConfigDotnet.ts +52 -54
  118. package/src/setupGitPluginSpec.ts +25 -26
  119. package/src/utils/env.ts +1 -0
  120. package/src/utils/execAsync.ts +16 -13
  121. package/src/utils/reflection/FunctionLike.d.ts +1 -0
  122. package/src/utils/reflection/InstancePropertyDescriptorMap.d.ts +4 -4
  123. package/src/utils/reflection/InstanceTypeOrSelfPropertyDescriptorMap.d.ts +6 -6
  124. package/src/utils/reflection/OwnGetterDescriptorMap.d.ts +2 -2
  125. package/src/utils/reflection/OwnKeyOf.d.ts +3 -3
  126. package/src/utils/reflection/OwnPropertyDescriptorMap.d.ts +3 -3
  127. package/src/utils/reflection/PropertyDescriptorMap.d.ts +3 -3
  128. package/src/utils/reflection/filterForGetters.ts +10 -10
  129. package/src/utils/reflection/getOwnPropertyDescriptors.ts +2 -2
  130. package/src/utils/reflection/getOwnPropertyDescriptorsRecursively.ts +13 -13
  131. package/src/utils/reflection/getPrototypeChainOf.ts +17 -17
  132. package/src/utils/reflection/getPrototypeOf.ts +2 -2
  133. package/src/utils/reflection/inheritance.ts +5 -4
  134. package/src/utils/reflection/isConstructor.ts +7 -7
  135. package/src/utils/reflection/listOwnGetters.ts +8 -8
  136. package/tsconfig.base.json +2 -0
@@ -18,14 +18,14 @@ import { cwd, env } from 'node:process';
18
18
  import { setTimeout } from 'node:timers/promises';
19
19
  import { isError } from '../utils/isError.ts';
20
20
  import sanitizeFileName from 'sanitize-filename';
21
- import { getEnvVarValue } from '../utils/env.ts';
21
+ import { getEnvVarValue as getEnvironmentVariableValue } from '../utils/env.ts';
22
22
  import { execAsync } from '../utils/execAsync.ts';
23
23
  import { catchEBUSY, MSBuildEvaluationOutput, MSBuildProject } from './MSBuildProject.ts';
24
24
  import type { Default } from 'arktype/internal/attributes.ts';
25
25
 
26
- type TmpDirNamespace_Unix = `${ReturnType<typeof tmpdir>}/HCE.Shared/.NET/Dummies`;
27
- type TmpDirNamespace_Win = `${ReturnType<typeof tmpdir>}\\HCE.Shared\\.NET\\Dummies`;
28
- const tmpDirNamespace = node_path.join(tmpdir(), 'HCE.Shared', '.NET', 'Dummies') as TmpDirNamespace_Unix | TmpDirNamespace_Win;
26
+ type TemporaryDirectoryNamespace_Unix = `${ReturnType<typeof tmpdir>}/HCE.Shared/.NET/Dummies`;
27
+ type TemporaryDirectoryNamespace_Win = `${ReturnType<typeof tmpdir>}\\HCE.Shared\\.NET\\Dummies`;
28
+ const temporaryDirectoryNamespace = node_path.join(tmpdir(), 'HCE.Shared', '.NET', 'Dummies') as TemporaryDirectoryNamespace_Unix | TemporaryDirectoryNamespace_Win;
29
29
  const defaultNugetSource = 'https://api.nuget.org/v3/index.json';
30
30
  const key_OutputPackItems = '_OutputPackItems';
31
31
  /**
@@ -42,16 +42,16 @@ export async function getGithubOutput(): Promise<ReturnType<typeof configDotenv>
42
42
  }
43
43
 
44
44
  const encoding = await detectFile(env['GITHUB_OUTPUT']);
45
- const envOutput = configDotenv({
45
+ const environmentOutput = configDotenv({
46
46
  path: env['GITHUB_OUTPUT'],
47
47
  override: true,
48
48
  encoding: encoding ?? undefined,
49
49
  processEnv: {},
50
50
  });
51
51
 
52
- if (isError(envOutput.error))
53
- throw envOutput.error;
54
- return envOutput.parsed;
52
+ if (isError(environmentOutput.error))
53
+ throw environmentOutput.error;
54
+ return environmentOutput.parsed;
55
55
  }
56
56
 
57
57
  /**
@@ -68,7 +68,7 @@ export function getGithubOutputSync(): NonNullable<ReturnType<typeof configDoten
68
68
  }
69
69
 
70
70
  const encoding = detectFileSync(env['GITHUB_OUTPUT']);
71
- const envOutput = configDotenv({
71
+ const environmentOutput = configDotenv({
72
72
  path: env['GITHUB_OUTPUT'],
73
73
  override: true,
74
74
  encoding: encoding ?? undefined,
@@ -76,19 +76,19 @@ export function getGithubOutputSync(): NonNullable<ReturnType<typeof configDoten
76
76
  }) as { error: Error }
77
77
  | { parsed: NonNullable<ReturnType<typeof configDotenv>['parsed']> };
78
78
 
79
- if ('error' in envOutput)
80
- throw envOutput.error;
81
- return envOutput.parsed;
79
+ if ('error' in environmentOutput)
80
+ throw environmentOutput.error;
81
+ return environmentOutput.parsed;
82
82
  }
83
83
 
84
- type DummiesDir<T> = T extends undefined
85
- ? `${TmpDirNamespace_Unix}/` | `${TmpDirNamespace_Win}\\`
84
+ type DummiesDirectory<T> = T extends undefined
85
+ ? `${TemporaryDirectoryNamespace_Unix}/` | `${TemporaryDirectoryNamespace_Win}\\`
86
86
  : T extends MSBuildProject
87
- ? `${TmpDirNamespace_Unix}/${T['Properties']['PackageId']}/` | `${TmpDirNamespace_Win}\\${T['Properties']['PackageId']}\\`
87
+ ? `${TemporaryDirectoryNamespace_Unix}/${T['Properties']['PackageId']}/` | `${TemporaryDirectoryNamespace_Win}\\${T['Properties']['PackageId']}\\`
88
88
  : never;
89
89
 
90
- function getDummiesDir<T extends MSBuildProject | undefined = undefined>(project?: T): DummiesDir<T>;
91
- function getDummiesDir<T extends MSBuildProject>(project: T): DummiesDir<T>;
90
+ function getDummiesDirectory<T extends MSBuildProject | undefined = undefined>(project?: T): DummiesDirectory<T>;
91
+ function getDummiesDirectory<T extends MSBuildProject>(project: T): DummiesDirectory<T>;
92
92
  /**
93
93
  * Get HCE.Shared's temporary directory for .NET projects' dummy packages.
94
94
  * @param project The MSBuild project whose PackageId will be used to create a
@@ -97,17 +97,17 @@ function getDummiesDir<T extends MSBuildProject>(project: T): DummiesDir<T>;
97
97
  * `${tmpdir()}/HCE.Shared/.NET/Dummies/${project.Properties.PackageId}` if
98
98
  * {@link project} is defined. Else `${tmpdir()}/HCE.Shared/.NET/Dummies`
99
99
  */
100
- function getDummiesDir<T extends MSBuildProject | undefined = undefined>(project?: T): DummiesDir<typeof project> {
100
+ function getDummiesDirectory<T extends MSBuildProject | undefined = undefined>(project?: T): DummiesDirectory<typeof project> {
101
101
  switch (true) {
102
102
  case project === undefined: {
103
- return node_path.join(tmpDirNamespace, node_path.sep) as
104
- DummiesDir<typeof project> satisfies
105
- ReturnType<typeof getDummiesDir>;
103
+ return node_path.join(temporaryDirectoryNamespace, node_path.sep) as
104
+ DummiesDirectory<typeof project> satisfies
105
+ ReturnType<typeof getDummiesDirectory>;
106
106
  }
107
107
  case project instanceof MSBuildProject: {
108
- return node_path.join(tmpDirNamespace, project.Properties.PackageId, node_path.sep) as
109
- DummiesDir<typeof project> satisfies
110
- ReturnType<typeof getDummiesDir<MSBuildProject>>;
108
+ return node_path.join(temporaryDirectoryNamespace, project.Properties.PackageId, node_path.sep) as
109
+ DummiesDirectory<typeof project> satisfies
110
+ ReturnType<typeof getDummiesDirectory<MSBuildProject>>;
111
111
  }
112
112
  default: {
113
113
  throw new Error('The type of argument `project` must be `undefined` or `MSBuildProject`.');
@@ -117,18 +117,18 @@ function getDummiesDir<T extends MSBuildProject | undefined = undefined>(project
117
117
 
118
118
  /**
119
119
  * Get the environment variables as key-value pairs.
120
- * @param tokenEnvVars The name of the environment variables whose values are
120
+ * @param tokenEnvironmentVariables The name of the environment variables whose values are
121
121
  * NuGet API keys.
122
122
  * @returns an array of key-value pairs of the given environment variables and
123
123
  * their values, filtered to only those whose values are not undefined.
124
124
  * @throws {Error} when none of the provided environment variables are defined.
125
125
  */
126
- function _GetTokenEnvVariables(tokenEnvVars: readonly string[]): undefined | [readonly [string, string], ...readonly [string, string][]] {
126
+ function _GetTokenEnvironmentVariables(tokenEnvironmentVariables: readonly string[]): undefined | [readonly [string, string], ...readonly [string, string][]] {
127
127
  const definedTokens = Object.freeze(
128
- tokenEnvVars
129
- .map((key: string) => [key, getEnvVarValue(key)] as const)
130
- .filter((envVarTuple: readonly [string, string | undefined]): envVarTuple is [string, string] =>
131
- envVarTuple[1] !== undefined,
128
+ tokenEnvironmentVariables
129
+ .map((key: string) => [key, getEnvironmentVariableValue(key)] as const)
130
+ .filter((environmentVariableTuple: readonly [string, string | undefined]): environmentVariableTuple is [string, string] =>
131
+ environmentVariableTuple[1] !== undefined,
132
132
  ),
133
133
  );
134
134
 
@@ -138,14 +138,30 @@ function _GetTokenEnvVariables(tokenEnvVars: readonly string[]): undefined | [re
138
138
  }
139
139
 
140
140
  export class NugetRegistryInfo {
141
- private _canPushPackagesToSource: Promise<true> | undefined = undefined;
142
- private readonly _project: MSBuildProject;
143
- private readonly _resolvedEnvVariable: string | undefined;
144
- private readonly _source: string;
145
-
146
141
  public static readonly DefaultTokenEnvVars: readonly ['NUGET_TOKEN']
147
142
  = Object.freeze(['NUGET_TOKEN'] as const);
148
143
 
144
+ /**
145
+ * Get the API token from {@link NugetRegistryInfo#resolvedEnvVariable}
146
+ * @param resolvedEnvironmentVariable The name of the environment variable(s) whose
147
+ * value is a NuGet API key. Typically, the value of
148
+ * {@link NugetRegistryInfo#resolvedEnvVariable}.
149
+ * @returns The value of the first defined environment variable.
150
+ * @throws {Error} when none of the provided environment variables are defined.
151
+ */
152
+ private static _GetTokenValue(resolvedEnvironmentVariable: string): string {
153
+ type.string.assert(resolvedEnvironmentVariable);
154
+
155
+ const tokenValue = getEnvironmentVariableValue(resolvedEnvironmentVariable);
156
+ if (tokenValue === undefined) {
157
+ throw new Error(`\
158
+ The environment variable ${resolvedEnvironmentVariable} was specified \
159
+ as the source of the token to push a NuGet package, \
160
+ but the environment variable is empty or undefined.`);
161
+ }
162
+ return tokenValue;
163
+ }
164
+
149
165
  /**
150
166
  * Convert a URL string to a filesystem folder name.
151
167
  *
@@ -167,6 +183,11 @@ export class NugetRegistryInfo {
167
183
  );
168
184
  }
169
185
 
186
+ private _canPushPackagesToSource: Promise<true> | undefined = undefined;
187
+ private readonly _project: MSBuildProject;
188
+ private readonly _resolvedEnvVariable: string | undefined;
189
+ private readonly _source: string;
190
+
170
191
  /**
171
192
  * Creates an instance of NugetRegistryInfo.\
172
193
  * This class enables the ability to push a given {@link project}'s
@@ -183,32 +204,32 @@ export class NugetRegistryInfo {
183
204
  * Release's config object for later use by `@semantic-release/exec`.
184
205
  * - Other EcmaScript modules can access the environment variable(s) and steal
185
206
  * your key. Be aware of malicious dependencies!
186
- * @param opts The input type of {@link NRIOpts.from}
187
- * @param opts.project The project whose package(s) will be
207
+ * @param options The input type of {@link NRIOpts.from}
208
+ * @param options.project The project whose package(s) will be
188
209
  * pushed.\
189
210
  * - Its {@link NugetProjectProperties#PackageId} will be read.\
190
211
  * - Its {@link NugetProjectProperties#PackageVersion} will be overridden via CLI args when creating a dummy package. The real package's
191
212
  * `PackageVersion` will *not* be overridden.
192
- * @param [opts.tokenEnvVars] The environment variables
213
+ * @param [options.tokenEnvVars] The environment variables
193
214
  * whose values are tokens with permission to push a package to the NuGet
194
215
  * package registry. The array is iterated through until one token is found.
195
216
  * If none of the environment variables are defined, this constructor will
196
217
  * throw an {@link Error}.
197
- * @param [opts.source] A NuGet package registry's API endpoint URL or name. Default: 'https://api.nuget.org/v3/index.json'
218
+ * @param [options.source] A NuGet package registry's API endpoint URL or name. Default: 'https://api.nuget.org/v3/index.json'
198
219
  */
199
- constructor(opts: typeof NRIOpts['inferIn']) {
200
- // note: you can reassign `opts` only when typeof `inferOut` is assignable
220
+ constructor(options: typeof NRIOpts['inferIn']) {
221
+ // note: you can reassign `options` only when typeof `inferOut` is assignable
201
222
  // to typeof `inferIn`.
202
- const validOpts = NRIOpts.from(opts);
203
- this._project = validOpts.project;
223
+ const validOptions = NRIOpts.from(options);
224
+ this._project = validOptions.project;
204
225
  /**
205
226
  * May throw! Assign key of the first key-value pair to
206
227
  * {@link resolvedEnvVariable}
207
228
  */
208
- const tokenVars = _GetTokenEnvVariables(validOpts.tokenEnvVars);
209
- if (tokenVars)
210
- this._resolvedEnvVariable = tokenVars[0][0];
211
- this._source = validOpts.source;
229
+ const tokenVariables = _GetTokenEnvironmentVariables(validOptions.tokenEnvVars);
230
+ if (tokenVariables)
231
+ this._resolvedEnvVariable = tokenVariables[0][0];
232
+ this._source = validOptions.source;
212
233
  }
213
234
 
214
235
  public get project(): MSBuildProject {
@@ -237,15 +258,17 @@ export class NugetRegistryInfo {
237
258
  tokenValue = NRI._GetTokenValue(this.resolvedEnvVariable);
238
259
 
239
260
  if (tokenValue?.startsWith('github_pat_')) {
240
- const errMsg = `The value of the token in 'resolvedEnvVariable' ${String(this.resolvedEnvVariable)} begins with 'github_pat_', indicating it's a Fine-Grained token. At the time of writing, GitHub Fine-Grained tokens cannot push packages. If you believe this is statement is outdated, report the issue at https://github.com/halospv3/hce.shared/issues/new. For more information, see https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry.`;
241
- const err = new Error(errMsg);
242
- return this._canPushPackagesToSource = Promise.reject(err);
261
+ const errorMessage = `The value of the token in 'resolvedEnvVariable' ${String(this.resolvedEnvVariable)} begins with 'github_pat_', indicating it's a Fine-Grained token. At the time of writing, GitHub Fine-Grained tokens cannot push packages. If you believe this is statement is outdated, report the issue at https://github.com/halospv3/hce.shared/issues/new. For more information, see https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-nuget-registry.`;
262
+ const error = new Error(errorMessage);
263
+ return this._canPushPackagesToSource = Promise.reject(error);
243
264
  }
244
265
 
245
266
  return this._canPushPackagesToSource = this.PackDummyPackage({})
267
+ // eslint-disable-next-line unicorn/prefer-await
246
268
  .then(async () => await this._PushDummyPackages({
247
269
  apiKey: tokenValue,
248
270
  }))
271
+ // eslint-disable-next-line unicorn/prefer-await
249
272
  .then<true>((execAsyncReturn) => {
250
273
  ok(execAsyncReturn);
251
274
  return true as const;
@@ -265,27 +288,6 @@ export class NugetRegistryInfo {
265
288
  return this._source;
266
289
  }
267
290
 
268
- /**
269
- * Get the API token from {@link NugetRegistryInfo#resolvedEnvVariable}
270
- * @param resolvedEnvVariable The name of the environment variable(s) whose
271
- * value is a NuGet API key. Typically, the value of
272
- * {@link NugetRegistryInfo#resolvedEnvVariable}.
273
- * @returns The value of the first defined environment variable.
274
- * @throws {Error} when none of the provided environment variables are defined.
275
- */
276
- private static _GetTokenValue(resolvedEnvVariable: string): string {
277
- type.string.assert(resolvedEnvVariable);
278
-
279
- const tokenValue = getEnvVarValue(resolvedEnvVariable);
280
- if (tokenValue === undefined) {
281
- throw new Error(`\
282
- The environment variable ${resolvedEnvVariable} was specified \
283
- as the source of the token to push a NuGet package, \
284
- but the environment variable is empty or undefined.`);
285
- }
286
- return tokenValue;
287
- }
288
-
289
291
  // #region Pack
290
292
 
291
293
  /**
@@ -294,6 +296,7 @@ but the environment variable is empty or undefined.`);
294
296
  * {@link NRI.PackPackagesOptionsType.t.propertyOverrides `propertyOverrides`}
295
297
  * is a wrapper for MSBuild's `-property:<n>=<v>` properties override arg.
296
298
  */
299
+ // eslint-disable-next-line unicorn/consistent-class-member-order
297
300
  static readonly PackPackagesOptionsType: Type<{
298
301
  propertyOverrides?: Record<string, string> | undefined;
299
302
  artifactsPath?: string | undefined;
@@ -373,80 +376,80 @@ but the environment variable is empty or undefined.`);
373
376
  * When pushing the package(s), you only need to supply the main .nupkg's path
374
377
  * or its directory to the dotnet CLI—by default, it will also push the
375
378
  * symbols package, if present.
376
- * @param opts Options passed to
379
+ * @param options Options passed to
377
380
  * `dotnet pack`, excluding the required `<PROJECT | SOLUTION>` argument. The
378
381
  * {@link PackPackagesOptionsType.t.output} path is modified according to the
379
- * {@link usePerSourceSubfolder} and {@link usePerPackageIdSubfolder}
382
+ * {@link shouldUsePerSourceSubfolder} and {@link shouldUsePerPackageIdSubfolder}
380
383
  * arguments.
381
- * @param usePerSourceSubfolder If true, the path of the package output will
384
+ * @param shouldUsePerSourceSubfolder If true, the path of the package output will
382
385
  * include a subfolder named after the NuGet Source.
383
- * @param usePerPackageIdSubfolder If true, the path of the package output
386
+ * @param shouldUsePerPackageIdSubfolder If true, the path of the package output
384
387
  * will include a subfolder named after the NuGet package's ID.
385
388
  * @returns `dotnet pack "${this.project.Properties.MSBuildProjectFullPath}"
386
389
  * -o "${outDir}"` where outDir may be `${cwd()}/publish/${NugetRegistryInfo.GetNameForURL(this.source)}/${this._project.Properties.PackageId}`
387
390
  */
388
391
  GetPackCommand(
389
- opts: typeof NRI.PackPackagesOptionsType.inferIn,
390
- usePerSourceSubfolder = false,
391
- usePerPackageIdSubfolder = false,
392
+ options: typeof NRI.PackPackagesOptionsType.inferIn,
393
+ shouldUsePerSourceSubfolder = false,
394
+ shouldUsePerPackageIdSubfolder = false,
392
395
  ): string {
393
- const validOpts = NRI.PackPackagesOptionsType.from(opts);
394
- type.boolean.assert(usePerSourceSubfolder);
395
- type.boolean.assert(usePerPackageIdSubfolder);
396
+ const validOptions = NRI.PackPackagesOptionsType.from(options);
397
+ type.boolean.assert(shouldUsePerSourceSubfolder);
398
+ type.boolean.assert(shouldUsePerPackageIdSubfolder);
396
399
 
397
- validOpts.output ??= node_path.join(cwd(), 'publish');
398
- if (usePerSourceSubfolder)
399
- validOpts.output = node_path.join(validOpts.output, NugetRegistryInfo.GetDirNameForSource(this.source), node_path.sep);
400
- if (usePerPackageIdSubfolder)
401
- validOpts.output = node_path.join(validOpts.output, this._project.Properties.PackageId, node_path.sep);
400
+ validOptions.output ??= node_path.join(cwd(), 'publish');
401
+ if (shouldUsePerSourceSubfolder)
402
+ validOptions.output = node_path.join(validOptions.output, NugetRegistryInfo.GetDirNameForSource(this.source), node_path.sep);
403
+ if (shouldUsePerPackageIdSubfolder)
404
+ validOptions.output = node_path.join(validOptions.output, this._project.Properties.PackageId, node_path.sep);
402
405
 
403
- const packCmdArr: string[] = [
406
+ const packCommandArray: string[] = [
404
407
  'dotnet',
405
408
  'pack',
406
409
  `"${this._project.Properties.MSBuildProjectFullPath}"`,
407
410
  ];
408
- if (validOpts.artifactsPath !== undefined)
409
- packCmdArr.push('--artifactsPath', `"${validOpts.artifactsPath}"`);
410
- if (validOpts.configuration !== undefined)
411
- packCmdArr.push('--configuration', validOpts.configuration);
412
- if (validOpts.disableBuildServers === true)
413
- packCmdArr.push('--disable-build-servers');
414
- if (validOpts.force === true) packCmdArr.push('--force');
415
- if (validOpts.includeSource === true) packCmdArr.push('--include-source');
416
- if (validOpts.includeSymbols === true) packCmdArr.push('--include-symbols');
417
- if (validOpts.interactive === true) packCmdArr.push('--interactive');
418
- if (validOpts.noBuild === true) packCmdArr.push('--no-build');
419
- if (validOpts.noLogo === true) packCmdArr.push('--nologo');
420
- if (validOpts.noRestore === true) packCmdArr.push('--no-restore');
421
- if (validOpts.runtime !== undefined)
422
- packCmdArr.push('--runtime', validOpts.runtime);
423
- if (validOpts.serviceable === true) packCmdArr.push('--serviceable');
424
- if (validOpts.terminalLogger !== undefined)
425
- packCmdArr.push('--tl', validOpts.terminalLogger);
426
- if (validOpts.useCurrentRuntime === true)
427
- packCmdArr.push('--use-current-runtime');
428
- if (validOpts.verbosity !== undefined)
429
- packCmdArr.push('--verbosity', validOpts.verbosity);
430
- if (validOpts.versionSuffix !== undefined)
431
- packCmdArr.push('--version-suffix', validOpts.versionSuffix);
411
+ if (validOptions.artifactsPath !== undefined)
412
+ packCommandArray.push('--artifactsPath', `"${validOptions.artifactsPath}"`);
413
+ if (validOptions.configuration !== undefined)
414
+ packCommandArray.push('--configuration', validOptions.configuration);
415
+ if (validOptions.disableBuildServers === true)
416
+ packCommandArray.push('--disable-build-servers');
417
+ if (validOptions.force === true) packCommandArray.push('--force');
418
+ if (validOptions.includeSource === true) packCommandArray.push('--include-source');
419
+ if (validOptions.includeSymbols === true) packCommandArray.push('--include-symbols');
420
+ if (validOptions.interactive === true) packCommandArray.push('--interactive');
421
+ if (validOptions.noBuild === true) packCommandArray.push('--no-build');
422
+ if (validOptions.noLogo === true) packCommandArray.push('--nologo');
423
+ if (validOptions.noRestore === true) packCommandArray.push('--no-restore');
424
+ if (validOptions.runtime !== undefined)
425
+ packCommandArray.push('--runtime', validOptions.runtime);
426
+ if (validOptions.serviceable === true) packCommandArray.push('--serviceable');
427
+ if (validOptions.terminalLogger !== undefined)
428
+ packCommandArray.push('--tl', validOptions.terminalLogger);
429
+ if (validOptions.useCurrentRuntime === true)
430
+ packCommandArray.push('--use-current-runtime');
431
+ if (validOptions.verbosity !== undefined)
432
+ packCommandArray.push('--verbosity', validOptions.verbosity);
433
+ if (validOptions.versionSuffix !== undefined)
434
+ packCommandArray.push('--version-suffix', validOptions.versionSuffix);
432
435
  /**
433
436
  * Haphazard. I need to override the Version and I'm not considering side
434
437
  * effects of arbitrary overrides.
435
438
  */
436
- if (validOpts.propertyOverrides) {
439
+ if (validOptions.propertyOverrides) {
437
440
  /** convert propertyOverrides record to "-p:n0=v0;n1=v1;n2=v2" et cetera */
438
- const assignments: string = '-p:' + Object.entries(validOpts.propertyOverrides)
441
+ const assignments: string = '-p:' + Object.entries(validOptions.propertyOverrides)
439
442
  .map(v => `${v[0]}=${v[1]}`).join(';');
440
- packCmdArr.push(`"${assignments}"`);
443
+ packCommandArray.push(`"${assignments}"`);
441
444
  }
442
- if (validOpts['-GetItem'] && validOpts['-GetItem'].length > 0) {
445
+ if (validOptions['-GetItem'] && validOptions['-GetItem'].length > 0) {
443
446
  // -GetItem:_OutputPackItems,MyCustomItem
444
- packCmdArr.push(`-GetItem:${validOpts['-GetItem'].join(',')}`);
447
+ packCommandArray.push(`-GetItem:${validOptions['-GetItem'].join(',')}`);
445
448
  }
446
449
  // MSBuild parses everything after -o as the path.
447
- packCmdArr.push('-o', `"${validOpts.output}"`);
450
+ packCommandArray.push('-o', `"${validOptions.output}"`);
448
451
 
449
- return packCmdArr.join(' ');
452
+ return packCommandArray.join(' ');
450
453
  }
451
454
 
452
455
  /**
@@ -459,39 +462,42 @@ but the environment variable is empty or undefined.`);
459
462
  * NuGet packages should be created during the `prepare` step, but complex
460
463
  * configuration of `dotnet pack` via command lines intended to be invoked by
461
464
  * `@semantic-release/exec` is impractical.
462
- * @param opts `dotnet pack` options. See `dotnet pack -h`,
465
+ * @param options `dotnet pack` options. See `dotnet pack -h`,
463
466
  * https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-pack, and
464
467
  * {@link PackPackagesOptionsType}.
465
- * {@link opts['-GetItem']} will _always_ have '_OutputPackItems'.
466
- * @param [usePerSourceSubfolder] If `true`, modify the output path to
468
+ * {@link options['-GetItem']} will _always_ have '_OutputPackItems'.
469
+ * @param [shouldUsePerSourceSubfolder] If `true`, modify the output path to
467
470
  * include a subfolder bearing a path-safe encoding of the NuGet Source that
468
471
  * will receive the nupkg.
469
- * @param [usePerPackageIdSubfolder] If `true`, modify the output path
472
+ * @param [shouldUsePerPackageIdSubfolder] If `true`, modify the output path
470
473
  * to include a subfolder named after the the PackageId.
471
474
  * @returns a string[] containing the full file paths of all new packages i.e.
472
475
  * .nupkg, .symbols.nupkg, .snupkg
473
476
  */
474
477
  // @ts-expect-error Todo: publicize to dismiss this "unused" error.
475
478
  private async _PackPackages(
476
- opts: typeof NRI.PackPackagesOptionsType.inferIn,
477
- usePerSourceSubfolder = false,
478
- usePerPackageIdSubfolder = false,
479
+ options: typeof NRI.PackPackagesOptionsType.inferIn,
480
+ shouldUsePerSourceSubfolder = false,
481
+ shouldUsePerPackageIdSubfolder = false,
479
482
  ): Promise<string[]> {
480
- opts['-GetItem'] = [...opts['-GetItem'] ?? [], key_OutputPackItems];
483
+ options['-GetItem'] = [...options['-GetItem'] ?? [], key_OutputPackItems];
481
484
 
482
- const packCmd = this.GetPackCommand(
483
- opts,
484
- usePerSourceSubfolder,
485
- usePerPackageIdSubfolder,
485
+ const packCommand = this.GetPackCommand(
486
+ options,
487
+ shouldUsePerSourceSubfolder,
488
+ shouldUsePerPackageIdSubfolder,
486
489
  );
487
- let packOutput: undefined | { stdout: string; stderr: string } = undefined;
490
+ let packOutput: undefined | { stdout: string; stderr: string };
488
491
  while (packOutput === undefined) {
489
- packOutput = await setTimeout(
490
- 1000,
491
- execAsync(packCmd, true),
492
- )
493
- .then(async p => await p)
494
- .catch<undefined>(catchEBUSY);
492
+ try {
493
+ packOutput = await setTimeout(
494
+ 1000,
495
+ execAsync(packCommand, true),
496
+ );
497
+ }
498
+ catch (error: unknown) {
499
+ catchEBUSY(error);
500
+ }
495
501
  }
496
502
  // may include .snupkg
497
503
  const nupkgFullPaths: string[] | undefined = new MSBuildEvaluationOutput(packOutput.stdout)
@@ -505,7 +511,7 @@ but the environment variable is empty or undefined.`);
505
511
  /**
506
512
  * Create a dummy package for the current {@link project} by executing a
507
513
  * command line like \``dotnet pack ${this.project.Properties.MSBuildProjectFullPath} -p:Version=0.0.1-DUMMY -output ${getDummiesDir(this._project)}/${GetNameForURL(this.source)}`\`
508
- * @param opts Options passed to
514
+ * @param options Options passed to
509
515
  * `dotnet pack`, excluding the required `<PROJECT | SOLUTION>` argument.
510
516
  * - The `output` field is ignored and overwritten. It is replaced with
511
517
  * ${{@link getDummiesDir}({@link project})}/${{@link GetDirNameForSource}({@link source})}
@@ -517,26 +523,42 @@ but the environment variable is empty or undefined.`);
517
523
  * If mixed with other nupkgs, filter for the {@link NugetProjectProperties#PackageId}
518
524
  */
519
525
  public async PackDummyPackage(
520
- opts: typeof NRI.PackDummyPackagesOptionsType.inferIn,
526
+ options: typeof NRI.PackDummyPackagesOptionsType.inferIn,
521
527
  ): Promise<string[]> {
522
- const packCmd: string = this.GetPackCommand(
528
+ const packCommand: string = this.GetPackCommand(
523
529
  {
524
- ...opts,
525
- output: getDummiesDir(this._project),
526
- propertyOverrides: { ...opts.propertyOverrides, Version: '0.0.1-DUMMY', UpdateVersionProperties: 'false' },
527
- '-GetItem': [...opts['-GetItem'] ?? [], key_OutputPackItems],
530
+ ...options,
531
+ output: getDummiesDirectory(this._project),
532
+ propertyOverrides: { ...options.propertyOverrides, Version: '0.0.1-DUMMY', UpdateVersionProperties: 'false' },
533
+ '-GetItem': [...options['-GetItem'] ?? [], key_OutputPackItems],
528
534
  },
529
535
  true,
530
536
  );
531
537
 
532
- let packOutput: undefined | { stdout: string; stderr: string } = undefined;
538
+ let packOutput: undefined | { stdout: string; stderr: string };
539
+ let delay = 0;
533
540
  while (packOutput === undefined) {
534
- packOutput = await setTimeout(
535
- 1000,
536
- execAsync(packCmd, true),
537
- )
538
- .then(async p => await p)
539
- .catch<undefined>(catchEBUSY);
541
+ try {
542
+ packOutput = await setTimeout(
543
+ delay,
544
+ execAsync(packCommand, true),
545
+ );
546
+ }
547
+ catch (error: unknown) {
548
+ if (delay <= 10_000 /* milliseconds */) {
549
+ catchEBUSY(error);
550
+ }
551
+ else {
552
+ throw new Error(
553
+ 'Unable to pack dummy package; (10/10) Maximum retries reached.',
554
+ { cause: error });
555
+ }
556
+ // If the delay is pushed back to 10 seconds, then...
557
+ // A) A project's intermediate output (`obj/**`) is in use by a build system or language server
558
+ // B) something horrible has happened
559
+ }
560
+ // back-off
561
+ delay += 1000;
540
562
  }
541
563
  // may include .snupkg
542
564
  const nupkgFullPaths: string[] | undefined = new MSBuildEvaluationOutput(packOutput.stdout)
@@ -633,11 +655,11 @@ but the environment variable is empty or undefined.`);
633
655
  /**
634
656
  * Create a `dotnet nuget push` command line from the given options and
635
657
  * optional boolean parameters.
636
- * @param opts See {@link PushPackagesOptionsType}
637
- * @param usePerSourceSubfolder If `true`, the NuGet Source name or URL is formatted
658
+ * @param options See {@link PushPackagesOptionsType}
659
+ * @param shouldUsePerSourceSubfolder If `true`, the NuGet Source name or URL is formatted
638
660
  * to a folder name and appended to the ROOT as a subfolder. Do not use
639
661
  * wildcards in ROOT with this set to `true`!
640
- * @param usePerPackageIdSubfolder If `true`, the
662
+ * @param shouldUsePerPackageIdSubfolder If `true`, the
641
663
  * {@link project}'s {@link NugetProjectProperties#PackageId}
642
664
  * is appended to the ROOT as a subfolder. Do not use wildcards in
643
665
  * ROOT with this set to `true`!
@@ -645,96 +667,108 @@ but the environment variable is empty or undefined.`);
645
667
  * appropriate arguments.
646
668
  */
647
669
  GetPushCommand(
648
- opts: typeof NRI.PushPackagesOptionsType.inferIn,
649
- usePerSourceSubfolder = false,
650
- usePerPackageIdSubfolder = false,
670
+ options: typeof NRI.PushPackagesOptionsType.inferIn,
671
+ shouldUsePerSourceSubfolder = false,
672
+ shouldUsePerPackageIdSubfolder = false,
651
673
  ): string {
652
- const validOpts = NRI.PushPackagesOptionsType.from(opts);
653
- type.boolean.assert(usePerSourceSubfolder);
654
- type.boolean.assert(usePerPackageIdSubfolder);
674
+ const validOptions = NRI.PushPackagesOptionsType.from(options);
675
+ type.boolean.assert(shouldUsePerSourceSubfolder);
676
+ type.boolean.assert(shouldUsePerPackageIdSubfolder);
655
677
 
656
- validOpts.root = validOpts.root === '' ? `${cwd()}/publish` : validOpts.root;
657
- if (usePerSourceSubfolder)
658
- validOpts.root = node_path.join(validOpts.root, NugetRegistryInfo.GetDirNameForSource(this.source), node_path.sep);
659
- if (usePerPackageIdSubfolder)
660
- validOpts.root = node_path.join(validOpts.root, this._project.Properties.PackageId, node_path.sep);
678
+ validOptions.root = validOptions.root === '' ? `${cwd()}/publish` : validOptions.root;
679
+ if (shouldUsePerSourceSubfolder)
680
+ validOptions.root = node_path.join(validOptions.root, NugetRegistryInfo.GetDirNameForSource(this.source), node_path.sep);
681
+ if (shouldUsePerPackageIdSubfolder)
682
+ validOptions.root = node_path.join(validOptions.root, this._project.Properties.PackageId, node_path.sep);
661
683
 
662
- const packCmdArr: string[] = [
684
+ const packCommandArray: string[] = [
663
685
  'dotnet',
664
686
  'nuget',
665
687
  'push',
666
- `"${node_path.join(validOpts.root, '*.nupkg')}"`,
688
+ `"${node_path.join(validOptions.root, '*.nupkg')}"`,
667
689
  ];
668
690
 
669
691
  if (this.resolvedEnvVariable)
670
- validOpts.apiKey ??= NRI._GetTokenValue(this.resolvedEnvVariable);
692
+ validOptions.apiKey ??= NRI._GetTokenValue(this.resolvedEnvVariable);
671
693
  /**
672
694
  * If apiKey is an empty string, defer to the dotnet CLI's NuGet client
673
695
  * ability to lookup API keys saved via `dotnet nuget add source` or NuGet config
674
696
  * files.
675
697
  */
676
- if (validOpts.apiKey && validOpts.apiKey !== '')
677
- packCmdArr.push('--api-key', validOpts.apiKey);
678
- if (validOpts.configFile)
679
- packCmdArr.push('--configfile', validOpts.configFile);
680
- if (validOpts.disableBuffering === true)
681
- packCmdArr.push('--disable-buffering');
682
- if (validOpts.forceEnglishOutput === true)
683
- packCmdArr.push('--force-english-output');
684
- if (validOpts.interactive === true)
685
- packCmdArr.push('--interactive');
686
- if (validOpts.noServiceEndpoint === true)
687
- packCmdArr.push('--no-service-endpoint');
688
- if (validOpts.noSymbols === true)
689
- packCmdArr.push('--no-symbols');
690
- if (validOpts.skipDuplicate === true)
691
- packCmdArr.push('--skip-duplicate');
692
- validOpts.source ??= this.source;
693
- packCmdArr.push('--source', validOpts.source);
694
- if (validOpts.symbolApiKey !== undefined)
695
- packCmdArr.push('--symbol-api-key', validOpts.symbolApiKey);
696
- if (validOpts.symbolSource !== undefined)
697
- packCmdArr.push('--symbol-source', validOpts.symbolSource);
698
- if (validOpts.timeout !== undefined)
699
- packCmdArr.push('--timeout', validOpts.timeout.toString());
698
+ if (validOptions.apiKey && validOptions.apiKey !== '')
699
+ packCommandArray.push('--api-key', validOptions.apiKey);
700
+ if (validOptions.configFile)
701
+ packCommandArray.push('--configfile', validOptions.configFile);
702
+ if (validOptions.disableBuffering === true)
703
+ packCommandArray.push('--disable-buffering');
704
+ if (validOptions.forceEnglishOutput === true)
705
+ packCommandArray.push('--force-english-output');
706
+ if (validOptions.interactive === true)
707
+ packCommandArray.push('--interactive');
708
+ if (validOptions.noServiceEndpoint === true)
709
+ packCommandArray.push('--no-service-endpoint');
710
+ if (validOptions.noSymbols === true)
711
+ packCommandArray.push('--no-symbols');
712
+ if (validOptions.skipDuplicate === true)
713
+ packCommandArray.push('--skip-duplicate');
714
+ validOptions.source ??= this.source;
715
+ packCommandArray.push('--source', validOptions.source);
716
+ if (validOptions.symbolApiKey !== undefined)
717
+ packCommandArray.push('--symbol-api-key', validOptions.symbolApiKey);
718
+ if (validOptions.symbolSource !== undefined)
719
+ packCommandArray.push('--symbol-source', validOptions.symbolSource);
720
+ if (validOptions.timeout !== undefined)
721
+ packCommandArray.push('--timeout', validOptions.timeout.toString());
700
722
 
701
- return packCmdArr.join(' ');
723
+ return packCommandArray.join(' ');
702
724
  }
703
725
 
704
726
  /**
705
727
  * Immediately push packages. The input path may be modified according to the
706
- * {@link usePerSourceSubfolder} and {@link usePerPackageIdSubfolder}
728
+ * {@link shouldUsePerSourceSubfolder} and {@link shouldUsePerPackageIdSubfolder}
707
729
  * arguments.
708
- * @param opts The `dotnet nuget push` command line options, including the
730
+ * @param options The `dotnet nuget push` command line options, including the
709
731
  * ROOT argument, the directory containing local nuget packages ready to be
710
732
  * pushed.
711
- * @param usePerSourceSubfolder If `true`, the NuGet Source name or URL is formatted
733
+ * @param shouldUsePerSourceSubfolder If `true`, the NuGet Source name or URL is formatted
712
734
  * to a folder name and appended to the ROOT as a subfolder. Do not use
713
735
  * wildcards in ROOT with this set to `true`!
714
- * @param usePerPackageIdSubfolder If `true`, the current {@link project}'s
736
+ * @param shouldUsePerPackageIdSubfolder If `true`, the current {@link project}'s
715
737
  * PackageId is appended to the ROOT as a subfolder. Do not use wildcards in
716
738
  * ROOT with this set to `true`!
717
739
  */
718
740
  // @ts-expect-error Todo: publicize to dismiss this "unused" error.
719
741
  private async _PushPackages(
720
- opts: typeof NRI.PushPackagesOptionsType.inferIn,
721
- usePerSourceSubfolder = false,
722
- usePerPackageIdSubfolder = false,
742
+ options: typeof NRI.PushPackagesOptionsType.inferIn,
743
+ shouldUsePerSourceSubfolder = false,
744
+ shouldUsePerPackageIdSubfolder = false,
723
745
  ) {
724
- // const pushOutput =
725
- await execAsync(
726
- this.GetPushCommand(
727
- opts,
728
- usePerSourceSubfolder,
729
- usePerPackageIdSubfolder,
730
- ),
731
- true,
732
- ).catch((error: unknown) => {
733
- const _error: Error = isError(error) ? error : new Error(JSON.stringify(error));
734
- throw opts.apiKey
735
- ? _censorTokenInError(_error, opts.apiKey)
746
+ let command = '';
747
+ try {
748
+ await execAsync(
749
+ command = this.GetPushCommand(
750
+ options,
751
+ shouldUsePerSourceSubfolder,
752
+ shouldUsePerPackageIdSubfolder,
753
+ ),
754
+ true,
755
+ );
756
+ }
757
+ catch (error: unknown) {
758
+ const _error: ExecException = Object.assign(
759
+ isError(error)
760
+ ? error
761
+ : new Error(JSON.stringify(error)),
762
+ { cmd: command },
763
+ );
764
+
765
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
766
+ throw options.apiKey
767
+ ? _censorTokenInError(_error, options.apiKey)
736
768
  : _error;
737
- });
769
+ };
770
+
771
+ // const pushOutput =.catch((error: unknown) => {
738
772
  }
739
773
 
740
774
  /**
@@ -756,7 +790,7 @@ but the environment variable is empty or undefined.`);
756
790
  * nri.GetPushDummyPackageCommand(pushOpts, false, false),
757
791
  * ].join(' && ')
758
792
  * ```
759
- * @param opts options for `dotnet nuget push`. The following
793
+ * @param options options for `dotnet nuget push`. The following
760
794
  * fields are overwritten:
761
795
  * - root: getDummiesDir(this.project)
762
796
  * - skipDuplicates: true
@@ -764,12 +798,12 @@ but the environment variable is empty or undefined.`);
764
798
  * (created by executing {@link PackDummyPackage}) to {@link source}
765
799
  */
766
800
  GetPushDummyCommand(
767
- opts: typeof NRI.PushDummyPackagesOptionsType.inferIn,
801
+ options: typeof NRI.PushDummyPackagesOptionsType.inferIn,
768
802
  ): string {
769
803
  return this.GetPushCommand(
770
804
  {
771
- ...NRI.PushDummyPackagesOptionsType.from(opts),
772
- root: getDummiesDir(this._project),
805
+ ...NRI.PushDummyPackagesOptionsType.from(options),
806
+ root: getDummiesDirectory(this._project),
773
807
  },
774
808
  true,
775
809
  );
@@ -780,23 +814,32 @@ but the environment variable is empty or undefined.`);
780
814
  * @throws {Error} when the process exits with an error code indicating
781
815
  * failure i.e. the command line is invalid, the process fails to start,
782
816
  * the push fails, et cetera.
783
- * @param opts the ROOT arg and options for `dotnet nuget push`. The following
817
+ * @param options the ROOT arg and options for `dotnet nuget push`. The following
784
818
  * fields are overwritten:
785
819
  * - root: getDummiesDir(this.project)
786
820
  * - skipDuplicates: true
787
821
  * @returns The return type of {@link execAsync} i.e. a {@link Promise} resolving to `{ stdout: string; stderr: string }`.
788
822
  */
789
823
  private async _PushDummyPackages(
790
- opts: typeof NRI.PushDummyPackagesOptionsType.inferIn,
824
+ options: typeof NRI.PushDummyPackagesOptionsType.inferIn,
791
825
  ): ReturnType<typeof execAsync> {
792
- const pushCmd: string = this.GetPushDummyCommand(opts);
793
- return await execAsync(pushCmd, true)
794
- .catch((error: unknown) => {
795
- const _error: Error = isError(error) ? error : new Error(String(error));
796
- throw opts.apiKey
797
- ? _censorTokenInError(_error, opts.apiKey)
798
- : _error;
799
- });
826
+ const pushCommand: string = this.GetPushDummyCommand(options);
827
+ try {
828
+ return await execAsync(pushCommand, true);
829
+ }
830
+ catch (error: unknown) {
831
+ const _error: ExecException = Object.assign(
832
+ isError(error)
833
+ ? error
834
+ : new Error(JSON.stringify(error)),
835
+ { cmd: pushCommand },
836
+ );
837
+
838
+ // eslint-disable-next-line @typescript-eslint/only-throw-error
839
+ throw options.apiKey
840
+ ? _censorTokenInError(_error, options.apiKey)
841
+ : _error;
842
+ }
800
843
  }
801
844
 
802
845
  // #endregion Push
@@ -849,19 +892,17 @@ but the environment variable is empty or undefined.`);
849
892
  ): Promise<boolean> {
850
893
  if (nextVersion === '')
851
894
  throw new Error('The value of nextVersion is empty');
852
- return await execAsync(
895
+ const stdPair = await execAsync(
853
896
  `dotnet package search --format JSON --exact-match --source ${source} --prerelease ${packageId}`,
854
897
  true,
855
- )
856
- .then(stdPair => stdPair.stdout)
857
- .then(json => this._ParseNugetSearchReturn(json))
858
- .then(errsOrObj => errsOrObj instanceof type.errors ? errsOrObj.throw() : errsOrObj)
859
- .then(obj => obj.searchResult)
860
- .then(results => results[0].packages)
861
- .then(pkgs =>
862
- pkgs.find(p => p.version === type('string.semver').from(nextVersion)),
863
- )
864
- .then(pkg => pkg !== undefined);
898
+ );
899
+ const json = stdPair.stdout;
900
+ const errsOrObject = this._ParseNugetSearchReturn(json);
901
+ const _object = errsOrObject instanceof type.errors ? errsOrObject.throw() : errsOrObject;
902
+ const results = _object.searchResult;
903
+ const packages = results[0].packages;
904
+ const package_ = packages.find(p => p.version === type('string.semver').from(nextVersion));
905
+ return package_ !== undefined;
865
906
  }
866
907
 
867
908
  /**
@@ -906,6 +947,7 @@ const NRI: typeof NugetRegistryInfo = NugetRegistryInfo;
906
947
  * The base type for {@link NRIOpts} and related types. Extend this type while
907
948
  * overriding member types via {@link NRIOptsBase.merge}
908
949
  */
950
+ // eslint-disable-next-line unicorn/name-replacements
909
951
  export const NRIOptsBase: Type<{
910
952
  project: MSBuildProject | {
911
953
  readonly Items: Readonly<Required<MSBuildEvaluationOutput>['Items']>;
@@ -960,6 +1002,7 @@ export const NRIOptsBase: Type<{
960
1002
  /**
961
1003
  * The type of the parameter for {@link NugetRegistryInfo}'s constructor.
962
1004
  */
1005
+ // eslint-disable-next-line unicorn/name-replacements
963
1006
  export const NRIOpts: Type<{
964
1007
  project: MSBuildProject | {
965
1008
  readonly Items: Readonly<Required<MSBuildEvaluationOutput>['Items']>;
@@ -1007,15 +1050,16 @@ function _censorToken(string: string, token: string): string {
1007
1050
  * NuGet API token.
1008
1051
  */
1009
1052
  function _censorTokenInError(error: ExecException, token: string): ExecException {
1053
+ const text = JSON.stringify({
1054
+ ...error,
1055
+ message: error.message,
1056
+ stack: error.stack,
1057
+ });
1010
1058
  return Object.assign(
1011
1059
  error,
1012
1060
  JSON.parse(
1013
1061
  _censorToken(
1014
- JSON.stringify({
1015
- ...error,
1016
- message: error.message,
1017
- stack: error.stack,
1018
- }),
1062
+ text,
1019
1063
  token,
1020
1064
  ),
1021
1065
  ) as ExecException,