setup-php 2.35.5 → 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.
Files changed (58) hide show
  1. package/README.md +103 -90
  2. package/lib/core.d.ts +8 -0
  3. package/lib/core.js +55 -0
  4. package/lib/core.js.map +1 -0
  5. package/lib/extensions.js +17 -16
  6. package/lib/extensions.js.map +1 -1
  7. package/lib/fetch.js +25 -70
  8. package/lib/fetch.js.map +1 -1
  9. package/lib/install.js +1 -1
  10. package/lib/install.js.map +1 -1
  11. package/lib/tools.d.ts +48 -21
  12. package/lib/tools.js +175 -154
  13. package/lib/tools.js.map +1 -1
  14. package/lib/utils.js +5 -5
  15. package/lib/utils.js.map +1 -1
  16. package/package.json +23 -22
  17. package/src/configs/brew_extensions +20 -0
  18. package/src/configs/darwin_libs +22 -0
  19. package/src/configs/linux_libs +22 -0
  20. package/src/configs/php-versions.json +5 -4
  21. package/src/configs/tools.json +2 -1
  22. package/src/core.ts +112 -0
  23. package/src/extensions.ts +39 -32
  24. package/src/fetch.ts +28 -42
  25. package/src/install.ts +1 -1
  26. package/src/scripts/darwin.sh +45 -19
  27. package/src/scripts/extensions/add_extensions.sh +5 -3
  28. package/src/scripts/extensions/couchbase.sh +13 -2
  29. package/src/scripts/extensions/firebird.sh +6 -23
  30. package/src/scripts/extensions/gearman.sh +3 -1
  31. package/src/scripts/extensions/http.ps1 +7 -5
  32. package/src/scripts/extensions/ibm.ps1 +56 -0
  33. package/src/scripts/extensions/ibm.sh +106 -0
  34. package/src/scripts/extensions/oci.sh +2 -1
  35. package/src/scripts/extensions/patches/amqp.sh +5 -0
  36. package/src/scripts/extensions/patches/common.sh +31 -8
  37. package/src/scripts/extensions/patches/geos.sh +1 -5
  38. package/src/scripts/extensions/patches/pdo_oci.sh +3 -0
  39. package/src/scripts/extensions/patches/pdo_sqlsrv.sh +5 -0
  40. package/src/scripts/extensions/patches/phpize.sh +2 -1
  41. package/src/scripts/extensions/relay.sh +25 -35
  42. package/src/scripts/extensions/source.sh +26 -6
  43. package/src/scripts/extensions/sqlsrv.ps1 +2 -0
  44. package/src/scripts/extensions/sqlsrv.sh +2 -0
  45. package/src/scripts/linux.sh +50 -10
  46. package/src/scripts/tools/add_tools.ps1 +52 -26
  47. package/src/scripts/tools/add_tools.sh +41 -19
  48. package/src/scripts/tools/blackfire.sh +1 -1
  49. package/src/scripts/tools/brew.sh +130 -0
  50. package/src/scripts/tools/grpc_php_plugin.sh +2 -2
  51. package/src/scripts/tools/ppa.sh +201 -28
  52. package/src/scripts/tools/symfony.ps1 +28 -14
  53. package/src/scripts/tools/symfony.sh +34 -31
  54. package/src/scripts/unix.sh +8 -4
  55. package/src/scripts/win32.ps1 +9 -4
  56. package/src/tools.ts +312 -203
  57. package/src/utils.ts +6 -7
  58. package/src/scripts/extensions/patches/gearman.sh +0 -5
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') {
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,19 +367,20 @@ 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']);
293
- const version_source_url = `${getcomposer}/composer-${channel}.phar`;
381
+ const is_lts = /^5\.[3-6]$|^7\.[0-1]$/.test(data.php_version);
382
+ const channel_source_url = `${getcomposer}/composer-${channel}.phar`;
383
+ const version_source_url = `${getcomposer}/download/${channel}/composer.phar`;
294
384
  let cache_url = `${releases_url},${spc_url},${cds_url}`;
295
385
  let source_url = `${getcomposer}/composer.phar`;
296
386
  switch (true) {
@@ -298,21 +388,21 @@ export async function addComposer(data: RS): Promise<string> {
298
388
  source_url = is_lts ? lts_url : source_url;
299
389
  break;
300
390
  case /^preview$|^2$/.test(channel):
301
- source_url = is_lts ? lts_url : version_source_url;
391
+ source_url = is_lts ? lts_url : channel_source_url;
302
392
  break;
303
393
  case /^1$/.test(channel):
304
- source_url = version_source_url;
394
+ source_url = channel_source_url;
305
395
  break;
306
- case /^\d+\.\d+\.\d+[\w-]*$/.test(data['version']):
307
- 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`;
308
398
  source_url = version_source_url;
309
399
  break;
310
400
  default:
311
- source_url = is_lts ? lts_url : version_source_url;
401
+ source_url = is_lts ? lts_url : channel_source_url;
312
402
  }
313
403
  const use_cache: boolean = (await utils.readEnv('NO_TOOLS_CACHE')) !== 'true';
314
- data['url'] = use_cache ? `${cache_url},${source_url}` : source_url;
315
- data['version_parameter'] = data['version'];
404
+ data.url = use_cache ? `${cache_url},${source_url}` : source_url;
405
+ data.version_parameter = data.version;
316
406
  return await addArchive(data);
317
407
  }
318
408
 
@@ -321,27 +411,27 @@ export async function addComposer(data: RS): Promise<string> {
321
411
  *
322
412
  * @param data
323
413
  */
324
- export async function addDeployer(data: RS): Promise<string> {
325
- if (data['version'] === 'latest') {
326
- 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';
327
417
  } else {
328
- const manifest: RS = await fetch.fetch(
329
- '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
330
421
  );
331
- const version_data: RSRS = JSON.parse(manifest.data);
332
422
  const version_key: string | undefined = Object.keys(version_data).find(
333
423
  (key: string) => {
334
- return version_data[key]['version'] === data['version'];
424
+ return version_data[key].version === data.version;
335
425
  }
336
426
  );
337
427
  if (version_key) {
338
- data['url'] = version_data[version_key]['url'];
428
+ data.url = version_data[version_key].url;
339
429
  } else {
340
430
  return await utils.addLog(
341
431
  '$cross',
342
432
  'deployer',
343
433
  'Version missing in deployer manifest',
344
- data['os']
434
+ data.os
345
435
  );
346
436
  }
347
437
  }
@@ -353,22 +443,22 @@ export async function addDeployer(data: RS): Promise<string> {
353
443
  *
354
444
  * @param data
355
445
  */
356
- export async function addDevTools(data: RS): Promise<string> {
357
- switch (data['os']) {
446
+ export async function addDevTools(data: ToolData): Promise<string> {
447
+ switch (data.os) {
358
448
  case 'linux':
359
449
  case 'darwin':
360
- return 'add_devtools ' + data['tool'];
450
+ return 'add_devtools ' + data.tool;
361
451
  case 'win32':
362
452
  return await utils.addLog(
363
453
  '$tick',
364
- data['tool'],
365
- data['tool'] + ' is not a windows tool',
454
+ data.tool,
455
+ data.tool + ' is not a windows tool',
366
456
  'win32'
367
457
  );
368
458
  default:
369
459
  return await utils.log(
370
- 'Platform ' + data['os'] + ' is not supported',
371
- data['os'],
460
+ 'Platform ' + data.os + ' is not supported',
461
+ data.os,
372
462
  'error'
373
463
  );
374
464
  }
@@ -379,8 +469,8 @@ export async function addDevTools(data: RS): Promise<string> {
379
469
  *
380
470
  * @param data
381
471
  */
382
- export async function addPECL(data: RS): Promise<string> {
383
- return await utils.getCommand(data['os'], 'pecl');
472
+ export async function addPECL(data: ToolData): Promise<string> {
473
+ return await utils.getCommand(data.os, 'pecl');
384
474
  }
385
475
 
386
476
  /**
@@ -388,14 +478,13 @@ export async function addPECL(data: RS): Promise<string> {
388
478
  *
389
479
  * @param data
390
480
  */
391
- export async function addPhing(data: RS): Promise<string> {
392
- data['url'] =
393
- data['domain'] + '/get/phing-' + data['version'] + data['extension'];
394
- if (data['version'] != 'latest') {
395
- [data['prefix'], data['verb']] = ['releases', 'download'];
396
- data['domain'] = data['github'];
397
- data['extension'] = '-' + data['version'] + data['extension'];
398
- 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));
399
488
  }
400
489
  return await addArchive(data);
401
490
  }
@@ -405,33 +494,33 @@ export async function addPhing(data: RS): Promise<string> {
405
494
  *
406
495
  * @param data
407
496
  */
408
- export async function addPhive(data: RS): Promise<string> {
497
+ export async function addPhive(data: ToolData): Promise<string> {
409
498
  switch (true) {
410
- case /5\.[3-5]/.test(data['php_version']):
499
+ case /5\.[3-5]/.test(data.php_version):
411
500
  return await utils.addLog(
412
501
  '$cross',
413
502
  'phive',
414
- 'Phive is not supported on PHP ' + data['php_version'],
415
- data['os']
503
+ 'Phive is not supported on PHP ' + data.php_version,
504
+ data.os
416
505
  );
417
- case /5\.6|7\.0/.test(data['php_version']):
418
- data['version'] = '0.12.1';
506
+ case /5\.6|7\.0/.test(data.php_version):
507
+ data.version = '0.12.1';
419
508
  break;
420
- case /7\.1/.test(data['php_version']):
421
- data['version'] = '0.13.5';
509
+ case /7\.1/.test(data.php_version):
510
+ data.version = '0.13.5';
422
511
  break;
423
- case /7\.2/.test(data['php_version']):
424
- data['version'] = '0.14.5';
512
+ case /7\.2/.test(data.php_version):
513
+ data.version = '0.14.5';
425
514
  break;
426
- case /7\.3|7\.4/.test(data['php_version']):
427
- data['version'] = '0.15.3';
515
+ case /7\.3|7\.4/.test(data.php_version):
516
+ data.version = '0.15.3';
428
517
  break;
429
- case /^latest$/.test(data['version']):
430
- data['version'] = await getLatestVersion(data);
518
+ case /^latest$/.test(data.version):
519
+ data.version = await getLatestVersion(data);
431
520
  break;
432
521
  }
433
- data['extension'] = '-' + data['version'] + data['extension'];
434
- data['url'] = await getUrl(data);
522
+ data.extension = '-' + data.version + data.extension;
523
+ data.url = await getUrl(data);
435
524
  return await addArchive(data);
436
525
  }
437
526
 
@@ -440,16 +529,15 @@ export async function addPhive(data: RS): Promise<string> {
440
529
  *
441
530
  * @param data
442
531
  */
443
- export async function addPHPUnitTools(data: RS): Promise<string> {
532
+ export async function addPHPUnitTools(data: ToolData): Promise<string> {
444
533
  /* istanbul ignore next */
445
- if (data['version'] === 'latest') {
446
- data['version'] =
447
- (await packagist.search(data['packagist'], data['php_version'])) ??
448
- 'latest';
534
+ if (data.version === 'latest') {
535
+ data.version =
536
+ (await packagist.search(data.packagist, data.php_version)) ?? 'latest';
449
537
  }
450
- data['url'] = await getPharUrl(data);
451
- if (data['url'].match(/-\d+/)) {
452
- 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');
453
541
  }
454
542
  return await addArchive(data);
455
543
  }
@@ -459,13 +547,13 @@ export async function addPHPUnitTools(data: RS): Promise<string> {
459
547
  *
460
548
  * @param data
461
549
  */
462
- export async function addWPCLI(data: RS): Promise<string> {
463
- if (data['version'] === 'latest') {
464
- data['uri'] = 'wp-cli/builds/blob/gh-pages/phar/wp-cli.phar?raw=true';
465
- 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('/');
466
554
  } else {
467
- data['extension'] = '-' + data['version'] + data['extension'];
468
- data['url'] = await getUrl(data);
555
+ data.extension = '-' + data.version + data.extension;
556
+ data.url = await getUrl(data);
469
557
  }
470
558
  return await addArchive(data);
471
559
  }
@@ -481,56 +569,74 @@ export async function getData(
481
569
  release: string,
482
570
  php_version: string,
483
571
  os: string
484
- ): Promise<RS> {
572
+ ): Promise<ToolData> {
485
573
  const json_file_path = path.join(__dirname, '../src/configs/tools.json');
486
574
  const json_file: string = fs.readFileSync(json_file_path, 'utf8');
487
- const json_objects: RSRS = JSON.parse(json_file);
575
+ const json_objects: Record<string, ToolConfig> = JSON.parse(json_file);
488
576
  release = release.replace(/\s+/g, '');
489
577
  const parts: string[] = release.split(':');
490
578
  const tool = parts[0];
491
579
  const version = parts[1];
492
- let data: RS;
493
- if (Object.keys(json_objects).includes(tool)) {
494
- data = json_objects[tool];
495
- data['tool'] = tool;
580
+ let config: ToolConfig & {tool: string};
581
+ if (Object.hasOwn(json_objects, tool)) {
582
+ config = {...json_objects[tool], tool};
496
583
  } else {
497
584
  const key: string | undefined = Object.keys(json_objects).find(
498
585
  (key: string) => {
499
- return json_objects[key]['alias'] == tool;
586
+ return json_objects[key].alias == tool;
500
587
  }
501
588
  );
502
589
  if (key) {
503
- data = json_objects[key];
504
- data['tool'] = key;
505
- } else {
506
- data = {
590
+ config = {...json_objects[key], tool: key};
591
+ } else if (tool.includes('/')) {
592
+ config = {
507
593
  tool: tool.split('/')[1],
508
594
  repository: tool,
509
595
  type: 'composer'
510
596
  };
511
- data = !tool.includes('/') ? {tool: tool} : data;
597
+ } else {
598
+ config = {tool};
512
599
  }
513
600
  }
514
- data['github'] = 'https://github.com';
515
- data['domain'] ??= data['github'];
516
- data['extension'] ??= '.phar';
517
- data['os'] = os;
518
- data['php_version'] = php_version;
519
- data['packagist'] ??= data['repository'];
520
- data['prefix'] = data['github'] === data['domain'] ? 'releases' : '';
521
- data['verb'] = data['github'] === data['domain'] ? 'download' : '';
522
- data['fetch_latest'] ??= 'false';
523
- data['scope'] ??= 'global';
524
- data['version_parameter'] = JSON.stringify(data['version_parameter']) || '';
525
- data['version_prefix'] ??= '';
526
- data['release'] = await getRelease(release, data);
527
- 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
528
630
  ? await getVersion(version, data)
529
631
  : await getLatestVersion(data);
632
+ data.url = await getUrl(data);
530
633
  return data;
531
634
  }
532
635
 
533
- export const functionRecord: Record<string, (data: RS) => Promise<string>> = {
636
+ export const functionRecord: Record<
637
+ ToolFunction,
638
+ (data: ToolData) => Promise<string>
639
+ > = {
534
640
  castor: addCastor,
535
641
  composer: addComposer,
536
642
  deployer: addDeployer,
@@ -564,43 +670,46 @@ export async function addTools(
564
670
  }
565
671
  const tools_list = await filterList(await utils.CSVArray(tools_csv));
566
672
  await utils.asyncForEach(tools_list, async function (release: string) {
567
- const data: RS = await getData(release, php_version, os);
673
+ const data: ToolData = await getData(release, php_version, os);
568
674
  script += '\n';
569
675
  switch (true) {
570
- case data['error'] !== undefined:
571
- script += await utils.addLog(
572
- '$cross',
573
- data['tool'],
574
- data['error'],
575
- data['os']
576
- );
676
+ case data.error !== undefined:
677
+ script += await utils.addLog('$cross', data.tool, data.error, data.os);
577
678
  break;
578
- case 'phar' === data['type']:
579
- data['url'] = await getUrl(data);
679
+ case 'phar' === data.type:
580
680
  script += await addArchive(data);
581
681
  break;
582
- case 'composer' === data['type']:
682
+ case 'composer' === data.type:
583
683
  script += await addPackage(data);
584
684
  break;
585
- case 'custom-package' === data['type']:
685
+ case 'custom-package' === data.type:
586
686
  script += await utils.customPackage(
587
- data['tool'].split('-')[0],
687
+ data.tool.split('-')[0],
588
688
  'tools',
589
- data['version'],
590
- data['os']
689
+ data.version,
690
+ data.os
591
691
  );
592
692
  break;
593
- case 'custom-function' === data['type']:
594
- 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
+ }
595
704
  break;
596
- case /^none$/.test(data['tool']):
705
+ case /^none$/.test(data.tool):
597
706
  break;
598
707
  default:
599
708
  script += await utils.addLog(
600
709
  '$cross',
601
- data['tool'],
602
- 'Tool ' + data['tool'] + ' is not supported',
603
- data['os']
710
+ data.tool,
711
+ 'Tool ' + data.tool + ' is not supported',
712
+ data.os
604
713
  );
605
714
  break;
606
715
  }