setup-php 2.36.0 → 2.37.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/src/tools.ts CHANGED
@@ -5,14 +5,94 @@ import * as fetch from './fetch';
5
5
  import * as packagist from './packagist';
6
6
  import * as utils from './utils';
7
7
 
8
- type RS = Record<string, string>;
9
- type RSRS = Record<string, RS>;
8
+ /**
9
+ * Valid function names for custom tool handlers
10
+ */
11
+ type ToolFunction =
12
+ | 'castor'
13
+ | 'composer'
14
+ | 'deployer'
15
+ | 'dev_tools'
16
+ | 'phive'
17
+ | 'blackfire_player'
18
+ | 'pecl'
19
+ | 'phing'
20
+ | 'phpunit'
21
+ | 'phpcpd'
22
+ | 'wp_cli';
23
+
24
+ /**
25
+ * Tool data interface containing all properties for tool installation
26
+ */
27
+ export interface ToolData {
28
+ tool: string;
29
+ version: string;
30
+ os: string;
31
+ php_version: string;
32
+ github: string;
33
+ domain: string;
34
+ extension: string;
35
+ repository: string;
36
+ prefix: string;
37
+ verb: string;
38
+ fetch_latest: 'true' | 'false';
39
+ scope: string;
40
+ version_parameter: string;
41
+ version_prefix: string;
42
+ release: string;
43
+ packagist: string;
44
+ type?: string;
45
+ function?: ToolFunction;
46
+ alias?: string;
47
+ url: string;
48
+ uri?: string;
49
+ error?: string;
50
+ }
51
+
52
+ /**
53
+ * Input type for functions that may receive partial/unresolved tool data
54
+ * Used by getUrl, getLatestVersion etc. before version is fully resolved
55
+ */
56
+ export type ToolInput = Omit<ToolData, 'version' | 'url'> & {version?: string};
57
+
58
+ /**
59
+ * Partial tool data from tools.json configuration
60
+ */
61
+ interface ToolConfig {
62
+ tool?: string;
63
+ repository?: string;
64
+ type?: string;
65
+ function?: ToolFunction;
66
+ alias?: string;
67
+ domain?: string;
68
+ extension?: string;
69
+ fetch_latest?: 'true' | 'false';
70
+ scope?: string;
71
+ version_parameter?: string;
72
+ version_prefix?: string;
73
+ packagist?: string;
74
+ }
10
75
 
11
- interface IRef {
76
+ /**
77
+ * GitHub reference object from API response
78
+ */
79
+ interface GitHubRef {
12
80
  ref: string;
13
81
  node_id: string;
14
82
  url: string;
15
- object: RS;
83
+ object: {
84
+ sha: string;
85
+ type: string;
86
+ url: string;
87
+ };
88
+ }
89
+
90
+ /**
91
+ * Deployer manifest entry
92
+ */
93
+ interface DeployerManifestEntry {
94
+ version: string;
95
+ url: string;
16
96
  }
17
97
 
18
98
  /**
@@ -20,7 +100,7 @@ interface IRef {
20
100
  *
21
101
  * @param data
22
102
  */
23
- export async function getSemverVersion(data: RS): Promise<string> {
103
+ export async function getSemverVersion(data: ToolData): Promise<string> {
24
104
  const fixSemver = (t: string): string => {
25
105
  if (/^\d+\.\d+\.\d+(-|$)/.test(t)) return t;
26
106
  const m = t.match(/^(\d+\.\d+\.\d+)([A-Za-z]+[0-9A-Za-z.]+)$/);
@@ -31,14 +111,16 @@ export async function getSemverVersion(data: RS): Promise<string> {
31
111
  const github_token: string =
32
112
  (await utils.readEnv('GITHUB_TOKEN')) ||
33
113
  (await utils.readEnv('COMPOSER_TOKEN'));
34
- const response: RS = await fetch.fetch(url, github_token);
114
+ const response = await fetch.fetch(url, github_token);
35
115
  if (response.error || response.data === '[]') {
36
- data['error'] = response.error ?? `No version found with prefix ${search}.`;
37
- return data['version'];
116
+ data.error = response.error ?? `No version found with prefix ${search}.`;
117
+ return data.version;
38
118
  } else {
39
- const refs: IRef[] = JSON.parse(response['data']);
119
+ const refs: GitHubRef[] = JSON.parse(response.data);
40
120
  const tags = refs
41
- .map((i: IRef) => (i.ref?.split('/').pop() ?? '').replace(/^v(?=\d)/, ''))
121
+ .map((i: GitHubRef) =>
122
+ (i.ref?.split('/').pop() ?? '').replace(/^v(?=\d)/, '')
123
+ )
42
124
  .filter((t: string) => t.length > 0);
43
125
  const fixedToOriginal = new Map<string, string>();
44
126
  const fixed = tags.map(t => {
@@ -46,14 +128,14 @@ export async function getSemverVersion(data: RS): Promise<string> {
46
128
  fixedToOriginal.set(f, t);
47
129
  return f;
48
130
  });
49
- fixed.sort((a, b) => {
131
+ const sorted = fixed.toSorted((a, b) => {
50
132
  try {
51
133
  return cv.compareVersions(b, a);
52
134
  } catch {
53
135
  return b.localeCompare(a, 'en', {numeric: true, sensitivity: 'base'});
54
136
  }
55
137
  });
56
- return fixedToOriginal.get(fixed[0]) ?? fixed[0];
138
+ return fixedToOriginal.get(sorted[0]) ?? sorted[0];
57
139
  }
58
140
  }
59
141
 
@@ -62,25 +144,25 @@ export async function getSemverVersion(data: RS): Promise<string> {
62
144
  *
63
145
  * @param data
64
146
  */
65
- export async function getLatestVersion(data: RS): Promise<string> {
66
- if (!data['version'] && data['fetch_latest'] === 'false') {
147
+ export async function getLatestVersion(data: ToolInput): Promise<string> {
148
+ if (!data.version && data.fetch_latest === 'false') {
67
149
  return 'latest';
68
150
  }
69
- const resp: Record<string, string> = await fetch.fetch(
70
- `${data['github']}/${data['repository']}/releases.atom`
151
+ if (data.fetch_latest === 'true' && !data.repository) {
152
+ return 'latest';
153
+ }
154
+ const resp = await fetch.fetch(
155
+ `${data.github}/${data.repository}/releases.atom`
71
156
  );
72
- if (resp['data']) {
157
+ if (resp.data) {
73
158
  const releases: string[] = [
74
- ...resp['data'].matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+.\d+.\d+)"/g)
159
+ ...resp.data.matchAll(/releases\/tag\/([a-zA-Z]*)?(\d+\.\d+\.\d+)"/g)
75
160
  ].map(match => match[2]);
76
161
 
77
- return (
78
- releases
79
- .sort((a: string, b: string) =>
80
- a.localeCompare(b, undefined, {numeric: true})
81
- )
82
- .pop() || 'latest'
162
+ const sorted = releases.toSorted((a: string, b: string) =>
163
+ a.localeCompare(b, undefined, {numeric: true})
83
164
  );
165
+ return sorted.at(-1) || 'latest';
84
166
  }
85
167
  return 'latest';
86
168
  }
@@ -91,26 +173,29 @@ export async function getLatestVersion(data: RS): Promise<string> {
91
173
  * @param version
92
174
  * @param data
93
175
  */
94
- export async function getVersion(version: string, data: RS): Promise<string> {
176
+ export async function getVersion(
177
+ version: string,
178
+ data: ToolData
179
+ ): Promise<string> {
95
180
  // semver_regex - https://semver.org/
96
181
  const semver_regex =
97
182
  /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
98
- const composer_regex = /^composer:(stable|preview|snapshot|[1|2])$/;
183
+ const composer_regex = /^composer:(stable|preview|snapshot|[12])$/;
99
184
  const constraint_regex = /[><=^~]+.*/;
100
185
  const major_minor_regex = /^\d+(\.\d+)?$/;
101
- data['version'] = version.replace(/v?(\d)/, '$1').replace(/\.x/, '');
186
+ data.version = version.replace(/v?(\d)/, '$1').replace(/\.x/, '');
102
187
  switch (true) {
103
- case composer_regex.test(data['release']):
104
- case semver_regex.test(data['version']):
105
- case constraint_regex.test(data['version']) && data['type'] === 'composer':
106
- return data['version'];
107
- case major_minor_regex.test(data['version']) && data['type'] === 'composer':
108
- data['release'] = `${data['tool']}:${data['version']}.*`;
109
- return `${data['version']}.*`;
110
- case data['repository'] && major_minor_regex.test(data['version']):
188
+ case composer_regex.test(data.release):
189
+ case semver_regex.test(data.version):
190
+ case constraint_regex.test(data.version) && data.type === 'composer':
191
+ return data.version;
192
+ case major_minor_regex.test(data.version) && data.type === 'composer':
193
+ data.release = `${data.tool}:${data.version}.*`;
194
+ return `${data.version}.*`;
195
+ case !!data.repository && major_minor_regex.test(data.version):
111
196
  return await getSemverVersion(data);
112
197
  default:
113
- return data['version'].replace(/[><=^~]*/, '');
198
+ return data.version.replace(/[><=^~]*/, '');
114
199
  }
115
200
  }
116
201
 
@@ -120,11 +205,14 @@ export async function getVersion(version: string, data: RS): Promise<string> {
120
205
  * @param release
121
206
  * @param data
122
207
  */
123
- export async function getRelease(release: string, data: RS): Promise<string> {
208
+ export async function getRelease(
209
+ release: string,
210
+ data: ToolData
211
+ ): Promise<string> {
124
212
  release = release.includes('/') ? release.split('/')[1] : release;
125
213
  return release.includes(':')
126
- ? [data['tool'], release.split(':')[1]].join(':')
127
- : data['tool'];
214
+ ? [data.tool, release.split(':')[1]].join(':')
215
+ : data.tool;
128
216
  }
129
217
 
130
218
  /**
@@ -143,7 +231,7 @@ export async function filterList(tools_list: string[]): Promise<string[]> {
143
231
  case matches[0] == undefined:
144
232
  break;
145
233
  default:
146
- composer = matches[matches.length - 1].replace(/v(\d\S*)/, '$1');
234
+ composer = matches.at(-1)!.replace(/v(\d\S*)/, '$1');
147
235
  break;
148
236
  }
149
237
  tools_list.unshift(composer);
@@ -155,26 +243,27 @@ export async function filterList(tools_list: string[]): Promise<string[]> {
155
243
  *
156
244
  * @param data
157
245
  */
158
- export async function getUrl(data: RS): Promise<string> {
159
- if ((data['version'] ?? 'latest') === 'latest') {
246
+ export async function getUrl(data: ToolInput): Promise<string> {
247
+ const version = data.version ?? 'latest';
248
+ if (version === 'latest' || version === '') {
160
249
  return [
161
- data['domain'],
162
- data['repository'],
163
- data['prefix'],
164
- data['version'],
165
- data['verb'],
166
- data['tool'] + data['extension']
250
+ data.domain,
251
+ data.repository,
252
+ data.prefix,
253
+ 'latest',
254
+ data.verb,
255
+ data.tool + data.extension
167
256
  ]
168
257
  .filter(Boolean)
169
258
  .join('/');
170
259
  } else {
171
260
  return [
172
- data['domain'],
173
- data['repository'],
174
- data['prefix'],
175
- data['verb'],
176
- data['version_prefix'] + data['version'],
177
- data['tool'] + data['extension']
261
+ data.domain,
262
+ data.repository,
263
+ data.prefix,
264
+ data.verb,
265
+ data.version_prefix + data.version,
266
+ data.tool + data.extension
178
267
  ]
179
268
  .filter(Boolean)
180
269
  .join('/');
@@ -186,17 +275,17 @@ export async function getUrl(data: RS): Promise<string> {
186
275
  *
187
276
  * @param data
188
277
  */
189
- export async function getPharUrl(data: RS): Promise<string> {
190
- if (data['version'] === 'latest') {
191
- return data['domain'] + '/' + data['tool'] + '.phar';
278
+ export async function getPharUrl(data: ToolData): Promise<string> {
279
+ if (data.version === 'latest') {
280
+ return data.domain + '/' + data.tool + '.phar';
192
281
  } else {
193
282
  return (
194
- data['domain'] +
283
+ data.domain +
195
284
  '/' +
196
- data['tool'] +
285
+ data.tool +
197
286
  '-' +
198
- data['version_prefix'] +
199
- data['version'] +
287
+ data.version_prefix +
288
+ data.version +
200
289
  '.phar'
201
290
  );
202
291
  }
@@ -207,10 +296,10 @@ export async function getPharUrl(data: RS): Promise<string> {
207
296
  *
208
297
  * @param data
209
298
  */
210
- export async function addArchive(data: RS): Promise<string> {
299
+ export async function addArchive(data: ToolData): Promise<string> {
211
300
  return (
212
- (await utils.getCommand(data['os'], 'tool')) +
213
- (await utils.joins(data['url'], data['tool'], data['version_parameter']))
301
+ (await utils.getCommand(data.os, 'tool')) +
302
+ (await utils.joins(data.url, data.tool, data.version_parameter))
214
303
  );
215
304
  }
216
305
 
@@ -219,14 +308,14 @@ export async function addArchive(data: RS): Promise<string> {
219
308
  *
220
309
  * @param data
221
310
  */
222
- export async function addPackage(data: RS): Promise<string> {
223
- const command = await utils.getCommand(data['os'], 'composer_tool');
224
- const parts: string[] = data['repository'].split('/');
311
+ export async function addPackage(data: ToolData): Promise<string> {
312
+ const command = await utils.getCommand(data.os, 'composer_tool');
313
+ const parts: string[] = data.repository.split('/');
225
314
  const args: string = await utils.joins(
226
315
  parts[1],
227
- data['release'],
316
+ data.release,
228
317
  parts[0] + '/',
229
- data['scope']
318
+ data.scope
230
319
  );
231
320
  return command + args;
232
321
  }
@@ -236,24 +325,24 @@ export async function addPackage(data: RS): Promise<string> {
236
325
  *
237
326
  * @param data
238
327
  */
239
- export async function addBlackfirePlayer(data: RS): Promise<string> {
240
- switch (data['os']) {
328
+ export async function addBlackfirePlayer(data: ToolData): Promise<string> {
329
+ switch (data.os) {
241
330
  case 'win32':
242
331
  return await utils.addLog(
243
332
  '$cross',
244
- data['tool'],
245
- data['tool'] + ' is not a windows tool',
333
+ data.tool,
334
+ data.tool + ' is not a windows tool',
246
335
  'win32'
247
336
  );
248
337
  default:
249
- if (data['version'] == 'latest') {
250
- if (/5\.[5-6]|7\.0/.test(data['php_version'])) {
251
- data['version'] = '1.9.3';
252
- } else if (/7\.[1-4]|8\.0/.test(data['php_version'])) {
253
- data['version'] = '1.22.0';
338
+ if (data.version == 'latest') {
339
+ if (/5\.[5-6]|7\.0/.test(data.php_version)) {
340
+ data.version = '1.9.3';
341
+ } else if (/7\.[1-4]|8\.0/.test(data.php_version)) {
342
+ data.version = '1.22.0';
254
343
  }
255
344
  }
256
- data['url'] = await getPharUrl(data);
345
+ data.url = await getPharUrl(data);
257
346
  return addArchive(data);
258
347
  }
259
348
  }
@@ -263,12 +352,12 @@ export async function addBlackfirePlayer(data: RS): Promise<string> {
263
352
  *
264
353
  * @param data
265
354
  */
266
- export async function addCastor(data: RS): Promise<string> {
267
- data['tool'] = 'castor.' + data['os'].replace('win32', 'windows') + '-amd64';
268
- data['url'] = await getUrl(data);
269
- data['tool'] = 'castor';
270
- data['version_parameter'] = fs.existsSync('castor.php')
271
- ? data['version_parameter']
355
+ export async function addCastor(data: ToolData): Promise<string> {
356
+ data.tool = 'castor.' + data.os.replace('win32', 'windows') + '-amd64';
357
+ data.url = await getUrl(data);
358
+ data.tool = 'castor';
359
+ data.version_parameter = fs.existsSync('castor.php')
360
+ ? data.version_parameter
272
361
  : '';
273
362
  return await addArchive(data);
274
363
  }
@@ -278,18 +367,18 @@ export async function addCastor(data: RS): Promise<string> {
278
367
  *
279
368
  * @param data
280
369
  */
281
- export async function addComposer(data: RS): Promise<string> {
282
- const channel = data['version'].replace('latest', 'stable');
283
- const github = data['github'];
284
- const getcomposer = data['domain'];
370
+ export async function addComposer(data: ToolData): Promise<string> {
371
+ const channel = data.version.replace('latest', 'stable');
372
+ const github = data.github;
373
+ const getcomposer = data.domain;
285
374
  const cds = 'https://dl.cloudsmith.io';
286
375
  const spc = 'https://artifacts.setup-php.com';
287
- const filename = `composer-${data['php_version']}-${channel}.phar`;
376
+ const filename = `composer-${data.php_version}-${channel}.phar`;
288
377
  const releases_url = `${github}/shivammathur/composer-cache/releases/latest/download/${filename}`;
289
378
  const cds_url = `${cds}/public/shivammathur/composer-cache/raw/files/${filename}`;
290
379
  const spc_url = `${spc}/composer/${filename}`;
291
380
  const lts_url = `${getcomposer}/download/latest-2.2.x/composer.phar`;
292
- const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data['php_version']);
381
+ const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data.php_version);
293
382
  const channel_source_url = `${getcomposer}/composer-${channel}.phar`;
294
383
  const version_source_url = `${getcomposer}/download/${channel}/composer.phar`;
295
384
  let cache_url = `${releases_url},${spc_url},${cds_url}`;
@@ -304,16 +393,16 @@ export async function addComposer(data: RS): Promise<string> {
304
393
  case /^1$/.test(channel):
305
394
  source_url = channel_source_url;
306
395
  break;
307
- case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']):
308
- cache_url = `${github}/${data['repository']}/releases/download/${data['version']}/composer.phar`;
396
+ case /^\d+\.\d+\.\d+[\w-]*$/.test(data.version):
397
+ cache_url = `${github}/${data.repository}/releases/download/${data.version}/composer.phar`;
309
398
  source_url = version_source_url;
310
399
  break;
311
400
  default:
312
401
  source_url = is_lts ? lts_url : channel_source_url;
313
402
  }
314
403
  const use_cache: boolean = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true';
315
- data['url'] = use_cache ? `${cache_url},${source_url}` : source_url;
316
- data['version_parameter'] = data['version'];
404
+ data.url = use_cache ? `${cache_url},${source_url}` : source_url;
405
+ data.version_parameter = data.version;
317
406
  return await addArchive(data);
318
407
  }
319
408
 
@@ -322,27 +411,27 @@ export async function addComposer(data: RS): Promise<string> {
322
411
  *
323
412
  * @param data
324
413
  */
325
- export async function addDeployer(data: RS): Promise<string> {
326
- if (data['version'] === 'latest') {
327
- data['url'] = data['domain'] + '/deployer.phar';
414
+ export async function addDeployer(data: ToolData): Promise<string> {
415
+ if (data.version === 'latest') {
416
+ data.url = data.domain + '/deployer.phar';
328
417
  } else {
329
- const manifest: RS = await fetch.fetch(
330
- 'https://deployer.org/manifest.json'
418
+ const manifest = await fetch.fetch('https://deployer.org/manifest.json');
419
+ const version_data: Record<string, DeployerManifestEntry> = JSON.parse(
420
+ manifest.data
331
421
  );
332
- const version_data: RSRS = JSON.parse(manifest.data);
333
422
  const version_key: string | undefined = Object.keys(version_data).find(
334
423
  (key: string) => {
335
- return version_data[key]['version'] === data['version'];
424
+ return version_data[key].version === data.version;
336
425
  }
337
426
  );
338
427
  if (version_key) {
339
- data['url'] = version_data[version_key]['url'];
428
+ data.url = version_data[version_key].url;
340
429
  } else {
341
430
  return await utils.addLog(
342
431
  '$cross',
343
432
  'deployer',
344
433
  'Version missing in deployer manifest',
345
- data['os']
434
+ data.os
346
435
  );
347
436
  }
348
437
  }
@@ -354,22 +443,22 @@ export async function addDeployer(data: RS): Promise<string> {
354
443
  *
355
444
  * @param data
356
445
  */
357
- export async function addDevTools(data: RS): Promise<string> {
358
- switch (data['os']) {
446
+ export async function addDevTools(data: ToolData): Promise<string> {
447
+ switch (data.os) {
359
448
  case 'linux':
360
449
  case 'darwin':
361
- return 'add_devtools ' + data['tool'];
450
+ return 'add_devtools ' + data.tool;
362
451
  case 'win32':
363
452
  return await utils.addLog(
364
453
  '$tick',
365
- data['tool'],
366
- data['tool'] + ' is not a windows tool',
454
+ data.tool,
455
+ data.tool + ' is not a windows tool',
367
456
  'win32'
368
457
  );
369
458
  default:
370
459
  return await utils.log(
371
- 'Platform ' + data['os'] + ' is not supported',
372
- data['os'],
460
+ 'Platform ' + data.os + ' is not supported',
461
+ data.os,
373
462
  'error'
374
463
  );
375
464
  }
@@ -380,8 +469,8 @@ export async function addDevTools(data: RS): Promise<string> {
380
469
  *
381
470
  * @param data
382
471
  */
383
- export async function addPECL(data: RS): Promise<string> {
384
- return await utils.getCommand(data['os'], 'pecl');
472
+ export async function addPECL(data: ToolData): Promise<string> {
473
+ return await utils.getCommand(data.os, 'pecl');
385
474
  }
386
475
 
387
476
  /**
@@ -389,14 +478,13 @@ export async function addPECL(data: RS): Promise<string> {
389
478
  *
390
479
  * @param data
391
480
  */
392
- export async function addPhing(data: RS): Promise<string> {
393
- data['url'] =
394
- data['domain'] + '/get/phing-' + data['version'] + data['extension'];
395
- if (data['version'] != 'latest') {
396
- [data['prefix'], data['verb']] = ['releases', 'download'];
397
- data['domain'] = data['github'];
398
- data['extension'] = '-' + data['version'] + data['extension'];
399
- data['url'] += ',' + (await getUrl(data));
481
+ export async function addPhing(data: ToolData): Promise<string> {
482
+ data.url = data.domain + '/get/phing-' + data.version + data.extension;
483
+ if (data.version != 'latest') {
484
+ [data.prefix, data.verb] = ['releases', 'download'];
485
+ data.domain = data.github;
486
+ data.extension = '-' + data.version + data.extension;
487
+ data.url += ',' + (await getUrl(data));
400
488
  }
401
489
  return await addArchive(data);
402
490
  }
@@ -406,33 +494,33 @@ export async function addPhing(data: RS): Promise<string> {
406
494
  *
407
495
  * @param data
408
496
  */
409
- export async function addPhive(data: RS): Promise<string> {
497
+ export async function addPhive(data: ToolData): Promise<string> {
410
498
  switch (true) {
411
- case /5\.[3-5]/.test(data['php_version']):
499
+ case /5\.[3-5]/.test(data.php_version):
412
500
  return await utils.addLog(
413
501
  '$cross',
414
502
  'phive',
415
- 'Phive is not supported on PHP ' + data['php_version'],
416
- data['os']
503
+ 'Phive is not supported on PHP ' + data.php_version,
504
+ data.os
417
505
  );
418
- case /5\.6|7\.0/.test(data['php_version']):
419
- data['version'] = '0.12.1';
506
+ case /5\.6|7\.0/.test(data.php_version):
507
+ data.version = '0.12.1';
420
508
  break;
421
- case /7\.1/.test(data['php_version']):
422
- data['version'] = '0.13.5';
509
+ case /7\.1/.test(data.php_version):
510
+ data.version = '0.13.5';
423
511
  break;
424
- case /7\.2/.test(data['php_version']):
425
- data['version'] = '0.14.5';
512
+ case /7\.2/.test(data.php_version):
513
+ data.version = '0.14.5';
426
514
  break;
427
- case /7\.3|7\.4/.test(data['php_version']):
428
- data['version'] = '0.15.3';
515
+ case /7\.3|7\.4/.test(data.php_version):
516
+ data.version = '0.15.3';
429
517
  break;
430
- case /^latest$/.test(data['version']):
431
- data['version'] = await getLatestVersion(data);
518
+ case /^latest$/.test(data.version):
519
+ data.version = await getLatestVersion(data);
432
520
  break;
433
521
  }
434
- data['extension'] = '-' + data['version'] + data['extension'];
435
- data['url'] = await getUrl(data);
522
+ data.extension = '-' + data.version + data.extension;
523
+ data.url = await getUrl(data);
436
524
  return await addArchive(data);
437
525
  }
438
526
 
@@ -441,16 +529,15 @@ export async function addPhive(data: RS): Promise<string> {
441
529
  *
442
530
  * @param data
443
531
  */
444
- export async function addPHPUnitTools(data: RS): Promise<string> {
532
+ export async function addPHPUnitTools(data: ToolData): Promise<string> {
445
533
  /* istanbul ignore next */
446
- if (data['version'] === 'latest') {
447
- data['version'] =
448
- (await packagist.search(data['packagist'], data['php_version'])) ??
449
- 'latest';
534
+ if (data.version === 'latest') {
535
+ data.version =
536
+ (await packagist.search(data.packagist, data.php_version)) ?? 'latest';
450
537
  }
451
- data['url'] = await getPharUrl(data);
452
- if (data['url'].match(/-\d+/)) {
453
- data['url'] += ',' + data['url'].replace(/-(\d+)\.\d+\.\d+/, '-$1');
538
+ data.url = await getPharUrl(data);
539
+ if (data.url.match(/-\d+/)) {
540
+ data.url += ',' + data.url.replace(/-(\d+)\.\d+\.\d+/, '-$1');
454
541
  }
455
542
  return await addArchive(data);
456
543
  }
@@ -460,13 +547,13 @@ export async function addPHPUnitTools(data: RS): Promise<string> {
460
547
  *
461
548
  * @param data
462
549
  */
463
- export async function addWPCLI(data: RS): Promise<string> {
464
- if (data['version'] === 'latest') {
465
- data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
466
- data['url'] = [data['domain'], data['uri']].join('/');
550
+ export async function addWPCLI(data: ToolData): Promise<string> {
551
+ if (data.version === 'latest') {
552
+ data.uri = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
553
+ data.url = [data.domain, data.uri].join('/');
467
554
  } else {
468
- data['extension'] = '-' + data['version'] + data['extension'];
469
- data['url'] = await getUrl(data);
555
+ data.extension = '-' + data.version + data.extension;
556
+ data.url = await getUrl(data);
470
557
  }
471
558
  return await addArchive(data);
472
559
  }
@@ -482,56 +569,74 @@ export async function getData(
482
569
  release: string,
483
570
  php_version: string,
484
571
  os: string
485
- ): Promise<RS> {
572
+ ): Promise<ToolData> {
486
573
  const json_file_path = path.join(__dirname, '../src/configs/tools.json');
487
574
  const json_file: string = fs.readFileSync(json_file_path, 'utf8');
488
- const json_objects: RSRS = JSON.parse(json_file);
575
+ const json_objects: Record<string, ToolConfig> = JSON.parse(json_file);
489
576
  release = release.replace(/\s+/g, '');
490
577
  const parts: string[] = release.split(':');
491
578
  const tool = parts[0];
492
579
  const version = parts[1];
493
- let data: RS;
494
- if (Object.keys(json_objects).includes(tool)) {
495
- data = json_objects[tool];
496
- data['tool'] = tool;
580
+ let config: ToolConfig & {tool: string};
581
+ if (Object.hasOwn(json_objects, tool)) {
582
+ config = {...json_objects[tool], tool};
497
583
  } else {
498
584
  const key: string | undefined = Object.keys(json_objects).find(
499
585
  (key: string) => {
500
- return json_objects[key]['alias'] == tool;
586
+ return json_objects[key].alias == tool;
501
587
  }
502
588
  );
503
589
  if (key) {
504
- data = json_objects[key];
505
- data['tool'] = key;
506
- } else {
507
- data = {
590
+ config = {...json_objects[key], tool: key};
591
+ } else if (tool.includes('/')) {
592
+ config = {
508
593
  tool: tool.split('/')[1],
509
594
  repository: tool,
510
595
  type: 'composer'
511
596
  };
512
- data = !tool.includes('/') ? {tool: tool} : data;
597
+ } else {
598
+ config = {tool};
513
599
  }
514
600
  }
515
- data['github'] = 'https://github.com';
516
- data['domain'] ??= data['github'];
517
- data['extension'] ??= '.phar';
518
- data['os'] = os;
519
- data['php_version'] = php_version;
520
- data['packagist'] ??= data['repository'];
521
- data['prefix'] = data['github'] === data['domain'] ? 'releases' : '';
522
- data['verb'] = data['github'] === data['domain'] ? 'download' : '';
523
- data['fetch_latest'] ??= 'false';
524
- data['scope'] ??= 'global';
525
- data['version_parameter'] = JSON.stringify(data['version_parameter']) || '';
526
- data['version_prefix'] ??= '';
527
- data['release'] = await getRelease(release, data);
528
- data['version'] = version
601
+ const github = 'https://github.com';
602
+ const domain = config.domain ?? github;
603
+ const data: ToolData = {
604
+ tool: config.tool,
605
+ version: '',
606
+ url: '',
607
+ os,
608
+ php_version,
609
+ github,
610
+ domain,
611
+ extension: config.extension ?? '.phar',
612
+ repository: config.repository ?? '',
613
+ prefix: domain === github ? 'releases' : '',
614
+ verb: domain === github ? 'download' : '',
615
+ fetch_latest: config.fetch_latest ?? 'false',
616
+ scope: config.scope ?? 'global',
617
+ version_parameter:
618
+ config.version_parameter != null
619
+ ? JSON.stringify(config.version_parameter)
620
+ : '',
621
+ version_prefix: config.version_prefix ?? '',
622
+ release: '',
623
+ packagist: config.packagist ?? config.repository ?? '',
624
+ type: config.type,
625
+ function: config.function,
626
+ alias: config.alias
627
+ };
628
+ data.release = await getRelease(release, data);
629
+ data.version = version
529
630
  ? await getVersion(version, data)
530
631
  : await getLatestVersion(data);
632
+ data.url = await getUrl(data);
531
633
  return data;
532
634
  }
533
635
 
534
- export const functionRecord: Record<string, (data: RS) => Promise<string>> = {
636
+ export const functionRecord: Record<
637
+ ToolFunction,
638
+ (data: ToolData) => Promise<string>
639
+ > = {
535
640
  castor: addCastor,
536
641
  composer: addComposer,
537
642
  deployer: addDeployer,
@@ -565,43 +670,46 @@ export async function addTools(
565
670
  }
566
671
  const tools_list = await filterList(await utils.CSVArray(tools_csv));
567
672
  await utils.asyncForEach(tools_list, async function (release: string) {
568
- const data: RS = await getData(release, php_version, os);
673
+ const data: ToolData = await getData(release, php_version, os);
569
674
  script += '\n';
570
675
  switch (true) {
571
- case data['error'] !== undefined:
572
- script += await utils.addLog(
573
- '$cross',
574
- data['tool'],
575
- data['error'],
576
- data['os']
577
- );
676
+ case data.error !== undefined:
677
+ script += await utils.addLog('$cross', data.tool, data.error, data.os);
578
678
  break;
579
- case 'phar' === data['type']:
580
- data['url'] = await getUrl(data);
679
+ case 'phar' === data.type:
581
680
  script += await addArchive(data);
582
681
  break;
583
- case 'composer' === data['type']:
682
+ case 'composer' === data.type:
584
683
  script += await addPackage(data);
585
684
  break;
586
- case 'custom-package' === data['type']:
685
+ case 'custom-package' === data.type:
587
686
  script += await utils.customPackage(
588
- data['tool'].split('-')[0],
687
+ data.tool.split('-')[0],
589
688
  'tools',
590
- data['version'],
591
- data['os']
689
+ data.version,
690
+ data.os
592
691
  );
593
692
  break;
594
- case 'custom-function' === data['type']:
595
- script += await functionRecord[data['function']](data);
693
+ case 'custom-function' === data.type:
694
+ if (!data.function) {
695
+ script += await utils.addLog(
696
+ '$cross',
697
+ data.tool,
698
+ data.tool + ' has no function defined. Please report this issue.',
699
+ data.os
700
+ );
701
+ } else {
702
+ script += await functionRecord[data.function](data);
703
+ }
596
704
  break;
597
- case /^none$/.test(data['tool']):
705
+ case /^none$/.test(data.tool):
598
706
  break;
599
707
  default:
600
708
  script += await utils.addLog(
601
709
  '$cross',
602
- data['tool'],
603
- 'Tool ' + data['tool'] + ' is not supported',
604
- data['os']
710
+ data.tool,
711
+ 'Tool ' + data.tool + ' is not supported',
712
+ data.os
605
713
  );
606
714
  break;
607
715
  }