@kumologica/sdk 3.1.0-alpha2 → 3.1.0-beta2
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/cli/.DS_Store +0 -0
- package/cli/KumologicaError.js +17 -0
- package/cli/cli.js +2 -1
- package/cli/commands/create-commands/create-project-iteratively.js +42 -0
- package/cli/commands/create-commands/index.js +5 -0
- package/cli/commands/create.js +55 -22
- package/cli/commands/list-templates.js +24 -0
- package/cli/commands/open.js +1 -1
- package/cli/commands/test-utils/TestSuiteController.js +0 -1
- package/cli/commands/test.js +3 -2
- package/cli/utils/download-template-from-repo.js +346 -0
- package/cli/utils/download-test.js +12 -0
- package/cli/utils/download.js +119 -0
- package/cli/utils/fs/copy-dir-contents-sync.js +15 -0
- package/cli/utils/fs/create-zip-file.js +39 -0
- package/cli/utils/fs/dir-exists-sync.js +14 -0
- package/cli/utils/fs/dir-exists.js +17 -0
- package/cli/utils/fs/file-exists-sync.js +14 -0
- package/cli/utils/fs/file-exists.js +12 -0
- package/cli/utils/fs/get-tmp-dir-path.js +22 -0
- package/cli/utils/fs/parse.js +40 -0
- package/cli/utils/fs/read-file-sync.js +11 -0
- package/cli/utils/fs/read-file.js +10 -0
- package/cli/utils/fs/safe-move-file.js +58 -0
- package/cli/utils/fs/walk-dir-sync.js +34 -0
- package/cli/utils/fs/write-file-sync.js +31 -0
- package/cli/utils/fs/write-file.js +32 -0
- package/cli/{commands/utils.js → utils/logger.js} +7 -1
- package/cli/utils/rename-service.js +49 -0
- package/package.json +18 -33
- package/src/app/ui/editor-api/lib/auth/index.js +75 -73
- package/src/app/ui/editor-api/lib/auth/strategies.js +132 -132
- package/src/app/ui/editor-api/lib/index.js +2 -2
- package/src/app/ui/editor-client/public/red/main-modals.min.js +1 -16
- package/src/app/ui/editor-client/public/red/main.min.js +1 -16
- package/src/app/ui/editor-client/public/red/red.js +64 -44
- package/src/app/ui/editor-client/public/red/red.min.js +19 -16
- package/src/app/ui/editor-client/public/red/style.min.css +1 -16
- package/src/app/ui/editor-client/public/vendor/ace/mode-jsonata.js +1 -1
- package/src/app/ui/editor-client/public/vendor/ace/snippets/jsonata.js +1 -1
- package/src/app/ui/editor-client/public/vendor/simplemde/simplemde.min.css +7 -0
- package/src/app/ui/editor-client/public/vendor/simplemde/simplemde.min.js +15 -0
- package/src/app/ui/editor-client/public/vendor/xterm/lib/xterm.js +2 -0
- package/src/app/ui/editor-client/src/js/ui/common/tabs.js +25 -17
- package/src/app/ui/editor-client/src/js/ui/palette-navigator.js +3 -2
- package/src/app/ui/editor-client/src/js/ui/search.js +21 -13
- package/src/app/ui/editor-client/src/js/ui/view.js +5 -3
- package/src/app/ui/editor-client/src/js/ui/workspaces.js +10 -9
- package/src/app/ui/editor-client/src/sass/palette.scss +1 -0
package/cli/.DS_Store
ADDED
|
Binary file
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
class KumologicaError extends Error {
|
|
4
|
+
constructor(message, code, options = {}) {
|
|
5
|
+
super(message);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.decoratedMessage = options.decoratedMessage;
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
Object.defineProperty(KumologicaError.prototype, 'name', {
|
|
12
|
+
value: KumologicaError.name,
|
|
13
|
+
configurable: true,
|
|
14
|
+
writable: true,
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
module.exports = KumologicaError;
|
package/cli/cli.js
CHANGED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const pathlib = require('path');
|
|
2
|
+
const { prompt, Select } = require('enquirer');
|
|
3
|
+
const { logNotice, logError } = require('../../utils/logger');
|
|
4
|
+
const { downloadTemplateFromRepo, listAvailableTemplates } = require('../../utils/download-template-from-repo');
|
|
5
|
+
|
|
6
|
+
async function createProjectIteratively(){
|
|
7
|
+
const availableTemplates = await listAvailableTemplates();
|
|
8
|
+
// Project name
|
|
9
|
+
const projectNameResponse = await prompt({
|
|
10
|
+
type: 'input',
|
|
11
|
+
name: 'projectName',
|
|
12
|
+
message: 'Enter the name for the project'
|
|
13
|
+
});
|
|
14
|
+
let aProjectName = projectNameResponse.projectName;
|
|
15
|
+
|
|
16
|
+
// Target Path
|
|
17
|
+
const directoryResponse = await prompt({
|
|
18
|
+
type: 'input',
|
|
19
|
+
name: 'directory',
|
|
20
|
+
message: 'Enter the path where the project will be created '
|
|
21
|
+
});
|
|
22
|
+
let aProjectPath = directoryResponse.directory;
|
|
23
|
+
|
|
24
|
+
// Template name
|
|
25
|
+
const promptTemplate = new Select({
|
|
26
|
+
name: 'template',
|
|
27
|
+
message: 'Pick one of the available templates',
|
|
28
|
+
choices: availableTemplates
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
let aTemplateName = await promptTemplate.run();
|
|
32
|
+
|
|
33
|
+
try{
|
|
34
|
+
await downloadTemplateFromRepo(undefined, aTemplateName, aProjectPath, aProjectName);
|
|
35
|
+
logNotice(`Successfully created project: ${pathlib.join(aProjectPath, aProjectName)}`)
|
|
36
|
+
} catch (err){
|
|
37
|
+
logError(`Error found while creating project due to: ${err.message}`)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
module.exports = createProjectIteratively;
|
package/cli/commands/create.js
CHANGED
|
@@ -1,32 +1,65 @@
|
|
|
1
1
|
const pathlib = require('path');
|
|
2
|
-
const { logNotice, logError } = require('./utils');
|
|
3
2
|
const { codegen } = require('@kumologica/builder');
|
|
4
3
|
|
|
5
|
-
|
|
4
|
+
const { logNotice, logError } = require('../utils/logger');
|
|
5
|
+
const { downloadTemplateFromRepo, isPlainGitURL } = require('../utils/download-template-from-repo');
|
|
6
|
+
const { createProjectIteratively } = require('./create-commands');
|
|
7
|
+
|
|
8
|
+
exports.command = 'create [options]'
|
|
6
9
|
exports.builder = (yargs) => {
|
|
7
10
|
yargs.option(`path`, {
|
|
8
|
-
describe: "The path where project will be created
|
|
9
|
-
demandOption: "The path is required.",
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
describe: "The project path where the project will be created",
|
|
12
|
+
// demandOption: "The path is required.",
|
|
13
|
+
type: 'string',
|
|
14
|
+
alias: 'p',
|
|
15
|
+
nargs: 1
|
|
16
|
+
})
|
|
17
|
+
yargs.option(`template`, {
|
|
18
|
+
describe: `Template for the project`,
|
|
19
|
+
type: 'string',
|
|
20
|
+
alias: 't',
|
|
21
|
+
nargs: 1
|
|
22
|
+
})
|
|
14
23
|
}
|
|
15
24
|
|
|
16
|
-
|
|
17
|
-
exports.
|
|
25
|
+
|
|
26
|
+
exports.desc = 'Create a kumologica project. Do not pass any options to create iteratively.'
|
|
27
|
+
exports.handler = async ({ path, template }) => {
|
|
18
28
|
const { version } = require('../../package.json');
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
|
|
30
|
+
if (!path && !template) {
|
|
31
|
+
await createProjectIteratively();
|
|
32
|
+
} else if (!path && template) {
|
|
33
|
+
try{
|
|
34
|
+
await downloadTemplateFromRepo(undefined, template, process.cwd(), template);
|
|
35
|
+
logNotice(`Successfully created project: ${ pathlib.join(process.cwd(), template)}`);
|
|
36
|
+
}catch(e){
|
|
37
|
+
logError(e.message);
|
|
38
|
+
}
|
|
39
|
+
} else if (path && !template){
|
|
40
|
+
try{
|
|
41
|
+
codegen.generateBoilerplateProject({
|
|
42
|
+
basePath :process.cwd(),
|
|
43
|
+
projectName: path,
|
|
44
|
+
runtimeVersion: version });
|
|
45
|
+
logNotice(`Successfully created project: ${ pathlib.join(process.cwd(), path)}`);
|
|
46
|
+
}catch(e){
|
|
47
|
+
logError(e.message);
|
|
48
|
+
}
|
|
49
|
+
} else if (path && template) {
|
|
50
|
+
path = pathlib.resolve(path);
|
|
51
|
+
let projectPath = pathlib.dirname(path);
|
|
52
|
+
let projectName = pathlib.basename(path);
|
|
53
|
+
try{
|
|
54
|
+
if (isPlainGitURL(template)){
|
|
55
|
+
await downloadTemplateFromRepo(template, undefined, projectPath, projectName);
|
|
56
|
+
} else {
|
|
57
|
+
await downloadTemplateFromRepo(undefined, template, projectPath, projectName);
|
|
58
|
+
}
|
|
59
|
+
logNotice(`Successfully created project: ${path}`);
|
|
60
|
+
}catch(e){
|
|
61
|
+
logError(e.message);
|
|
62
|
+
}
|
|
29
63
|
}
|
|
30
|
-
|
|
31
|
-
|
|
64
|
+
|
|
32
65
|
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
const { listAvailableTemplates } = require('../utils/download-template-from-repo');
|
|
2
|
+
const { logNotice, logError, logInfo } = require('../utils/logger');
|
|
3
|
+
|
|
4
|
+
exports.command = 'list-templates'
|
|
5
|
+
exports.desc = 'List of available templates'
|
|
6
|
+
exports.handler = async function (argv) {
|
|
7
|
+
try {
|
|
8
|
+
logInfo('List of available templates:');
|
|
9
|
+
let templates = await readerFriendly(listAvailableTemplates())
|
|
10
|
+
logNotice(templates);
|
|
11
|
+
}catch(e){
|
|
12
|
+
logError(e.message);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Utils
|
|
17
|
+
async function readerFriendly(templates) {
|
|
18
|
+
let result = [];
|
|
19
|
+
templates = await templates;
|
|
20
|
+
templates.forEach(t => {
|
|
21
|
+
result.push(`"${t}"`);
|
|
22
|
+
});
|
|
23
|
+
return result.join(',')
|
|
24
|
+
}
|
package/cli/commands/open.js
CHANGED
package/cli/commands/test.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const { Select } = require('enquirer');
|
|
3
3
|
const fs = require('fs');
|
|
4
|
-
const { logError } = require('./utils');
|
|
5
4
|
const path = require('path');
|
|
6
5
|
const wcmatch = require('wildcard-match');
|
|
7
6
|
|
|
8
7
|
const { AppServer } = require('@kumologica/runtime');
|
|
9
|
-
const { TestSuiteController } = require('./test-utils/TestSuiteController');
|
|
10
8
|
const { codegen } = require('@kumologica/builder');
|
|
11
9
|
|
|
10
|
+
const { TestSuiteController } = require('./test-utils/TestSuiteController');
|
|
11
|
+
const { logError } = require('../utils/logger');
|
|
12
|
+
|
|
12
13
|
const log = console.log;
|
|
13
14
|
const APP_SERVER_PORT = 1990;
|
|
14
15
|
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const URL = require('url');
|
|
5
|
+
const BbPromise = require('bluebird');
|
|
6
|
+
const fse = require('fs-extra');
|
|
7
|
+
const qs = require('querystring');
|
|
8
|
+
const spawn = require('child-process-ext/spawn');
|
|
9
|
+
const renameService = require('./rename-service').renameService;
|
|
10
|
+
const KumologicaError = require('../KumologicaError');
|
|
11
|
+
const copyDirContentsSync = require('./fs/copy-dir-contents-sync');
|
|
12
|
+
const dirExistsSync = require('./fs/dir-exists-sync');
|
|
13
|
+
const walkDirSync = require('./fs/walk-dir-sync');
|
|
14
|
+
const { getTmpDirPath, getBaseTmpDirPath } = require('./fs/get-tmp-dir-path');
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
const OFFICAL_TEMPLATES_REPO = 'https://github.com/KumologicaHQ/kumologica-templates.git';
|
|
18
|
+
/**
|
|
19
|
+
* Returns directory path
|
|
20
|
+
* @param {Number} length
|
|
21
|
+
* @param {Array} parts
|
|
22
|
+
* @returns {String} directory path
|
|
23
|
+
*/
|
|
24
|
+
function getPathDirectory(length, parts) {
|
|
25
|
+
if (!parts) {
|
|
26
|
+
return '';
|
|
27
|
+
}
|
|
28
|
+
return parts.slice(length).filter(Boolean).join(path.sep);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Validates URL
|
|
33
|
+
* @param {Object} url
|
|
34
|
+
* @param {String} hostname
|
|
35
|
+
* @param {String} service
|
|
36
|
+
* @param {String} owner
|
|
37
|
+
* @param {String} repo
|
|
38
|
+
*/
|
|
39
|
+
function validateUrl({ url, hostname, service, owner, repo }) {
|
|
40
|
+
// validate if given url is a valid url
|
|
41
|
+
if (url.hostname !== hostname || !owner || !repo) {
|
|
42
|
+
const errorMessage = `The URL must be a valid ${service} URL in the following format: https://${hostname}/serverless/serverless`;
|
|
43
|
+
throw new KumologicaError(errorMessage, 'INVALID_TEMPLATE_URL');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Check if the URL is pointing to a Git repository
|
|
49
|
+
* @param {String} url
|
|
50
|
+
*/
|
|
51
|
+
function isPlainGitURL(url) {
|
|
52
|
+
return (url.startsWith('https') || url.startsWith('git@')) && url.endsWith('.git');
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* @param {Object} url
|
|
57
|
+
* @returns {Object}
|
|
58
|
+
*/
|
|
59
|
+
function parseGitHubURL(url) {
|
|
60
|
+
const pathLength = 4;
|
|
61
|
+
const parts = url.pathname.split('/');
|
|
62
|
+
const isSubdirectory = parts.length > pathLength;
|
|
63
|
+
const owner = parts[1];
|
|
64
|
+
const repo = parts[2];
|
|
65
|
+
const branch = isSubdirectory ? parts[pathLength] : 'master';
|
|
66
|
+
const isGitHubEnterprise = url.hostname !== 'github.com';
|
|
67
|
+
|
|
68
|
+
if (!isGitHubEnterprise) {
|
|
69
|
+
// validate if given url is a valid GitHub url
|
|
70
|
+
validateUrl({ url, hostname: 'github.com', service: 'GitHub', owner, repo });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const downloadUrl = `https://${
|
|
74
|
+
isGitHubEnterprise ? url.hostname : 'github.com'
|
|
75
|
+
}/${owner}/${repo}/archive/${branch}.zip`;
|
|
76
|
+
|
|
77
|
+
return {
|
|
78
|
+
owner,
|
|
79
|
+
repo,
|
|
80
|
+
branch,
|
|
81
|
+
downloadUrl,
|
|
82
|
+
isSubdirectory,
|
|
83
|
+
pathToDirectory: getPathDirectory(pathLength + 1, parts),
|
|
84
|
+
username: url.username || '',
|
|
85
|
+
password: url.password || '',
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* @param {Object} url
|
|
91
|
+
* @returns {Object}
|
|
92
|
+
*/
|
|
93
|
+
function parseBitbucketURL(url) {
|
|
94
|
+
const pathLength = 4;
|
|
95
|
+
const parts = url.pathname.split('/');
|
|
96
|
+
const isSubdirectory = parts.length > pathLength;
|
|
97
|
+
const owner = parts[1];
|
|
98
|
+
const repo = parts[2];
|
|
99
|
+
|
|
100
|
+
const query = qs.parse(url.query);
|
|
101
|
+
const branch = 'at' in query ? query.at : 'master';
|
|
102
|
+
|
|
103
|
+
// validate if given url is a valid Bitbucket url
|
|
104
|
+
validateUrl({ url, hostname: 'bitbucket.org', service: 'Bitbucket', owner, repo });
|
|
105
|
+
|
|
106
|
+
const downloadUrl = `https://bitbucket.org/${owner}/${repo}/get/${branch}.zip`;
|
|
107
|
+
|
|
108
|
+
return {
|
|
109
|
+
owner,
|
|
110
|
+
repo,
|
|
111
|
+
branch,
|
|
112
|
+
downloadUrl,
|
|
113
|
+
isSubdirectory,
|
|
114
|
+
pathToDirectory: getPathDirectory(pathLength + 1, parts),
|
|
115
|
+
username: url.username || '',
|
|
116
|
+
password: url.password || '',
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function parseBitbucketServerURL(url) {
|
|
121
|
+
const pathLength = 9;
|
|
122
|
+
const parts = url.pathname.split('/');
|
|
123
|
+
const isSubdirectory = parts.length > pathLength;
|
|
124
|
+
const owner = parts[5];
|
|
125
|
+
const repo = parts[7];
|
|
126
|
+
|
|
127
|
+
const query = qs.parse(url.query);
|
|
128
|
+
const branch = 'at' in query ? decodeURIComponent(query.at) : 'master';
|
|
129
|
+
|
|
130
|
+
const downloadUrl = `${url.protocol}//${url.hostname}/rest/api/latest/projects/${owner}/repos/${repo}/archive${url.search}&format=zip`;
|
|
131
|
+
|
|
132
|
+
return {
|
|
133
|
+
owner,
|
|
134
|
+
repo,
|
|
135
|
+
branch,
|
|
136
|
+
downloadUrl,
|
|
137
|
+
isSubdirectory,
|
|
138
|
+
pathToDirectory: getPathDirectory(pathLength + 1, parts),
|
|
139
|
+
username: url.username || '',
|
|
140
|
+
password: url.password || '',
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Call `/rest/api/1.0/application-properties` to retrieve server info
|
|
146
|
+
* @param {Object} url
|
|
147
|
+
* @returns {Boolean}
|
|
148
|
+
*/
|
|
149
|
+
async function retrieveBitbucketServerInfo(url) {
|
|
150
|
+
let requestOpts = {
|
|
151
|
+
url: `${url.protocol}//${url.hostname}/rest/api/1.0/application-properties`,
|
|
152
|
+
method: 'GET',
|
|
153
|
+
throwHttpErrors: false,
|
|
154
|
+
retry: 0
|
|
155
|
+
}
|
|
156
|
+
try {
|
|
157
|
+
let resp = await got(requestOpts)
|
|
158
|
+
return resp.body.displayName === 'Bitbucket';
|
|
159
|
+
}catch(err){
|
|
160
|
+
throw err;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* @param {Object} url
|
|
167
|
+
* @returns {Object}
|
|
168
|
+
*/
|
|
169
|
+
function parseGitlabURL(url) {
|
|
170
|
+
const pathLength = 4;
|
|
171
|
+
const parts = url.pathname.split('/');
|
|
172
|
+
const isSubdirectory = parts.length > pathLength;
|
|
173
|
+
const owner = parts[1];
|
|
174
|
+
const repo = parts[2];
|
|
175
|
+
|
|
176
|
+
const branch = isSubdirectory ? parts[pathLength] : 'master';
|
|
177
|
+
|
|
178
|
+
// validate if given url is a valid GitLab url
|
|
179
|
+
validateUrl({ url, hostname: 'gitlab.com', service: 'Bitbucket', owner, repo });
|
|
180
|
+
|
|
181
|
+
const downloadUrl = `https://gitlab.com/${owner}/${repo}/-/archive/${branch}/${repo}-${branch}.zip`;
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
owner,
|
|
185
|
+
repo,
|
|
186
|
+
branch,
|
|
187
|
+
downloadUrl,
|
|
188
|
+
isSubdirectory,
|
|
189
|
+
pathToDirectory: getPathDirectory(pathLength + 1, parts),
|
|
190
|
+
username: url.username || '',
|
|
191
|
+
password: url.password || '',
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Parses a URL which points to a plain Git repository
|
|
197
|
+
* such as https://example.com/jdoe/project.git
|
|
198
|
+
*
|
|
199
|
+
* @param {String} url
|
|
200
|
+
* @returns {Object}
|
|
201
|
+
*/
|
|
202
|
+
function parsePlainGitURL(url) {
|
|
203
|
+
const branch = 'master';
|
|
204
|
+
const downloadUrl = url;
|
|
205
|
+
const isSubdirectory = false;
|
|
206
|
+
const repo = url.match(/.+\/(.+)\.git/)[1];
|
|
207
|
+
return {
|
|
208
|
+
repo,
|
|
209
|
+
branch,
|
|
210
|
+
downloadUrl,
|
|
211
|
+
isSubdirectory,
|
|
212
|
+
username: url.username || '',
|
|
213
|
+
password: url.password || '',
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Parse URL and call the appropriate adaptor
|
|
219
|
+
*
|
|
220
|
+
* @param {string} inputUrl
|
|
221
|
+
* @throws {KumologicaError}
|
|
222
|
+
* @returns {Promise}
|
|
223
|
+
*/
|
|
224
|
+
async function parseRepoURL(inputUrl) {
|
|
225
|
+
return new BbPromise((resolve, reject) => {
|
|
226
|
+
if (!inputUrl) {
|
|
227
|
+
return reject(new KumologicaError('URL is required', 'MISSING_TEMPLATE_URL'));
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const url = URL.parse(inputUrl.replace(/\/$/, ''));
|
|
231
|
+
if (url.auth) {
|
|
232
|
+
const [username, password] = url.auth.split(':');
|
|
233
|
+
url.username = username;
|
|
234
|
+
url.password = password;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// check if url parameter is a valid url
|
|
238
|
+
if (!url.host && !url.href.startsWith('git@')) {
|
|
239
|
+
return reject(new KumologicaError('The URL you passed is not valid', 'INVALID_TEMPLATE_URL'));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (isPlainGitURL(url.href)) {
|
|
243
|
+
return resolve(parsePlainGitURL(inputUrl));
|
|
244
|
+
} else if (url.hostname === 'github.com' || url.hostname.indexOf('github.') !== -1) {
|
|
245
|
+
return resolve(parseGitHubURL(url));
|
|
246
|
+
} else if (url.hostname === 'bitbucket.org') {
|
|
247
|
+
return resolve(parseBitbucketURL(url));
|
|
248
|
+
} else if (url.hostname === 'gitlab.com') {
|
|
249
|
+
return resolve(parseGitlabURL(url));
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const msg =
|
|
253
|
+
'The URL you passed is not one of the valid providers: "GitHub", "GitHub Entreprise", "Bitbucket", "Bitbucket Server" or "GitLab".';
|
|
254
|
+
const err = new KumologicaError(msg, 'INVALID_TEMPLATE_PROVIDER');
|
|
255
|
+
// test if it's a private bitbucket server
|
|
256
|
+
return retrieveBitbucketServerInfo(url)
|
|
257
|
+
.then((isBitbucket) => {
|
|
258
|
+
if (!isBitbucket) {
|
|
259
|
+
return reject(err);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// build download URL
|
|
263
|
+
return resolve(parseBitbucketServerURL(url));
|
|
264
|
+
})
|
|
265
|
+
.catch(() => reject(err));
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Downloads the content of the template into the projectName directory
|
|
271
|
+
* @param {string} [repoUrl] - the git repository
|
|
272
|
+
* @param {string} [templateName] - the name of the project (optional), in case we are only interested in a particular directory within the repo
|
|
273
|
+
* @param {string} projectName - the local project name / directory to be created
|
|
274
|
+
* @returns {Promise}
|
|
275
|
+
*/
|
|
276
|
+
async function downloadTemplateFromRepo(repoUrl, templateName, projectPath, projectName) {
|
|
277
|
+
try{
|
|
278
|
+
repoUrl = repoUrl || OFFICAL_TEMPLATES_REPO;
|
|
279
|
+
const repoInformation = await parseRepoURL(repoUrl);
|
|
280
|
+
|
|
281
|
+
const tempBaseDirectory = getBaseTmpDirPath();
|
|
282
|
+
// clean up temp directory
|
|
283
|
+
fse.removeSync(tempBaseDirectory);
|
|
284
|
+
const tempRepoDirectory = getTmpDirPath();
|
|
285
|
+
// const { username, password } = repoInformation;
|
|
286
|
+
|
|
287
|
+
const renamed = templateName !== projectName;
|
|
288
|
+
|
|
289
|
+
// Source project directory
|
|
290
|
+
const srcProjectDir = templateName? path.join(tempRepoDirectory, templateName) : tempRepoDirectory;
|
|
291
|
+
|
|
292
|
+
// Target project directory
|
|
293
|
+
const targetProjectDir = path.join(projectPath, projectName);
|
|
294
|
+
|
|
295
|
+
if (dirExistsSync(targetProjectDir)) {
|
|
296
|
+
const errorMessage = `A project already exist in path: "${targetProjectDir}".`;
|
|
297
|
+
throw new KumologicaError(errorMessage, 'TARGET_FOLDER_ALREADY_EXISTS');
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
if (isPlainGitURL(repoUrl)) {
|
|
301
|
+
return spawn('git', ['clone', repoUrl, tempRepoDirectory]).then(() => {
|
|
302
|
+
try {
|
|
303
|
+
copyDirContentsSync(srcProjectDir, targetProjectDir);
|
|
304
|
+
fse.removeSync(tempBaseDirectory);
|
|
305
|
+
if (renamed) renameService(targetProjectDir, projectName);
|
|
306
|
+
}catch(err){
|
|
307
|
+
throw new KumologicaError(`Template name: "${templateName}" does not exist. Run "kl list-templates" to see list of available templates.`);
|
|
308
|
+
}
|
|
309
|
+
return "";
|
|
310
|
+
});
|
|
311
|
+
} else {
|
|
312
|
+
throw new KumologicaError(`Git repo URL is incorrect`);
|
|
313
|
+
}
|
|
314
|
+
}catch(err){
|
|
315
|
+
throw new KumologicaError(err.message);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
async function listAvailableTemplates() {
|
|
320
|
+
try{
|
|
321
|
+
const tempBaseDirectory = getBaseTmpDirPath();
|
|
322
|
+
const tempRepoDirectory = getTmpDirPath();
|
|
323
|
+
|
|
324
|
+
await parseRepoURL(OFFICAL_TEMPLATES_REPO);
|
|
325
|
+
|
|
326
|
+
const listTemplates = spawn('git', ['clone', OFFICAL_TEMPLATES_REPO, tempRepoDirectory]).then(() => {
|
|
327
|
+
try {
|
|
328
|
+
const projects = walkDirSync(tempRepoDirectory);
|
|
329
|
+
fse.removeSync(tempBaseDirectory);
|
|
330
|
+
return projects;
|
|
331
|
+
}catch(err){
|
|
332
|
+
throw new KumologicaError(err.message);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
// ListTemplates: ["t1", "t2"]
|
|
336
|
+
return listTemplates;
|
|
337
|
+
} catch(err){
|
|
338
|
+
throw new KumologicaError(err.message);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
module.exports = {
|
|
343
|
+
downloadTemplateFromRepo,
|
|
344
|
+
listAvailableTemplates,
|
|
345
|
+
isPlainGitURL
|
|
346
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const { readerFriendly } = require('../commands/utils');
|
|
2
|
+
const { downloadTemplateFromRepo, listAvailableTemplates } = require('./download-template-from-repo');
|
|
3
|
+
|
|
4
|
+
(async()=> {
|
|
5
|
+
try{
|
|
6
|
+
// await downloadTemplateFromRepo(undefined, 'aws-api-helloworldWRONG', 'kk');
|
|
7
|
+
const result = await readerFriendly(listAvailableTemplates());
|
|
8
|
+
console.log(result);
|
|
9
|
+
} catch(err){
|
|
10
|
+
console.log('Error creating template due to: ', err.message);
|
|
11
|
+
}
|
|
12
|
+
})();
|