@hexonet/semantic-release-whmcs 3.0.2 → 3.1.2
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/.eslintrc.js +13 -11
- package/.github/workflows/pull-request.yml +47 -0
- package/.github/workflows/push.yml +76 -0
- package/.releaserc.json +20 -23
- package/HISTORY.md +30 -0
- package/README.md +5 -5
- package/coverage/base.css +224 -0
- package/coverage/block-navigation.js +87 -0
- package/coverage/coverage-final.json +11 -0
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +131 -0
- package/coverage/lib/definitions/errors.js.html +136 -0
- package/coverage/lib/definitions/index.html +116 -0
- package/coverage/lib/delete-marketplace-version.js.html +400 -0
- package/coverage/lib/get-error.js.html +106 -0
- package/coverage/lib/get-github-releases.js.html +190 -0
- package/coverage/lib/index.html +236 -0
- package/coverage/lib/publish.js.html +490 -0
- package/coverage/lib/puppet.js.html +271 -0
- package/coverage/lib/resolve-config.js.html +112 -0
- package/coverage/lib/scrape-marketplace-versions.js.html +322 -0
- package/coverage/lib/set-compatible-versions.js.html +376 -0
- package/coverage/lib/verify.js.html +145 -0
- package/coverage/prettify.css +1 -0
- package/coverage/prettify.js +2 -0
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +196 -0
- package/index.js +11 -9
- package/lib/definitions/errors.js +6 -3
- package/lib/delete-marketplace-version.js +7 -36
- package/lib/get-error.js +1 -1
- package/lib/get-github-releases.js +10 -8
- package/lib/publish.js +97 -105
- package/lib/puppet.js +62 -0
- package/lib/resolve-config.js +2 -2
- package/lib/scrape-marketplace-versions.js +5 -34
- package/lib/set-compatible-versions.js +6 -34
- package/package.json +20 -21
- package/whmcs.js +1 -2
- package/.github/workflows/release.yml +0 -56
- package/test/publish.test.js +0 -78
- package/test/verify.test.js +0 -54
@@ -0,0 +1,196 @@
|
|
1
|
+
/* eslint-disable */
|
2
|
+
var addSorting = (function() {
|
3
|
+
'use strict';
|
4
|
+
var cols,
|
5
|
+
currentSort = {
|
6
|
+
index: 0,
|
7
|
+
desc: false
|
8
|
+
};
|
9
|
+
|
10
|
+
// returns the summary table element
|
11
|
+
function getTable() {
|
12
|
+
return document.querySelector('.coverage-summary');
|
13
|
+
}
|
14
|
+
// returns the thead element of the summary table
|
15
|
+
function getTableHeader() {
|
16
|
+
return getTable().querySelector('thead tr');
|
17
|
+
}
|
18
|
+
// returns the tbody element of the summary table
|
19
|
+
function getTableBody() {
|
20
|
+
return getTable().querySelector('tbody');
|
21
|
+
}
|
22
|
+
// returns the th element for nth column
|
23
|
+
function getNthColumn(n) {
|
24
|
+
return getTableHeader().querySelectorAll('th')[n];
|
25
|
+
}
|
26
|
+
|
27
|
+
function onFilterInput() {
|
28
|
+
const searchValue = document.getElementById('fileSearch').value;
|
29
|
+
const rows = document.getElementsByTagName('tbody')[0].children;
|
30
|
+
for (let i = 0; i < rows.length; i++) {
|
31
|
+
const row = rows[i];
|
32
|
+
if (
|
33
|
+
row.textContent
|
34
|
+
.toLowerCase()
|
35
|
+
.includes(searchValue.toLowerCase())
|
36
|
+
) {
|
37
|
+
row.style.display = '';
|
38
|
+
} else {
|
39
|
+
row.style.display = 'none';
|
40
|
+
}
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
// loads the search box
|
45
|
+
function addSearchBox() {
|
46
|
+
var template = document.getElementById('filterTemplate');
|
47
|
+
var templateClone = template.content.cloneNode(true);
|
48
|
+
templateClone.getElementById('fileSearch').oninput = onFilterInput;
|
49
|
+
template.parentElement.appendChild(templateClone);
|
50
|
+
}
|
51
|
+
|
52
|
+
// loads all columns
|
53
|
+
function loadColumns() {
|
54
|
+
var colNodes = getTableHeader().querySelectorAll('th'),
|
55
|
+
colNode,
|
56
|
+
cols = [],
|
57
|
+
col,
|
58
|
+
i;
|
59
|
+
|
60
|
+
for (i = 0; i < colNodes.length; i += 1) {
|
61
|
+
colNode = colNodes[i];
|
62
|
+
col = {
|
63
|
+
key: colNode.getAttribute('data-col'),
|
64
|
+
sortable: !colNode.getAttribute('data-nosort'),
|
65
|
+
type: colNode.getAttribute('data-type') || 'string'
|
66
|
+
};
|
67
|
+
cols.push(col);
|
68
|
+
if (col.sortable) {
|
69
|
+
col.defaultDescSort = col.type === 'number';
|
70
|
+
colNode.innerHTML =
|
71
|
+
colNode.innerHTML + '<span class="sorter"></span>';
|
72
|
+
}
|
73
|
+
}
|
74
|
+
return cols;
|
75
|
+
}
|
76
|
+
// attaches a data attribute to every tr element with an object
|
77
|
+
// of data values keyed by column name
|
78
|
+
function loadRowData(tableRow) {
|
79
|
+
var tableCols = tableRow.querySelectorAll('td'),
|
80
|
+
colNode,
|
81
|
+
col,
|
82
|
+
data = {},
|
83
|
+
i,
|
84
|
+
val;
|
85
|
+
for (i = 0; i < tableCols.length; i += 1) {
|
86
|
+
colNode = tableCols[i];
|
87
|
+
col = cols[i];
|
88
|
+
val = colNode.getAttribute('data-value');
|
89
|
+
if (col.type === 'number') {
|
90
|
+
val = Number(val);
|
91
|
+
}
|
92
|
+
data[col.key] = val;
|
93
|
+
}
|
94
|
+
return data;
|
95
|
+
}
|
96
|
+
// loads all row data
|
97
|
+
function loadData() {
|
98
|
+
var rows = getTableBody().querySelectorAll('tr'),
|
99
|
+
i;
|
100
|
+
|
101
|
+
for (i = 0; i < rows.length; i += 1) {
|
102
|
+
rows[i].data = loadRowData(rows[i]);
|
103
|
+
}
|
104
|
+
}
|
105
|
+
// sorts the table using the data for the ith column
|
106
|
+
function sortByIndex(index, desc) {
|
107
|
+
var key = cols[index].key,
|
108
|
+
sorter = function(a, b) {
|
109
|
+
a = a.data[key];
|
110
|
+
b = b.data[key];
|
111
|
+
return a < b ? -1 : a > b ? 1 : 0;
|
112
|
+
},
|
113
|
+
finalSorter = sorter,
|
114
|
+
tableBody = document.querySelector('.coverage-summary tbody'),
|
115
|
+
rowNodes = tableBody.querySelectorAll('tr'),
|
116
|
+
rows = [],
|
117
|
+
i;
|
118
|
+
|
119
|
+
if (desc) {
|
120
|
+
finalSorter = function(a, b) {
|
121
|
+
return -1 * sorter(a, b);
|
122
|
+
};
|
123
|
+
}
|
124
|
+
|
125
|
+
for (i = 0; i < rowNodes.length; i += 1) {
|
126
|
+
rows.push(rowNodes[i]);
|
127
|
+
tableBody.removeChild(rowNodes[i]);
|
128
|
+
}
|
129
|
+
|
130
|
+
rows.sort(finalSorter);
|
131
|
+
|
132
|
+
for (i = 0; i < rows.length; i += 1) {
|
133
|
+
tableBody.appendChild(rows[i]);
|
134
|
+
}
|
135
|
+
}
|
136
|
+
// removes sort indicators for current column being sorted
|
137
|
+
function removeSortIndicators() {
|
138
|
+
var col = getNthColumn(currentSort.index),
|
139
|
+
cls = col.className;
|
140
|
+
|
141
|
+
cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, '');
|
142
|
+
col.className = cls;
|
143
|
+
}
|
144
|
+
// adds sort indicators for current column being sorted
|
145
|
+
function addSortIndicators() {
|
146
|
+
getNthColumn(currentSort.index).className += currentSort.desc
|
147
|
+
? ' sorted-desc'
|
148
|
+
: ' sorted';
|
149
|
+
}
|
150
|
+
// adds event listeners for all sorter widgets
|
151
|
+
function enableUI() {
|
152
|
+
var i,
|
153
|
+
el,
|
154
|
+
ithSorter = function ithSorter(i) {
|
155
|
+
var col = cols[i];
|
156
|
+
|
157
|
+
return function() {
|
158
|
+
var desc = col.defaultDescSort;
|
159
|
+
|
160
|
+
if (currentSort.index === i) {
|
161
|
+
desc = !currentSort.desc;
|
162
|
+
}
|
163
|
+
sortByIndex(i, desc);
|
164
|
+
removeSortIndicators();
|
165
|
+
currentSort.index = i;
|
166
|
+
currentSort.desc = desc;
|
167
|
+
addSortIndicators();
|
168
|
+
};
|
169
|
+
};
|
170
|
+
for (i = 0; i < cols.length; i += 1) {
|
171
|
+
if (cols[i].sortable) {
|
172
|
+
// add the click event handler on the th so users
|
173
|
+
// dont have to click on those tiny arrows
|
174
|
+
el = getNthColumn(i).querySelector('.sorter').parentElement;
|
175
|
+
if (el.addEventListener) {
|
176
|
+
el.addEventListener('click', ithSorter(i));
|
177
|
+
} else {
|
178
|
+
el.attachEvent('onclick', ithSorter(i));
|
179
|
+
}
|
180
|
+
}
|
181
|
+
}
|
182
|
+
}
|
183
|
+
// adds sorting functionality to the UI
|
184
|
+
return function() {
|
185
|
+
if (!getTable()) {
|
186
|
+
return;
|
187
|
+
}
|
188
|
+
cols = loadColumns();
|
189
|
+
loadData();
|
190
|
+
addSearchBox();
|
191
|
+
addSortIndicators();
|
192
|
+
enableUI();
|
193
|
+
};
|
194
|
+
})();
|
195
|
+
|
196
|
+
window.addEventListener('load', addSorting);
|
package/index.js
CHANGED
@@ -32,17 +32,19 @@ async function publish (pluginConfig, context) {
|
|
32
32
|
async function syncVersions (pluginConfig, context) {
|
33
33
|
await verifyConditions(pluginConfig, context)
|
34
34
|
const releases = await githubReleases(pluginConfig, context)
|
35
|
-
const versions = await marketplaceVersions(pluginConfig, context)
|
36
35
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
36
|
+
if (releases && releases.length) {
|
37
|
+
const versions = await marketplaceVersions(pluginConfig, context)
|
38
|
+
for (const release of releases) {
|
39
|
+
if (!versions.includes(release.name.substring(1))) {
|
40
|
+
context.nextRelease = {
|
41
|
+
version: release.name.substring(1),
|
42
|
+
notes: release.body,
|
43
|
+
releaseDate: release.published_at
|
44
|
+
}
|
45
|
+
console.log(`Adding missing version ${context.nextRelease.version}`)
|
46
|
+
await publish(pluginConfig, context)
|
43
47
|
}
|
44
|
-
console.log(`Adding missing version ${context.nextRelease.version}`)
|
45
|
-
await publish(pluginConfig, context)
|
46
48
|
}
|
47
49
|
}
|
48
50
|
}
|
@@ -1,14 +1,17 @@
|
|
1
1
|
module.exports = {
|
2
2
|
EWHMCSNOCREDENTIALS: () => ({
|
3
3
|
message: 'No WHMCS Marketplace credentials specified.',
|
4
|
-
details:
|
4
|
+
details:
|
5
|
+
'WHMCS Marketplace credentails have to be set in the `WHMCS_LOGIN` and `WHMCS_PASSWORD` environment variables on your CI environment.'
|
5
6
|
}),
|
6
7
|
EWHMCSNOPRODUCTID: () => ({
|
7
8
|
message: 'No WHMCS Marketplace Product ID specified.',
|
8
|
-
details:
|
9
|
+
details:
|
10
|
+
"The product id of your listed product at the WHMCS Marketplace has to be set in the `WHMCS_PRODUCTID` environment variable on your CI environment. You'll find that number in url when visiting the product page in WHMCS Marketplace."
|
9
11
|
}),
|
10
12
|
EWHMCSINVALIDPRODUCTID: () => ({
|
11
13
|
message: 'Invalid WHMCS Marketplace Product ID specified.',
|
12
|
-
details:
|
14
|
+
details:
|
15
|
+
"The product id of your listed product at the WHMCS Marketplace has to be set in the `WHMCS_PRODUCTID` environment variable on your CI environment. You'll find that number in url when visiting the product page in WHMCS Marketplace."
|
13
16
|
})
|
14
17
|
}
|
@@ -1,12 +1,6 @@
|
|
1
1
|
const debug = require('debug')('semantic-release:whmcs')
|
2
2
|
const resolveConfig = require('./resolve-config')
|
3
|
-
const
|
4
|
-
const gotoOpts = {
|
5
|
-
waitUntil: ['load', 'domcontentloaded'],
|
6
|
-
timeout: 240000
|
7
|
-
}
|
8
|
-
const navOpts = { waitUntil: 'networkidle0', timeout: 240000 }
|
9
|
-
const selectorOpts = { timeout: 10000 }
|
3
|
+
const puppet = require('./puppet')
|
10
4
|
|
11
5
|
/**
|
12
6
|
* A method to publish the module update on whmcs market place
|
@@ -25,6 +19,7 @@ module.exports = async (pluginConfig, context) => {
|
|
25
19
|
|
26
20
|
let success = true
|
27
21
|
const { whmcsLOGIN, whmcsPASSWORD, whmcsPRODUCTID, DEBUG } = resolveConfig(context)
|
22
|
+
const { gotoOpts, navOpts, selectorOpts, page } = await puppet(DEBUG, logger)
|
28
23
|
|
29
24
|
debug(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
|
30
25
|
logger.log(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
|
@@ -35,34 +30,8 @@ module.exports = async (pluginConfig, context) => {
|
|
35
30
|
// strip markdown links from notes as not allowed to keep
|
36
31
|
const wmbase = 'https://marketplace.whmcs.com'
|
37
32
|
let url = `${wmbase}/user/login`
|
38
|
-
const browser = await puppeteer.launch({
|
39
|
-
headless: !DEBUG,
|
40
|
-
defaultViewport: null, // automatically full-sized
|
41
|
-
args: [
|
42
|
-
'--incognito',
|
43
|
-
'--start-maximized',
|
44
|
-
'--no-sandbox',
|
45
|
-
'--disable-setuid-sandbox',
|
46
|
-
'--disable-infobars',
|
47
|
-
'--ignore-certifcate-errors',
|
48
|
-
'--ignore-certifcate-errors-spki-list',
|
49
|
-
'--ignoreHTTPSErrors=true',
|
50
|
-
'--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"'
|
51
|
-
]
|
52
|
-
})
|
53
|
-
const [page] = await browser.pages()
|
54
33
|
|
55
34
|
try {
|
56
|
-
await page.setRequestInterception(true)
|
57
|
-
page.on('request', request => {
|
58
|
-
if (/^(image|stylesheet|other)$/i.test(request.resourceType())) {
|
59
|
-
request.abort()
|
60
|
-
} else {
|
61
|
-
request.continue()
|
62
|
-
}
|
63
|
-
})
|
64
|
-
|
65
|
-
await page.setJavaScriptEnabled(true)
|
66
35
|
await page.goto(url, gotoOpts)
|
67
36
|
// do login
|
68
37
|
const selector = 'div.login-leftcol form button[type="submit"]'
|
@@ -72,6 +41,7 @@ module.exports = async (pluginConfig, context) => {
|
|
72
41
|
await page.type('#password', whmcsPASSWORD)
|
73
42
|
debug('WHMCS Marketplace credentials entered')
|
74
43
|
const nav = page.waitForNavigation(navOpts)
|
44
|
+
await page.hover(selector)
|
75
45
|
await page.click(selector)
|
76
46
|
await nav
|
77
47
|
debug('Login form successfully submitted.')
|
@@ -96,8 +66,10 @@ module.exports = async (pluginConfig, context) => {
|
|
96
66
|
await page.waitForXPath(xpath, selectorOpts)
|
97
67
|
debug('XPath found.')
|
98
68
|
let nav = page.waitForNavigation(navOpts)
|
69
|
+
/* istanbul ignore next */
|
99
70
|
const elements = await page.$x(xpath)
|
100
71
|
debug('Delete Button - click.')
|
72
|
+
await elements[0].hover()
|
101
73
|
await elements[0].click()
|
102
74
|
debug('Delete Button - clicked.')
|
103
75
|
await nav
|
@@ -108,6 +80,7 @@ module.exports = async (pluginConfig, context) => {
|
|
108
80
|
await page.waitForSelector(selector, selectorOpts)
|
109
81
|
debug('confirmation form loaded at %s', url)
|
110
82
|
nav = page.waitForNavigation(navOpts)
|
83
|
+
await page.hover(selector)
|
111
84
|
await page.click(selector)
|
112
85
|
await nav
|
113
86
|
|
@@ -121,9 +94,7 @@ module.exports = async (pluginConfig, context) => {
|
|
121
94
|
}
|
122
95
|
}
|
123
96
|
|
124
|
-
|
125
|
-
await browser.close()
|
126
|
-
}
|
97
|
+
await page.browser().close()
|
127
98
|
if (!success) {
|
128
99
|
return false
|
129
100
|
}
|
package/lib/get-error.js
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
const SemanticReleaseError = require('@semantic-release/error')
|
2
2
|
const ERROR_DEFINITIONS = require('./definitions/errors.js')
|
3
3
|
|
4
|
-
module.exports = code => {
|
4
|
+
module.exports = (code) => {
|
5
5
|
const { message, details } = ERROR_DEFINITIONS[code]()
|
6
6
|
return new SemanticReleaseError(message, code, details)
|
7
7
|
}
|
@@ -14,20 +14,22 @@ module.exports = async (pluginConfig, context) => {
|
|
14
14
|
} = context
|
15
15
|
|
16
16
|
debug('Getting releases from GitHub')
|
17
|
-
logger.
|
17
|
+
logger.log('Getting releases from GitHub')
|
18
18
|
|
19
19
|
const { githubREPO, githubTOKEN } = resolveConfig(context)
|
20
20
|
|
21
21
|
const gh = new GitHub({
|
22
22
|
token: githubTOKEN
|
23
23
|
})
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
githubReleases.
|
28
|
-
|
29
|
-
|
24
|
+
if (githubREPO) { // optional by default false
|
25
|
+
const repo = githubREPO.split('/')
|
26
|
+
const githubReleases = await gh.getRepo(repo[0], repo[1]).listReleases()
|
27
|
+
if (githubReleases.status === 200) {
|
28
|
+
githubReleases.data.forEach(r => logger.log(`Detected GitHub release ${r.name.substring(1)}`))
|
29
|
+
githubReleases.data.reverse()
|
30
|
+
return githubReleases.data
|
31
|
+
}
|
32
|
+
logger.log('Failed to get releases from GitHub')
|
30
33
|
}
|
31
|
-
logger.error('Failed to get releases from GitHub')
|
32
34
|
return false
|
33
35
|
}
|
package/lib/publish.js
CHANGED
@@ -1,13 +1,7 @@
|
|
1
|
-
const debug = require(
|
2
|
-
const resolveConfig = require(
|
3
|
-
const
|
4
|
-
const
|
5
|
-
waitUntil: ['load', 'domcontentloaded'],
|
6
|
-
timeout: 240000
|
7
|
-
}
|
8
|
-
const navOpts = { waitUntil: 'networkidle0', timeout: 240000 }
|
9
|
-
const selectorOpts = { timeout: 240000 }
|
10
|
-
const setCompatibleVersions = require('./set-compatible-versions')
|
1
|
+
const debug = require("debug")("semantic-release:whmcs");
|
2
|
+
const resolveConfig = require("./resolve-config");
|
3
|
+
const puppet = require("./puppet");
|
4
|
+
const setCompatibleVersions = require("./set-compatible-versions");
|
11
5
|
|
12
6
|
/**
|
13
7
|
* A method to publish the module update on whmcs market place
|
@@ -15,129 +9,127 @@ const setCompatibleVersions = require('./set-compatible-versions')
|
|
15
9
|
module.exports = async (pluginConfig, context) => {
|
16
10
|
const {
|
17
11
|
nextRelease: { notes, version, releaseDate },
|
18
|
-
logger
|
19
|
-
} = context
|
12
|
+
logger,
|
13
|
+
} = context;
|
20
14
|
|
21
15
|
if (!notes || !notes.length || !version || !version.length) {
|
22
|
-
debug(
|
23
|
-
logger.error(
|
16
|
+
debug("publishing new product version failed. No input data available.");
|
17
|
+
logger.error(
|
18
|
+
"WHMCS Marketplace publishing new product version failed. No input data available."
|
19
|
+
);
|
24
20
|
}
|
25
21
|
|
26
|
-
let success = true
|
27
|
-
const { whmcsLOGIN, whmcsPASSWORD, whmcsPRODUCTID, DEBUG } =
|
22
|
+
let success = true;
|
23
|
+
const { whmcsLOGIN, whmcsPASSWORD, whmcsPRODUCTID, DEBUG } =
|
24
|
+
resolveConfig(context);
|
25
|
+
const { gotoOpts, navOpts, selectorOpts, page } = await puppet(DEBUG, logger);
|
28
26
|
|
29
|
-
debug(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
|
30
|
-
logger.log(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`)
|
27
|
+
debug(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`);
|
28
|
+
logger.log(`WHMCS Marketplace Product ID: ${whmcsPRODUCTID}`);
|
31
29
|
|
32
|
-
debug(`Release Version: ${version}`)
|
33
|
-
logger.log(`Release Version: ${version}`)
|
34
|
-
debug(`Notes: ${notes}`)
|
35
|
-
logger.log(`Release Notes: ${notes}`)
|
30
|
+
debug(`Release Version: ${version}`);
|
31
|
+
logger.log(`Release Version: ${version}`);
|
32
|
+
debug(`Notes: ${notes}`);
|
33
|
+
logger.log(`Release Notes: ${notes}`);
|
36
34
|
|
37
35
|
// strip markdown links from notes as not allowed to keep
|
38
|
-
const cleanedNotes = notes.replace(/\[(
|
39
|
-
const wmbase =
|
40
|
-
let url = `${wmbase}/user/login
|
41
|
-
const browser = await puppeteer.launch({
|
42
|
-
headless: !DEBUG,
|
43
|
-
defaultViewport: null, // automatically full-sized
|
44
|
-
args: [
|
45
|
-
'--incognito',
|
46
|
-
'--start-maximized',
|
47
|
-
'--no-sandbox',
|
48
|
-
'--disable-setuid-sandbox',
|
49
|
-
'--disable-infobars',
|
50
|
-
'--ignore-certifcate-errors',
|
51
|
-
'--ignore-certifcate-errors-spki-list',
|
52
|
-
'--ignoreHTTPSErrors=true',
|
53
|
-
'--user-agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36"'
|
54
|
-
]
|
55
|
-
})
|
56
|
-
const [page] = await browser.pages()
|
36
|
+
const cleanedNotes = notes.replace(/\[([^\]]*?)\]\(([^)]+?)\)/gm, "$1");
|
37
|
+
const wmbase = "https://marketplace.whmcs.com";
|
38
|
+
let url = `${wmbase}/user/login`;
|
57
39
|
|
58
40
|
try {
|
59
|
-
await page.
|
60
|
-
page.on('request', request => {
|
61
|
-
if (/^(image|stylesheet|other)$/i.test(request.resourceType())) {
|
62
|
-
request.abort()
|
63
|
-
} else {
|
64
|
-
request.continue()
|
65
|
-
}
|
66
|
-
})
|
67
|
-
|
68
|
-
await page.setJavaScriptEnabled(true)
|
69
|
-
await page.goto(url, gotoOpts)
|
41
|
+
await page.goto(url, gotoOpts);
|
70
42
|
// do login
|
71
|
-
const selector = 'div.login-leftcol form button[type="submit"]'
|
72
|
-
await page.waitForSelector(selector, selectorOpts)
|
73
|
-
debug(
|
74
|
-
await page.type(
|
75
|
-
await page.type(
|
76
|
-
debug(
|
77
|
-
const nav = page.waitForNavigation(navOpts)
|
78
|
-
await page.
|
79
|
-
await
|
80
|
-
|
81
|
-
|
43
|
+
const selector = 'div.login-leftcol form button[type="submit"]';
|
44
|
+
await page.waitForSelector(selector, selectorOpts);
|
45
|
+
debug("login form loaded at %s", url);
|
46
|
+
await page.type("#email", whmcsLOGIN);
|
47
|
+
await page.type("#password", whmcsPASSWORD);
|
48
|
+
debug("WHMCS Marketplace credentials entered");
|
49
|
+
const nav = page.waitForNavigation(navOpts);
|
50
|
+
await page.hover(selector);
|
51
|
+
await page.click(selector);
|
52
|
+
await nav;
|
53
|
+
debug("Login form successfully submitted.");
|
54
|
+
logger.log("WHMCS Marketplace Login Form successfully submitted.");
|
82
55
|
} catch (error) {
|
83
|
-
debug(
|
84
|
-
logger.error(
|
85
|
-
success = false
|
56
|
+
debug("WHMCS Marketplace login failed.", error.message);
|
57
|
+
logger.error("WHMCS Marketplace login failed.", error.message);
|
58
|
+
success = false;
|
86
59
|
}
|
87
60
|
if (success) {
|
88
61
|
try {
|
89
62
|
if (!parseInt(whmcsPRODUCTID, 10)) {
|
90
|
-
return false
|
63
|
+
return false;
|
91
64
|
}
|
92
65
|
// add new version
|
93
|
-
url = `${wmbase}/product/${whmcsPRODUCTID}/versions/new
|
94
|
-
await page.goto(url, gotoOpts)
|
95
|
-
debug(
|
96
|
-
const selector = 'div.listing-edit-container form button[type="submit"]'
|
97
|
-
await page.waitForSelector(selector, selectorOpts)
|
98
|
-
debug(
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
66
|
+
url = `${wmbase}/product/${whmcsPRODUCTID}/versions/new`;
|
67
|
+
await page.goto(url, gotoOpts);
|
68
|
+
debug("product page loaded at %s", url);
|
69
|
+
const selector = 'div.listing-edit-container form button[type="submit"]';
|
70
|
+
await page.waitForSelector(selector, selectorOpts);
|
71
|
+
debug("product page submit button selector found");
|
72
|
+
/* istanbul ignore next */
|
73
|
+
await page.$eval(
|
74
|
+
"#version",
|
75
|
+
(el, value) => {
|
76
|
+
el.value = value;
|
77
|
+
},
|
78
|
+
version
|
79
|
+
);
|
80
|
+
debug("form input for version finished.");
|
103
81
|
|
104
82
|
// fill input type date with localized string
|
105
83
|
// https://www.mattzeunert.com/2020/04/01/filling-out-a-date-input-with-puppeteer.html
|
106
|
-
const date = releaseDate ? new Date(releaseDate) : new Date()
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
84
|
+
const date = releaseDate ? new Date(releaseDate) : new Date();
|
85
|
+
/* istanbul ignore next */
|
86
|
+
const dateString = await page.evaluate(
|
87
|
+
(d) =>
|
88
|
+
new Date(d).toLocaleDateString(navigator.language, {
|
89
|
+
day: "2-digit",
|
90
|
+
month: "2-digit",
|
91
|
+
year: "numeric",
|
92
|
+
}),
|
93
|
+
date.toISOString()
|
94
|
+
);
|
95
|
+
await page.type("#released_at", dateString);
|
113
96
|
|
114
|
-
debug(
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
97
|
+
debug("form input for released_at finished.");
|
98
|
+
/* istanbul ignore next */
|
99
|
+
await page.$eval(
|
100
|
+
"#description",
|
101
|
+
(el, value) => {
|
102
|
+
el.value = value;
|
103
|
+
},
|
104
|
+
cleanedNotes
|
105
|
+
);
|
106
|
+
debug("form input for description finished.");
|
107
|
+
const nav = page.waitForNavigation(navOpts);
|
108
|
+
await page.hover(selector);
|
109
|
+
await page.click(selector);
|
110
|
+
await nav;
|
122
111
|
|
123
|
-
await setCompatibleVersions(pluginConfig, context)
|
112
|
+
await setCompatibleVersions(pluginConfig, context);
|
124
113
|
|
125
|
-
debug(
|
126
|
-
logger.log(
|
127
|
-
success = true
|
114
|
+
debug("publishing new product version succeeded.");
|
115
|
+
logger.log("WHMCS Marketplace publishing new product version succeeded.");
|
116
|
+
success = true;
|
128
117
|
} catch (error) {
|
129
|
-
debug(
|
130
|
-
logger.error(
|
131
|
-
|
118
|
+
debug("publishing new product version failed.", error.message);
|
119
|
+
logger.error(
|
120
|
+
"WHMCS Marketplace publishing new product version failed.",
|
121
|
+
error.message
|
122
|
+
);
|
123
|
+
success = false;
|
132
124
|
}
|
133
125
|
}
|
134
126
|
|
135
|
-
await browser.close()
|
127
|
+
await page.browser().close();
|
136
128
|
if (!success) {
|
137
|
-
return false
|
129
|
+
return false;
|
138
130
|
}
|
139
131
|
return {
|
140
|
-
name:
|
141
|
-
url: `${wmbase}/product/${whmcsPRODUCTID}
|
142
|
-
}
|
143
|
-
}
|
132
|
+
name: "WHMCS Marketplace Product Version",
|
133
|
+
url: `${wmbase}/product/${whmcsPRODUCTID}`,
|
134
|
+
};
|
135
|
+
};
|