@ixon-cdk/core 1.0.0-alpha.1 → 1.0.0-alpha.13
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/api/auth.service.js +21 -20
- package/api/base.service.js +8 -8
- package/api/deploy.service.js +97 -29
- package/config/config.service.js +15 -15
- package/config/schema.d.ts +2 -0
- package/config/schema.json +7 -0
- package/http-request.js +28 -0
- package/index.js +8 -8
- package/meta-files.js +81 -14
- package/package.json +4 -2
- package/prompts.js +10 -10
- package/server/index.js +34 -36
- package/template/template.service.js +33 -27
- package/utils.js +44 -29
package/api/auth.service.js
CHANGED
|
@@ -1,30 +1,31 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const
|
|
3
|
-
const
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const ApiBaseService = require('./base.service');
|
|
3
|
+
const httpRequest = require('../http-request');
|
|
4
4
|
|
|
5
5
|
module.exports = class AuthService extends ApiBaseService {
|
|
6
6
|
logIn(credentials) {
|
|
7
7
|
const c = credentials;
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
{
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
);
|
|
8
|
+
return httpRequest({
|
|
9
|
+
method: 'POST',
|
|
10
|
+
url: `${this._getApiBaseUrl()}/access-tokens`,
|
|
11
|
+
data: { expiresIn: 86400 },
|
|
12
|
+
headers: {
|
|
13
|
+
...this._getApiDefaultHeaders(),
|
|
14
|
+
'User-Agent': 'ComponentDevKit',
|
|
15
|
+
Authorization: `Basic ${Buffer.from(
|
|
16
|
+
`${c.email}:${c.otp || ''}:${c.password}`,
|
|
17
|
+
'utf-8',
|
|
18
|
+
).toString('base64')}`,
|
|
19
|
+
},
|
|
20
|
+
});
|
|
22
21
|
}
|
|
23
22
|
|
|
24
23
|
logOut() {
|
|
25
24
|
const secretId = this._getSecretId();
|
|
26
25
|
if (secretId) {
|
|
27
|
-
return
|
|
26
|
+
return httpRequest({
|
|
27
|
+
method: 'DELETE',
|
|
28
|
+
url: `${this._getApiBaseUrl()}/access-tokens/me`,
|
|
28
29
|
headers: {
|
|
29
30
|
...this._getApiDefaultHeaders(),
|
|
30
31
|
Authorization: this._getApiAuthHeaderValue(),
|
|
@@ -40,8 +41,8 @@ module.exports = class AuthService extends ApiBaseService {
|
|
|
40
41
|
|
|
41
42
|
remember(secretId) {
|
|
42
43
|
fs.writeFileSync(this._getAccessTokenFilePath(), secretId, {
|
|
43
|
-
encoding:
|
|
44
|
-
flag:
|
|
44
|
+
encoding: 'utf8',
|
|
45
|
+
flag: 'w',
|
|
45
46
|
});
|
|
46
47
|
}
|
|
47
48
|
|
package/api/base.service.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const ConfigService = require(
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const ConfigService = require('../config/config.service');
|
|
4
4
|
|
|
5
5
|
module.exports = class ApiBaseService {
|
|
6
6
|
_configSrv = new ConfigService();
|
|
7
7
|
|
|
8
8
|
_getAccessTokenFilePath() {
|
|
9
|
-
return path.join(
|
|
9
|
+
return path.join(require('../utils').getRootDir(), '.accesstoken');
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
_getApiAuthHeaderValue() {
|
|
@@ -19,9 +19,9 @@ module.exports = class ApiBaseService {
|
|
|
19
19
|
|
|
20
20
|
_getApiDefaultHeaders() {
|
|
21
21
|
return {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
22
|
+
'Content-Type': 'application/json',
|
|
23
|
+
'Api-Application': this._configSrv.getApiApplication(),
|
|
24
|
+
'Api-Version': this._configSrv.getApiVersion(),
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -29,7 +29,7 @@ module.exports = class ApiBaseService {
|
|
|
29
29
|
let secretId;
|
|
30
30
|
try {
|
|
31
31
|
secretId = fs.readFileSync(this._getAccessTokenFilePath(), {
|
|
32
|
-
encoding:
|
|
32
|
+
encoding: 'utf-8',
|
|
33
33
|
});
|
|
34
34
|
} catch {
|
|
35
35
|
// do nothing
|
package/api/deploy.service.js
CHANGED
|
@@ -1,44 +1,65 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const
|
|
4
|
-
const
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const ApiBaseService = require('./base.service');
|
|
4
|
+
const httpRequest = require('../http-request');
|
|
5
5
|
|
|
6
6
|
module.exports = class DeployService extends ApiBaseService {
|
|
7
7
|
deploy(companyId, templateId, file) {
|
|
8
8
|
const url = `${this._getApiBaseUrl()}/page-component-templates/${templateId}/version-upload`;
|
|
9
|
-
const body = fs.readFileSync(path.join(
|
|
9
|
+
const body = fs.readFileSync(path.join(require('../utils').getRootDir(), file));
|
|
10
10
|
const headers = {
|
|
11
11
|
...this._getApiDefaultHeaders(),
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
13
|
+
'Api-Company': companyId,
|
|
14
14
|
Authorization: this._getApiAuthHeaderValue(),
|
|
15
15
|
};
|
|
16
|
-
return
|
|
16
|
+
return httpRequest({ method: 'POST', url, data: body, headers }).then((res) => res.data.data);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
deployAndPublish(companyId, templateId, file) {
|
|
20
20
|
return this.deploy(companyId, templateId, file).then((data) =>
|
|
21
|
-
this._publish(companyId, data.publicId)
|
|
21
|
+
this._publish(companyId, data.publicId),
|
|
22
22
|
);
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
fetchPublishable(companyId, templateId) {
|
|
26
26
|
return this._fetchDescTemplateVersions(companyId, templateId).then((versions) => {
|
|
27
|
-
const publishedIdx = versions.findIndex(
|
|
28
|
-
(v) => typeof v.publishedOn === "string"
|
|
29
|
-
);
|
|
27
|
+
const publishedIdx = versions.findIndex((v) => typeof v.publishedOn === 'string');
|
|
30
28
|
return publishedIdx !== -1 ? versions.slice(0, publishedIdx) : versions;
|
|
31
29
|
});
|
|
32
30
|
}
|
|
33
31
|
|
|
32
|
+
generatePreviewLink(companyId, versionId) {
|
|
33
|
+
return Promise.all([
|
|
34
|
+
this._fetchBrandingFqdn(companyId),
|
|
35
|
+
this._fetchTemplateVersion(companyId, versionId),
|
|
36
|
+
])
|
|
37
|
+
.then(([fqdn, version]) =>
|
|
38
|
+
this._fetchTemplate(companyId, version.template.publicId).then((template) => [
|
|
39
|
+
fqdn,
|
|
40
|
+
version,
|
|
41
|
+
template,
|
|
42
|
+
]),
|
|
43
|
+
)
|
|
44
|
+
.then(([fqdn, version, template]) => {
|
|
45
|
+
const hash = require('../utils').generatePreviewHash(
|
|
46
|
+
template.publicId,
|
|
47
|
+
template.name,
|
|
48
|
+
version.publicId,
|
|
49
|
+
version.number,
|
|
50
|
+
version.mainPath,
|
|
51
|
+
);
|
|
52
|
+
const search = `?pctpvw=${encodeURIComponent(hash)}`;
|
|
53
|
+
return `https://${fqdn || '[YOUR-PLATFORM-DOMAIN]'}/portal/${search}`;
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
34
57
|
publishLatestVersion(companyId, templateId) {
|
|
35
58
|
return this.fetchPublishable(companyId, templateId).then((data) => {
|
|
36
59
|
if (!data.length) {
|
|
37
|
-
return Promise.reject(
|
|
60
|
+
return Promise.reject('Template has no publishable versions');
|
|
38
61
|
}
|
|
39
|
-
const latest = data.sort(
|
|
40
|
-
(v1, v2) => Number(v2.number) - Number(v1.number)
|
|
41
|
-
)[0];
|
|
62
|
+
const latest = data.sort((v1, v2) => Number(v2.number) - Number(v1.number))[0];
|
|
42
63
|
return this._publish(companyId, latest.publicId);
|
|
43
64
|
});
|
|
44
65
|
}
|
|
@@ -46,33 +67,80 @@ module.exports = class DeployService extends ApiBaseService {
|
|
|
46
67
|
publishVersion(companyId, templateId, versionNumber) {
|
|
47
68
|
return this.fetchPublishable(companyId, templateId).then((data) => {
|
|
48
69
|
if (!data.length) {
|
|
49
|
-
return Promise.reject(
|
|
70
|
+
return Promise.reject('Template has no publishable versions');
|
|
50
71
|
}
|
|
51
72
|
const _version = data.find((v) => v.number === String(versionNumber));
|
|
52
|
-
if (
|
|
73
|
+
if (_version) {
|
|
53
74
|
return this._publish(companyId, _version.publicId);
|
|
54
75
|
}
|
|
55
|
-
return Promise.reject(
|
|
76
|
+
return Promise.reject('Could not match!');
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
_fetchBrandingFqdn(companyId) {
|
|
81
|
+
const url = `${this._getApiBaseUrl()}/companies/me`;
|
|
82
|
+
const params = { fields: 'branding(fqdn)' };
|
|
83
|
+
const headers = {
|
|
84
|
+
...this._getApiDefaultHeaders(),
|
|
85
|
+
'Api-Company': companyId,
|
|
86
|
+
Authorization: this._getApiAuthHeaderValue(),
|
|
87
|
+
};
|
|
88
|
+
// Lookup company FQDN (premium branding)
|
|
89
|
+
return httpRequest({ method: 'GET', url, params, headers }).then((res) => {
|
|
90
|
+
const myCompany = res.data.data;
|
|
91
|
+
if (myCompany.branding && myCompany.branding.fqdn) {
|
|
92
|
+
return myCompany.branding.fqdn;
|
|
93
|
+
}
|
|
94
|
+
// Or fallback to sector FQDN
|
|
95
|
+
const _url = `${this._getApiBaseUrl()}/sectors/me`;
|
|
96
|
+
const _headers = { ...this._getApiDefaultHeaders() };
|
|
97
|
+
return httpRequest({ method: 'GET', url: _url, params, headers: _headers }).then((res) => {
|
|
98
|
+
const mySector = res.data.data;
|
|
99
|
+
if (mySector.branding && mySector.branding.fqdn) {
|
|
100
|
+
return mySector.branding.fqdn;
|
|
101
|
+
}
|
|
102
|
+
return null;
|
|
103
|
+
});
|
|
56
104
|
});
|
|
57
105
|
}
|
|
58
106
|
|
|
59
107
|
_fetchDescTemplateVersions(companyId, templateId) {
|
|
60
108
|
const url = `${this._getApiBaseUrl()}/page-component-template-versions`;
|
|
61
109
|
const params = {
|
|
62
|
-
fields:
|
|
110
|
+
fields: '*,template(*)',
|
|
63
111
|
filters: `eq(template.publicId,"${templateId}")`,
|
|
64
|
-
|
|
112
|
+
'page-size': '100',
|
|
65
113
|
};
|
|
66
114
|
const headers = {
|
|
67
115
|
...this._getApiDefaultHeaders(),
|
|
68
|
-
|
|
116
|
+
'Api-Company': companyId,
|
|
69
117
|
Authorization: this._getApiAuthHeaderValue(),
|
|
70
118
|
};
|
|
71
|
-
return
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
119
|
+
return httpRequest({ method: 'GET', url, params, headers }).then((res) =>
|
|
120
|
+
res.data.data.sort((v1, v2) => Number(v2.number) - Number(v1.number)),
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
_fetchTemplate(companyId, templateId) {
|
|
125
|
+
const url = `${this._getApiBaseUrl()}/page-component-templates/${templateId}`;
|
|
126
|
+
const params = { fields: '*' };
|
|
127
|
+
const headers = {
|
|
128
|
+
...this._getApiDefaultHeaders(),
|
|
129
|
+
'Api-Company': companyId,
|
|
130
|
+
Authorization: this._getApiAuthHeaderValue(),
|
|
131
|
+
};
|
|
132
|
+
return httpRequest({ method: 'GET', url, params, headers }).then((res) => res.data.data);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
_fetchTemplateVersion(companyId, versionId) {
|
|
136
|
+
const url = `${this._getApiBaseUrl()}/page-component-template-versions/${versionId}`;
|
|
137
|
+
const params = { fields: '*,template(*)' };
|
|
138
|
+
const headers = {
|
|
139
|
+
...this._getApiDefaultHeaders(),
|
|
140
|
+
'Api-Company': companyId,
|
|
141
|
+
Authorization: this._getApiAuthHeaderValue(),
|
|
142
|
+
};
|
|
143
|
+
return httpRequest({ method: 'GET', url, params, headers }).then((res) => res.data.data);
|
|
76
144
|
}
|
|
77
145
|
|
|
78
146
|
_publish(companyId, versionId) {
|
|
@@ -80,9 +148,9 @@ module.exports = class DeployService extends ApiBaseService {
|
|
|
80
148
|
const body = { published: true };
|
|
81
149
|
const headers = {
|
|
82
150
|
...this._getApiDefaultHeaders(),
|
|
83
|
-
|
|
151
|
+
'Api-Company': companyId,
|
|
84
152
|
Authorization: this._getApiAuthHeaderValue(),
|
|
85
153
|
};
|
|
86
|
-
return
|
|
154
|
+
return httpRequest({ method: 'PATCH', url, data: body, headers });
|
|
87
155
|
}
|
|
88
156
|
};
|
package/config/config.service.js
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const { merge } = require(
|
|
3
|
-
const path = require(
|
|
4
|
-
const { logFileCrudMessage, logErrorMessage } = require(
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const { merge } = require('lodash');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { getRootDir, logFileCrudMessage, logErrorMessage } = require('../utils');
|
|
5
5
|
|
|
6
6
|
module.exports = class ConfigService {
|
|
7
7
|
_config = { components: {} };
|
|
8
8
|
|
|
9
|
-
_path = path.join(
|
|
9
|
+
_path = path.join(getRootDir(), 'config.json');
|
|
10
10
|
|
|
11
11
|
constructor() {
|
|
12
12
|
let config;
|
|
13
13
|
|
|
14
14
|
if (!fs.existsSync(this._path)) {
|
|
15
|
-
logErrorMessage(
|
|
15
|
+
logErrorMessage('No config file.');
|
|
16
16
|
process.exit();
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
try {
|
|
20
20
|
config = require(this._path);
|
|
21
21
|
} catch {
|
|
22
|
-
logErrorMessage(
|
|
22
|
+
logErrorMessage('Couldn\'t parse config file.');
|
|
23
23
|
process.exit();
|
|
24
24
|
}
|
|
25
25
|
|
|
@@ -43,15 +43,15 @@ module.exports = class ConfigService {
|
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
getApiApplication() {
|
|
46
|
-
return this._config.apiApplication ||
|
|
46
|
+
return this._config.apiApplication || 'LtDdZKEPa5lK';
|
|
47
47
|
}
|
|
48
48
|
|
|
49
49
|
getApiBaseUrl() {
|
|
50
|
-
return this._config.apiBaseUrl ||
|
|
50
|
+
return this._config.apiBaseUrl || 'https://api.ayayot.com';
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
getApiVersion() {
|
|
54
|
-
return this._config.apiVersion ||
|
|
54
|
+
return this._config.apiVersion || '2';
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
addComponent(name, config) {
|
|
@@ -63,16 +63,16 @@ module.exports = class ConfigService {
|
|
|
63
63
|
this._config.components[name] = merge(
|
|
64
64
|
{},
|
|
65
65
|
this._config.components[name],
|
|
66
|
-
config
|
|
66
|
+
config,
|
|
67
67
|
);
|
|
68
68
|
this._sync();
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
_sync() {
|
|
72
|
-
fs.writeFileSync(this._path, JSON.stringify(this._config, null, 2)
|
|
73
|
-
encoding:
|
|
74
|
-
flag:
|
|
72
|
+
fs.writeFileSync(this._path, `${JSON.stringify(this._config, null, 2)}\n`, {
|
|
73
|
+
encoding: 'utf8',
|
|
74
|
+
flag: 'w',
|
|
75
75
|
});
|
|
76
|
-
logFileCrudMessage(
|
|
76
|
+
logFileCrudMessage('UPDATE', 'config.json');
|
|
77
77
|
}
|
|
78
78
|
};
|
package/config/schema.d.ts
CHANGED
package/config/schema.json
CHANGED
package/http-request.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const axios = require('axios');
|
|
4
|
+
const { getRootDir, logErrorMessage } = require('./utils');
|
|
5
|
+
|
|
6
|
+
module.exports = function request(options) {
|
|
7
|
+
const customPath = path.join(getRootDir(), 'http-request.js');
|
|
8
|
+
|
|
9
|
+
if (fs.existsSync(customPath)) {
|
|
10
|
+
const customRequest = require(customPath);
|
|
11
|
+
|
|
12
|
+
if (typeof customRequest !== 'function') {
|
|
13
|
+
logErrorMessage('The custom "http-request.js" file must export a function.');
|
|
14
|
+
process.exit();
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const promise = customRequest(options);
|
|
18
|
+
|
|
19
|
+
if (typeof promise !== 'object' || typeof promise.then !== 'function') {
|
|
20
|
+
logErrorMessage('The exported function in the custom "http-request.js" file must return a Promise.');
|
|
21
|
+
process.exit();
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return promise;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return axios.request(options);
|
|
28
|
+
};
|
package/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
AuthService: require(
|
|
3
|
-
DeployService: require(
|
|
4
|
-
ConfigService: require(
|
|
5
|
-
Server: require(
|
|
6
|
-
TemplateService: require(
|
|
7
|
-
...require(
|
|
8
|
-
...require(
|
|
9
|
-
...require(
|
|
2
|
+
AuthService: require('./api/auth.service'),
|
|
3
|
+
DeployService: require('./api/deploy.service'),
|
|
4
|
+
ConfigService: require('./config/config.service'),
|
|
5
|
+
Server: require('./server'),
|
|
6
|
+
TemplateService: require('./template/template.service'),
|
|
7
|
+
...require('./meta-files'),
|
|
8
|
+
...require('./prompts'),
|
|
9
|
+
...require('./utils'),
|
|
10
10
|
};
|
package/meta-files.js
CHANGED
|
@@ -1,22 +1,84 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { debounce, uniq } = require('lodash');
|
|
4
|
+
const rimraf = require('rimraf');
|
|
3
5
|
|
|
4
|
-
const ICON_FILE_NAME =
|
|
5
|
-
const MANIFEST_FILE_NAME =
|
|
6
|
+
const ICON_FILE_NAME = 'icon.svg';
|
|
7
|
+
const MANIFEST_FILE_NAME = 'manifest.json';
|
|
8
|
+
const WATCH_OPTIONS = {
|
|
9
|
+
cwd: require('./utils').getRootDir(),
|
|
10
|
+
usePolling: process.platform !== 'darwin',
|
|
11
|
+
};
|
|
6
12
|
|
|
7
13
|
module.exports = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
cleanDir(dir) {
|
|
15
|
+
if (fs.existsSync(dir)) {
|
|
16
|
+
rimraf.sync(dir);
|
|
17
|
+
}
|
|
18
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
19
|
+
},
|
|
20
|
+
copyAssets(assets, inputDir, outputDir) {
|
|
21
|
+
const paths = uniq([MANIFEST_FILE_NAME, ICON_FILE_NAME, ...assets]).map((asset) =>
|
|
22
|
+
path.join(inputDir, asset),
|
|
23
|
+
);
|
|
24
|
+
paths.forEach((_path) => {
|
|
25
|
+
require('glob')
|
|
26
|
+
.sync(_path)
|
|
27
|
+
.forEach((file) => {
|
|
28
|
+
const fileName = file.slice(inputDir.length + 1);
|
|
29
|
+
_copyFileNameFromToSync(fileName, inputDir, outputDir);
|
|
30
|
+
});
|
|
11
31
|
});
|
|
12
32
|
},
|
|
13
|
-
|
|
14
|
-
require(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
watchAssets(assets, inputDir, outputDir) {
|
|
34
|
+
const root = require('./utils').getRootDir();
|
|
35
|
+
return require('chokidar')
|
|
36
|
+
.watch(
|
|
37
|
+
uniq([MANIFEST_FILE_NAME, ICON_FILE_NAME, ...assets]).map((asset) =>
|
|
38
|
+
path.join(inputDir, asset),
|
|
39
|
+
),
|
|
40
|
+
WATCH_OPTIONS,
|
|
41
|
+
)
|
|
42
|
+
.on('all', (type, file) => {
|
|
43
|
+
const fileName = path.join(root, file).slice(inputDir.length + 1);
|
|
44
|
+
switch (type) {
|
|
45
|
+
case 'add':
|
|
46
|
+
case 'change':
|
|
47
|
+
_copyFileNameFromToSync(fileName, inputDir, outputDir);
|
|
48
|
+
break;
|
|
49
|
+
case 'unlink':
|
|
50
|
+
if (fs.existsSync(path.join(outputDir, fileName))) {
|
|
51
|
+
rimraf.sync(path.join(outputDir, fileName));
|
|
52
|
+
}
|
|
53
|
+
break;
|
|
54
|
+
default:
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
},
|
|
59
|
+
watchInputDir(dir, watchCallback) {
|
|
60
|
+
const _debouncedCallback = debounce(() => watchCallback(), 300);
|
|
61
|
+
require('chokidar')
|
|
62
|
+
.watch([`${dir}/**`], WATCH_OPTIONS)
|
|
63
|
+
.on('all', (_, _path) => {
|
|
64
|
+
if (
|
|
65
|
+
_path.endsWith(path.join(dir, MANIFEST_FILE_NAME)) ||
|
|
66
|
+
_path.endsWith(path.join(dir, ICON_FILE_NAME))
|
|
67
|
+
) {
|
|
68
|
+
watchCallback(true);
|
|
69
|
+
} else {
|
|
70
|
+
_debouncedCallback();
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
},
|
|
74
|
+
writeDemoFile: function writeDemoFile(tag, outputDir, outputFile) {
|
|
75
|
+
const demoFileContent = `<meta charset="utf-8">\n<title>${tag} demo</title>\n<script src="./${path.basename(
|
|
76
|
+
outputFile,
|
|
77
|
+
)}"></script>\n\n\n<${tag}></${tag}>\n\n`;
|
|
78
|
+
fs.writeFileSync(`${outputDir}/demo.html`, demoFileContent, {
|
|
79
|
+
encoding: 'utf8',
|
|
80
|
+
flag: 'w',
|
|
81
|
+
});
|
|
20
82
|
},
|
|
21
83
|
};
|
|
22
84
|
|
|
@@ -27,6 +89,11 @@ function _copyFileNameFromToSync(fileName, sourceDir, destDir) {
|
|
|
27
89
|
if (!fs.existsSync(destDir)) {
|
|
28
90
|
fs.mkdirSync(destDir, { recursive: true });
|
|
29
91
|
}
|
|
92
|
+
if (!fs.existsSync(path.dirname(path.join(destDir, fileName)))) {
|
|
93
|
+
fs.mkdirSync(path.dirname(path.join(destDir, fileName)), {
|
|
94
|
+
recursive: true,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
30
97
|
fs.copyFileSync(sourceFile, destFile);
|
|
31
98
|
}
|
|
32
99
|
}
|
package/package.json
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ixon-cdk/core",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.13",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"author": "",
|
|
7
7
|
"license": "ISC",
|
|
8
8
|
"dependencies": {
|
|
9
|
+
"app-root-dir": "^1.0.2",
|
|
9
10
|
"archiver": "^5.3.0",
|
|
10
11
|
"axios": "^0.21.4",
|
|
11
12
|
"chalk": "^4.1.2",
|
|
12
13
|
"chokidar": "^3.5.2",
|
|
13
|
-
"
|
|
14
|
+
"crypto-js": "^4.1.1",
|
|
14
15
|
"express": "^4.17.1",
|
|
16
|
+
"glob": "^7.2.0",
|
|
15
17
|
"livereload": "^0.9.3",
|
|
16
18
|
"lodash": "^4.17.21",
|
|
17
19
|
"opener": "^1.5.2",
|
package/prompts.js
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
1
|
module.exports = {
|
|
2
|
-
promptCompanyId
|
|
2
|
+
promptCompanyId(name) {
|
|
3
3
|
return {
|
|
4
|
-
type:
|
|
4
|
+
type: 'text',
|
|
5
5
|
name,
|
|
6
|
-
message:
|
|
6
|
+
message: 'What is the ID of your Company?',
|
|
7
7
|
validate: (value) => {
|
|
8
8
|
if (!value) {
|
|
9
|
-
return
|
|
9
|
+
return 'Company ID is required.';
|
|
10
10
|
}
|
|
11
11
|
if (!/^[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}-[0-9]{4}$/.test(value)) {
|
|
12
|
-
return
|
|
12
|
+
return 'Invalid company ID.';
|
|
13
13
|
}
|
|
14
14
|
return true;
|
|
15
15
|
},
|
|
16
16
|
};
|
|
17
17
|
},
|
|
18
|
-
promptPageComponentTemplateId
|
|
18
|
+
promptPageComponentTemplateId(name) {
|
|
19
19
|
return {
|
|
20
|
-
type:
|
|
20
|
+
type: 'text',
|
|
21
21
|
name,
|
|
22
|
-
message:
|
|
22
|
+
message: 'What is the ID of the PageComponentTemplate?',
|
|
23
23
|
validate: (value) => {
|
|
24
24
|
if (!value) {
|
|
25
|
-
return
|
|
25
|
+
return 'Template ID is required.';
|
|
26
26
|
}
|
|
27
27
|
if (!/^[a-zA-Z0-9]{12}$/.test(value)) {
|
|
28
|
-
return
|
|
28
|
+
return 'Invalid template ID.';
|
|
29
29
|
}
|
|
30
30
|
return true;
|
|
31
31
|
},
|
package/server/index.js
CHANGED
|
@@ -1,31 +1,33 @@
|
|
|
1
|
-
const path = require(
|
|
2
|
-
const express = require(
|
|
3
|
-
const ConfigService = require(
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const express = require('express');
|
|
3
|
+
const ConfigService = require('../config/config.service');
|
|
4
4
|
|
|
5
5
|
module.exports = class Server {
|
|
6
6
|
constructor(opts) {
|
|
7
7
|
this._configSrv = new ConfigService();
|
|
8
|
-
this.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
this._rootDir = require('../utils').getRootDir();
|
|
9
|
+
this._opts = {
|
|
10
|
+
port: 8000,
|
|
11
|
+
componentBasePath: 'components',
|
|
12
|
+
...opts,
|
|
13
|
+
};
|
|
12
14
|
}
|
|
13
15
|
|
|
14
16
|
serve(names) {
|
|
15
17
|
const app = express();
|
|
16
18
|
|
|
17
19
|
// Cache
|
|
18
|
-
app.use(
|
|
19
|
-
res.header(
|
|
20
|
+
app.use((_, res, next) => {
|
|
21
|
+
res.header('Cache-Control', 'no-store');
|
|
20
22
|
next();
|
|
21
23
|
});
|
|
22
24
|
|
|
23
25
|
// CORS
|
|
24
|
-
app.use(
|
|
25
|
-
res.header(
|
|
26
|
+
app.use((_, res, next) => {
|
|
27
|
+
res.header('Access-Control-Allow-Origin', '*');
|
|
26
28
|
res.header(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
'Access-Control-Allow-Headers',
|
|
30
|
+
'Origin, X-Requested-With, Content-Type, Accept',
|
|
29
31
|
);
|
|
30
32
|
next();
|
|
31
33
|
});
|
|
@@ -35,36 +37,32 @@ module.exports = class Server {
|
|
|
35
37
|
names.forEach((name) => {
|
|
36
38
|
const outputDir = this._getOutputDir(name);
|
|
37
39
|
if (outputDir) {
|
|
38
|
-
const dir = path.resolve(
|
|
40
|
+
const dir = path.resolve(this._rootDir, outputDir);
|
|
39
41
|
app.use(
|
|
40
42
|
`/${this._opts.componentBasePath}/${name}`,
|
|
41
|
-
express.static(dir)
|
|
43
|
+
express.static(dir),
|
|
42
44
|
);
|
|
43
45
|
}
|
|
44
46
|
});
|
|
45
47
|
}
|
|
46
48
|
|
|
47
49
|
// Adds live reload watchers
|
|
48
|
-
const lrServer = require(
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
process.on("exit", () => {
|
|
58
|
-
lrServer.close();
|
|
59
|
-
watcher.close();
|
|
60
|
-
});
|
|
50
|
+
const lrServer = require('livereload').createServer();
|
|
51
|
+
const _refresh = () => lrServer.refresh('/');
|
|
52
|
+
const _debouncedRefresh = require('lodash/debounce')(_refresh, 250);
|
|
53
|
+
names
|
|
54
|
+
.flatMap((name) => [
|
|
55
|
+
[path.join(this._rootDir, this._getOutput(name)), 100],
|
|
56
|
+
[path.join(this._rootDir, `dist/${name}/manifest.json`), 500],
|
|
57
|
+
])
|
|
58
|
+
.forEach(([filename, interval]) => require('fs').watchFile(filename, { interval }, _debouncedRefresh));
|
|
61
59
|
|
|
62
60
|
// Simulator app
|
|
63
|
-
const appDir = path.dirname(require.resolve(
|
|
64
|
-
app.get(`/${this._opts.componentBasePath}/*`,
|
|
61
|
+
const appDir = path.dirname(require.resolve('@ixon-cdk/simulator'));
|
|
62
|
+
app.get(`/${this._opts.componentBasePath}/*`, (req, res) => {
|
|
65
63
|
res.sendStatus(404);
|
|
66
64
|
});
|
|
67
|
-
app.get(
|
|
65
|
+
app.get('/config.json', (req, res) => {
|
|
68
66
|
res.send({
|
|
69
67
|
api: {
|
|
70
68
|
appId: this._configSrv.getApiApplication(),
|
|
@@ -73,9 +71,9 @@ module.exports = class Server {
|
|
|
73
71
|
},
|
|
74
72
|
});
|
|
75
73
|
});
|
|
76
|
-
app.get(
|
|
77
|
-
app.all(
|
|
78
|
-
res.status(200).sendFile(
|
|
74
|
+
app.get('*.*', express.static(appDir));
|
|
75
|
+
app.all('*', (req, res) => {
|
|
76
|
+
res.status(200).sendFile('/index.html', { root: appDir });
|
|
79
77
|
});
|
|
80
78
|
|
|
81
79
|
app.listen(this._opts.port);
|
|
@@ -83,8 +81,8 @@ module.exports = class Server {
|
|
|
83
81
|
|
|
84
82
|
openSimulator(name = null) {
|
|
85
83
|
const url = this._getComponentUrl(name);
|
|
86
|
-
const queryString = url ? `?pct-url=${encodeURIComponent(url)}` :
|
|
87
|
-
require(
|
|
84
|
+
const queryString = url ? `?pct-url=${encodeURIComponent(url)}` : '';
|
|
85
|
+
require('opener')(`${this._getBaseUrl()}/${queryString}`);
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
_getBaseUrl() {
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const prompts = require(
|
|
4
|
-
|
|
5
|
-
const {
|
|
6
|
-
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const prompts = require('prompts');
|
|
4
|
+
|
|
5
|
+
const {
|
|
6
|
+
getRootDir,
|
|
7
|
+
ensureModule,
|
|
8
|
+
logFileCrudMessage,
|
|
9
|
+
pascalCase,
|
|
10
|
+
} = require('../utils');
|
|
11
|
+
const ConfigService = require('../config/config.service');
|
|
7
12
|
|
|
8
13
|
module.exports = class TemplateService {
|
|
9
14
|
_configSrv = new ConfigService();
|
|
@@ -18,9 +23,9 @@ module.exports = class TemplateService {
|
|
|
18
23
|
let schema;
|
|
19
24
|
|
|
20
25
|
const result = await prompts({
|
|
21
|
-
type:
|
|
22
|
-
name:
|
|
23
|
-
message:
|
|
26
|
+
type: 'select',
|
|
27
|
+
name: 'templateName',
|
|
28
|
+
message: 'Pick a template',
|
|
24
29
|
choices: Object.keys(this._schemas).map((key) => ({
|
|
25
30
|
title: this._schemas[key].name,
|
|
26
31
|
value: key,
|
|
@@ -42,9 +47,9 @@ module.exports = class TemplateService {
|
|
|
42
47
|
|
|
43
48
|
if (schema.variants) {
|
|
44
49
|
const _result = await prompts({
|
|
45
|
-
type:
|
|
46
|
-
name:
|
|
47
|
-
message:
|
|
50
|
+
type: 'select',
|
|
51
|
+
name: 'variantIdx',
|
|
52
|
+
message: 'Pick a variant',
|
|
48
53
|
choices: schema.variants.map((variant, index) => ({
|
|
49
54
|
title: variant.name,
|
|
50
55
|
value: index,
|
|
@@ -63,14 +68,14 @@ module.exports = class TemplateService {
|
|
|
63
68
|
const modulesNames = Object.keys(schema.config.runner).reduce(
|
|
64
69
|
(names, cmd) => {
|
|
65
70
|
if (schema.config.runner[cmd].builder) {
|
|
66
|
-
const name = schema.config.runner[cmd].builder.split(
|
|
71
|
+
const name = schema.config.runner[cmd].builder.split(':')[0];
|
|
67
72
|
if (!names.includes(name)) {
|
|
68
73
|
return [...names, name];
|
|
69
74
|
}
|
|
70
75
|
}
|
|
71
76
|
return names;
|
|
72
77
|
},
|
|
73
|
-
[]
|
|
78
|
+
[],
|
|
74
79
|
);
|
|
75
80
|
modulesNames.forEach((name) => ensureModule(name));
|
|
76
81
|
}
|
|
@@ -94,42 +99,43 @@ module.exports = class TemplateService {
|
|
|
94
99
|
}
|
|
95
100
|
|
|
96
101
|
createFile(file, ctx) {
|
|
97
|
-
|
|
102
|
+
const rootDir = getRootDir();
|
|
103
|
+
fs.mkdirSync(path.dirname(path.join(rootDir, file.dest)), {
|
|
98
104
|
recursive: true,
|
|
99
105
|
});
|
|
100
106
|
if (file.interpolateContent) {
|
|
101
107
|
const text = fs.readFileSync(
|
|
102
108
|
path.join(
|
|
103
|
-
path.dirname(require.resolve(
|
|
104
|
-
file.source
|
|
109
|
+
path.dirname(require.resolve('@ixon-cdk/templates')),
|
|
110
|
+
file.source,
|
|
105
111
|
),
|
|
106
|
-
{ encoding:
|
|
112
|
+
{ encoding: 'utf-8' },
|
|
107
113
|
);
|
|
108
114
|
const data = this._interpolateText(text, ctx);
|
|
109
|
-
fs.writeFileSync(path.join(
|
|
110
|
-
encoding:
|
|
115
|
+
fs.writeFileSync(path.join(rootDir, file.dest), data, {
|
|
116
|
+
encoding: 'utf-8',
|
|
111
117
|
});
|
|
112
118
|
} else {
|
|
113
119
|
fs.copyFileSync(
|
|
114
120
|
path.join(
|
|
115
|
-
path.dirname(require.resolve(
|
|
116
|
-
file.source
|
|
121
|
+
path.dirname(require.resolve('@ixon-cdk/templates')),
|
|
122
|
+
file.source,
|
|
117
123
|
),
|
|
118
|
-
path.join(
|
|
124
|
+
path.join(rootDir, file.dest),
|
|
119
125
|
);
|
|
120
126
|
}
|
|
121
|
-
logFileCrudMessage(
|
|
127
|
+
logFileCrudMessage('CREATE', file.dest);
|
|
122
128
|
}
|
|
123
129
|
|
|
124
130
|
_discover() {
|
|
125
|
-
const dir = path.dirname(require.resolve(
|
|
131
|
+
const dir = path.dirname(require.resolve('@ixon-cdk/templates'));
|
|
126
132
|
const files = fs.readdirSync(dir);
|
|
127
133
|
files.forEach((file) => {
|
|
128
134
|
if (fs.lstatSync(path.join(dir, file)).isDirectory()) {
|
|
129
|
-
const schemaFile = path.join(dir, file,
|
|
135
|
+
const schemaFile = path.join(dir, file, 'schema.json');
|
|
130
136
|
if (fs.existsSync(schemaFile)) {
|
|
131
137
|
const schema = JSON.parse(fs.readFileSync(schemaFile));
|
|
132
|
-
this._schemas =
|
|
138
|
+
this._schemas = { ...this._schemas, [file]: schema };
|
|
133
139
|
}
|
|
134
140
|
}
|
|
135
141
|
});
|
package/utils.js
CHANGED
|
@@ -1,20 +1,18 @@
|
|
|
1
|
-
const fs = require(
|
|
2
|
-
const path = require(
|
|
3
|
-
const chalk = require(
|
|
4
|
-
const flow = require(
|
|
5
|
-
const camelCase = require(
|
|
6
|
-
const upperFirst = require(
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const chalk = require('chalk');
|
|
4
|
+
const flow = require('lodash/flow');
|
|
5
|
+
const camelCase = require('lodash/camelCase');
|
|
6
|
+
const upperFirst = require('lodash/upperFirst');
|
|
7
7
|
|
|
8
8
|
function getArgv() {
|
|
9
9
|
const remain = process.argv.slice(2);
|
|
10
|
-
const argv = require(
|
|
10
|
+
const { argv } = require('yargs/yargs')(remain);
|
|
11
11
|
|
|
12
12
|
// version argument fix
|
|
13
|
-
if (
|
|
14
|
-
const versionArg = remain.find((arg) =>
|
|
15
|
-
|
|
16
|
-
);
|
|
17
|
-
if (!!versionArg) {
|
|
13
|
+
if ('version' in argv) {
|
|
14
|
+
const versionArg = remain.find((arg) => /^--version=("[0-9]+"|'[0-9]+'|[0-9]+)$/.test(arg));
|
|
15
|
+
if (versionArg) {
|
|
18
16
|
const matches = versionArg.match(/^--version=['"]?([0-9]+)['"]?$/);
|
|
19
17
|
argv.version = Number(matches[1]);
|
|
20
18
|
}
|
|
@@ -23,16 +21,22 @@ function getArgv() {
|
|
|
23
21
|
return argv;
|
|
24
22
|
}
|
|
25
23
|
|
|
24
|
+
function getRootDir() {
|
|
25
|
+
return require('app-root-dir').get();
|
|
26
|
+
}
|
|
27
|
+
|
|
26
28
|
function logErrorMessage(message) {
|
|
27
29
|
console.log(chalk.redBright.bold(message));
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
function logFileCrudMessage(crud, file) {
|
|
31
33
|
switch (crud) {
|
|
32
|
-
case
|
|
33
|
-
case
|
|
34
|
+
case 'CREATE':
|
|
35
|
+
case 'UPDATE':
|
|
34
36
|
console.log(`${chalk.green(crud)} ${file}`);
|
|
35
37
|
break;
|
|
38
|
+
default:
|
|
39
|
+
break;
|
|
36
40
|
}
|
|
37
41
|
}
|
|
38
42
|
|
|
@@ -51,24 +55,25 @@ function moduleExists(moduleName) {
|
|
|
51
55
|
}
|
|
52
56
|
|
|
53
57
|
function ensureModule(moduleName) {
|
|
54
|
-
if (!moduleName.startsWith(
|
|
55
|
-
|
|
58
|
+
if (!moduleName.startsWith('@ixon-cdk/')) {
|
|
59
|
+
logErrorMessage('Cannot install this module.');
|
|
60
|
+
return;
|
|
56
61
|
}
|
|
57
62
|
if (!moduleExists(moduleName)) {
|
|
58
63
|
console.log(`Installing package '${moduleName}'...`);
|
|
59
|
-
require(
|
|
64
|
+
require('child_process').execSync(`npm install --save-dev ${moduleName}`);
|
|
60
65
|
}
|
|
61
66
|
}
|
|
62
67
|
|
|
63
68
|
function zip(output, callback) {
|
|
64
69
|
const outputDir = path.dirname(output);
|
|
65
|
-
const zipFile = path.join(outputDir
|
|
70
|
+
const zipFile = path.join(`${outputDir}.zip`);
|
|
66
71
|
const stream = fs.createWriteStream(zipFile);
|
|
67
|
-
stream.on(
|
|
68
|
-
require(
|
|
72
|
+
stream.on('close', () => {
|
|
73
|
+
require('rimraf').sync(outputDir);
|
|
69
74
|
callback(zipFile);
|
|
70
75
|
});
|
|
71
|
-
const archive = require(
|
|
76
|
+
const archive = require('archiver')('zip', { zlib: { level: 9 } });
|
|
72
77
|
archive.pipe(stream);
|
|
73
78
|
archive.directory(outputDir, path.basename(outputDir));
|
|
74
79
|
archive.finalize();
|
|
@@ -77,7 +82,7 @@ function zip(output, callback) {
|
|
|
77
82
|
const pascalCase = flow(camelCase, upperFirst);
|
|
78
83
|
|
|
79
84
|
function apiHttpErrorToMessage(error) {
|
|
80
|
-
if (typeof error ===
|
|
85
|
+
if (typeof error === 'string') {
|
|
81
86
|
logErrorMessage(error);
|
|
82
87
|
process.exit();
|
|
83
88
|
}
|
|
@@ -86,23 +91,32 @@ function apiHttpErrorToMessage(error) {
|
|
|
86
91
|
if (errors) {
|
|
87
92
|
logErrorMessage(
|
|
88
93
|
errors
|
|
89
|
-
.map((err) =>
|
|
90
|
-
|
|
91
|
-
? `${err.propertyName}: ${err.message}`
|
|
92
|
-
: err.message
|
|
93
|
-
)
|
|
94
|
-
.join("\n")
|
|
94
|
+
.map((err) => (err.propertyName ? `${err.propertyName}: ${err.message}` : err.message))
|
|
95
|
+
.join('\n'),
|
|
95
96
|
);
|
|
96
97
|
process.exit();
|
|
97
98
|
}
|
|
98
99
|
}
|
|
99
|
-
logErrorMessage(
|
|
100
|
+
logErrorMessage('Unexpected error.');
|
|
100
101
|
console.log(error);
|
|
101
102
|
process.exit();
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
function generatePreviewHash(templateId, templateName, versionId, versionNumber, versionMainPath) {
|
|
106
|
+
const ref = {
|
|
107
|
+
tid: templateId,
|
|
108
|
+
tnm: templateName,
|
|
109
|
+
vid: versionId,
|
|
110
|
+
vnr: versionNumber,
|
|
111
|
+
vmp: versionMainPath,
|
|
112
|
+
};
|
|
113
|
+
const salt = 'A9qJ03jh';
|
|
114
|
+
return require('crypto-js').AES.encrypt(JSON.stringify(ref), salt).toString();
|
|
115
|
+
}
|
|
116
|
+
|
|
104
117
|
module.exports = {
|
|
105
118
|
getArgv,
|
|
119
|
+
getRootDir,
|
|
106
120
|
logErrorMessage,
|
|
107
121
|
logFileCrudMessage,
|
|
108
122
|
logSuccessMessage,
|
|
@@ -111,4 +125,5 @@ module.exports = {
|
|
|
111
125
|
zip,
|
|
112
126
|
pascalCase,
|
|
113
127
|
apiHttpErrorToMessage,
|
|
128
|
+
generatePreviewHash,
|
|
114
129
|
};
|