test-bdk-cli 1.0.1 → 1.0.3
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/package.json +22 -2
- package/dist/commands/create.js +0 -314
- package/dist/commands/help.js +0 -83
- package/dist/commands/pack.js +0 -116
- package/dist/commands/publish.js +0 -97
- package/dist/commands/run.js +0 -155
- package/dist/commands/test.js +0 -61
- package/dist/commands/validate.js +0 -57
- package/dist/commands/version.js +0 -62
- package/dist/index.js +0 -24
- package/dist/lib/appPath.js +0 -17
- package/dist/lib/package.js +0 -146
- package/dist/utils/appConfig.js +0 -24
- package/dist/utils/createApp.js +0 -47
- package/dist/utils/getAppSettings.js +0 -13
- package/dist/utils/manifest.js +0 -14
- package/dist/utils/uploadApp.js +0 -25
package/dist/commands/run.js
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.registerRun = registerRun;
|
|
37
|
-
const http = __importStar(require("http"));
|
|
38
|
-
const fs = __importStar(require("fs"));
|
|
39
|
-
const path = __importStar(require("path"));
|
|
40
|
-
const child_process_1 = require("child_process");
|
|
41
|
-
function registerRun(program) {
|
|
42
|
-
program
|
|
43
|
-
.command('run [source]')
|
|
44
|
-
.alias('apps:run')
|
|
45
|
-
.description('Run the app locally with live reload')
|
|
46
|
-
.option('--port <number>', 'port to run', '3000')
|
|
47
|
-
.option('--env <env>', 'environment', 'dev')
|
|
48
|
-
.option('--open', 'open browser after start', false)
|
|
49
|
-
.action((sourceArg, opts) => {
|
|
50
|
-
const sourceDir = path.resolve(process.cwd(), sourceArg || '.');
|
|
51
|
-
const port = parseInt(opts.port || '3000', 10);
|
|
52
|
-
const env = opts.env || 'dev';
|
|
53
|
-
// Check if manifest.json exists
|
|
54
|
-
const manifestPath = path.join(sourceDir, 'manifest.json');
|
|
55
|
-
if (!fs.existsSync(manifestPath)) {
|
|
56
|
-
console.error(`manifest.json not found in ${sourceDir}`);
|
|
57
|
-
process.exit(1);
|
|
58
|
-
}
|
|
59
|
-
// Create a simple HTTP server
|
|
60
|
-
const server = http.createServer((req, res) => {
|
|
61
|
-
let filePath = req.url || '/';
|
|
62
|
-
if (filePath === '/') {
|
|
63
|
-
filePath = '/assets/iframe.html';
|
|
64
|
-
}
|
|
65
|
-
// Resolve the file path
|
|
66
|
-
const fullPath = path.join(sourceDir, filePath);
|
|
67
|
-
// Security: prevent directory traversal attacks
|
|
68
|
-
const resolvedPath = path.resolve(fullPath);
|
|
69
|
-
const basePath = path.resolve(sourceDir);
|
|
70
|
-
if (!resolvedPath.startsWith(basePath)) {
|
|
71
|
-
res.writeHead(403, { 'Content-Type': 'text/plain' });
|
|
72
|
-
res.end('Forbidden');
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
// Try to serve the file
|
|
76
|
-
fs.readFile(resolvedPath, (err, data) => {
|
|
77
|
-
if (err) {
|
|
78
|
-
// If file not found, try to serve index.html or 404
|
|
79
|
-
if (err.code === 'ENOENT') {
|
|
80
|
-
res.writeHead(404, { 'Content-Type': 'text/html' });
|
|
81
|
-
res.end(`
|
|
82
|
-
<!DOCTYPE html>
|
|
83
|
-
<html>
|
|
84
|
-
<head><title>404 Not Found</title></head>
|
|
85
|
-
<body>
|
|
86
|
-
<h1>404 - File Not Found</h1>
|
|
87
|
-
<p>Could not find: ${filePath}</p>
|
|
88
|
-
<p><a href="/">Go back</a></p>
|
|
89
|
-
</body>
|
|
90
|
-
</html>
|
|
91
|
-
`);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
res.writeHead(500, { 'Content-Type': 'text/plain' });
|
|
95
|
-
res.end('Internal Server Error');
|
|
96
|
-
}
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// Determine content type
|
|
100
|
-
const ext = path.extname(resolvedPath);
|
|
101
|
-
let contentType = 'application/octet-stream';
|
|
102
|
-
if (ext === '.html')
|
|
103
|
-
contentType = 'text/html; charset=utf-8';
|
|
104
|
-
else if (ext === '.js')
|
|
105
|
-
contentType = 'application/javascript; charset=utf-8';
|
|
106
|
-
else if (ext === '.json')
|
|
107
|
-
contentType = 'application/json; charset=utf-8';
|
|
108
|
-
else if (ext === '.css')
|
|
109
|
-
contentType = 'text/css; charset=utf-8';
|
|
110
|
-
else if (ext === '.svg')
|
|
111
|
-
contentType = 'image/svg+xml';
|
|
112
|
-
else if (ext === '.png')
|
|
113
|
-
contentType = 'image/png';
|
|
114
|
-
else if (ext === '.jpg' || ext === '.jpeg')
|
|
115
|
-
contentType = 'image/jpeg';
|
|
116
|
-
else if (ext === '.gif')
|
|
117
|
-
contentType = 'image/gif';
|
|
118
|
-
res.writeHead(200, { 'Content-Type': contentType });
|
|
119
|
-
res.end(data);
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
server.listen(port, () => {
|
|
123
|
-
console.log(`✅ Dev server started on http://localhost:${port} (env=${env})`);
|
|
124
|
-
console.log(`📁 Serving from: ${sourceDir}`);
|
|
125
|
-
console.log(`📄 Iframe: http://localhost:${port}/assets/iframe.html`);
|
|
126
|
-
console.log(`\nPress Ctrl+C to stop the server\n`);
|
|
127
|
-
// Open browser if --open flag is set
|
|
128
|
-
if (opts.open) {
|
|
129
|
-
const url = `http://localhost:${port}`;
|
|
130
|
-
try {
|
|
131
|
-
const isWindows = process.platform === 'win32';
|
|
132
|
-
const command = isWindows
|
|
133
|
-
? `start ${url}`
|
|
134
|
-
: process.platform === 'darwin'
|
|
135
|
-
? `open ${url}`
|
|
136
|
-
: `xdg-open ${url}`;
|
|
137
|
-
(0, child_process_1.execSync)(command, { stdio: 'ignore' });
|
|
138
|
-
}
|
|
139
|
-
catch (e) {
|
|
140
|
-
// Silently ignore if browser open fails
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
server.on('error', (err) => {
|
|
145
|
-
if (err.code === 'EADDRINUSE') {
|
|
146
|
-
console.error(`❌ Port ${port} is already in use. Try a different port:`);
|
|
147
|
-
console.error(` npx bdk apps:run [source] --port 3001`);
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
console.error(`❌ Server error: ${err.message}`);
|
|
151
|
-
}
|
|
152
|
-
process.exit(1);
|
|
153
|
-
});
|
|
154
|
-
});
|
|
155
|
-
}
|
package/dist/commands/test.js
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.registerTest = registerTest;
|
|
4
|
-
const child_process_1 = require("child_process");
|
|
5
|
-
function registerTest(program) {
|
|
6
|
-
program
|
|
7
|
-
.command('test [source]')
|
|
8
|
-
.alias('apps:test')
|
|
9
|
-
.description('Run unit and integration tests')
|
|
10
|
-
.option('--watch', 're-run tests on file changes', false)
|
|
11
|
-
.option('--coverage', 'generate coverage report', false)
|
|
12
|
-
.action((sourceArg, opts) => {
|
|
13
|
-
const path = require('path');
|
|
14
|
-
const fs = require('fs');
|
|
15
|
-
const cwd = path.resolve(process.cwd(), sourceArg || '.');
|
|
16
|
-
// Check if package.json exists and has test script
|
|
17
|
-
const pkgPath = path.join(cwd, 'package.json');
|
|
18
|
-
const hasPkg = (() => {
|
|
19
|
-
try {
|
|
20
|
-
if (!fs.existsSync(pkgPath)) {
|
|
21
|
-
return false;
|
|
22
|
-
}
|
|
23
|
-
const p = require(pkgPath);
|
|
24
|
-
return !!p.scripts && (p.scripts.test || p.scripts['test:watch']);
|
|
25
|
-
}
|
|
26
|
-
catch (e) {
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
})();
|
|
30
|
-
if (!hasPkg) {
|
|
31
|
-
console.error('No test script found in package.json. Please add a `test` script.');
|
|
32
|
-
process.exit(1);
|
|
33
|
-
}
|
|
34
|
-
if (opts.watch) {
|
|
35
|
-
// prefer npm run test -- --watch if available
|
|
36
|
-
try {
|
|
37
|
-
console.log('Running tests in watch mode...');
|
|
38
|
-
const child = (0, child_process_1.spawn)('npm', ['run', 'test', '--', '--watch'], { stdio: 'inherit', cwd: cwd, shell: true });
|
|
39
|
-
child.on('exit', (code) => process.exit(code || 0));
|
|
40
|
-
}
|
|
41
|
-
catch (e) {
|
|
42
|
-
console.error('Failed to start watch tests:', e);
|
|
43
|
-
process.exit(2);
|
|
44
|
-
}
|
|
45
|
-
return;
|
|
46
|
-
}
|
|
47
|
-
try {
|
|
48
|
-
const args = ['run', 'test'];
|
|
49
|
-
if (opts.coverage) {
|
|
50
|
-
// many projects use `npm run test -- --coverage` to enable coverage
|
|
51
|
-
args.push('--', '--coverage');
|
|
52
|
-
}
|
|
53
|
-
console.log('Running tests...');
|
|
54
|
-
(0, child_process_1.execSync)('npm ' + args.join(' '), { stdio: 'inherit', cwd: cwd });
|
|
55
|
-
}
|
|
56
|
-
catch (e) {
|
|
57
|
-
console.error('Tests failed.');
|
|
58
|
-
process.exit(e.status || 1);
|
|
59
|
-
}
|
|
60
|
-
});
|
|
61
|
-
}
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.registerValidate = registerValidate;
|
|
37
|
-
const path = __importStar(require("path"));
|
|
38
|
-
const package_1 = require("../lib/package");
|
|
39
|
-
const appPath_1 = require("../lib/appPath");
|
|
40
|
-
function registerValidate(program) {
|
|
41
|
-
program
|
|
42
|
-
.command('validate [appDirectory]')
|
|
43
|
-
.alias('apps:validate')
|
|
44
|
-
.description('Validate app structure and manifest')
|
|
45
|
-
.action(async (appDirectory = '.') => {
|
|
46
|
-
try {
|
|
47
|
-
(0, appPath_1.validateAppPath)(appDirectory);
|
|
48
|
-
const appPath = path.resolve(appDirectory);
|
|
49
|
-
await (0, package_1.validatePkg)(appPath);
|
|
50
|
-
console.log('No validation errors');
|
|
51
|
-
}
|
|
52
|
-
catch (err) {
|
|
53
|
-
console.error(err && err.message ? err.message : err);
|
|
54
|
-
process.exit(2);
|
|
55
|
-
}
|
|
56
|
-
});
|
|
57
|
-
}
|
package/dist/commands/version.js
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.registerVersion = registerVersion;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
function bumpVersion(v, level) {
|
|
10
|
-
const parts = v.split('.').map((s) => parseInt(s, 10));
|
|
11
|
-
while (parts.length < 3)
|
|
12
|
-
parts.push(0);
|
|
13
|
-
if (level === 'patch')
|
|
14
|
-
parts[2] = (parts[2] || 0) + 1;
|
|
15
|
-
if (level === 'minor') {
|
|
16
|
-
parts[1] = (parts[1] || 0) + 1;
|
|
17
|
-
parts[2] = 0;
|
|
18
|
-
}
|
|
19
|
-
if (level === 'major') {
|
|
20
|
-
parts[0] = (parts[0] || 0) + 1;
|
|
21
|
-
parts[1] = 0;
|
|
22
|
-
parts[2] = 0;
|
|
23
|
-
}
|
|
24
|
-
return parts.join('.');
|
|
25
|
-
}
|
|
26
|
-
function registerVersion(program) {
|
|
27
|
-
program
|
|
28
|
-
.command('version [source]')
|
|
29
|
-
.alias('apps:version')
|
|
30
|
-
.description('Show or bump app version')
|
|
31
|
-
.option('--bump <level>', 'patch|minor|major')
|
|
32
|
-
.option('--set <version>', 'set exact version')
|
|
33
|
-
.action((sourceArg, opts) => {
|
|
34
|
-
const manifestPath = path_1.default.resolve(process.cwd(), sourceArg || '.', 'manifest.json');
|
|
35
|
-
if (!fs_1.default.existsSync(manifestPath)) {
|
|
36
|
-
console.error('manifest.json not found at', manifestPath);
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
|
|
40
|
-
let version = manifest.version || '0.0.0';
|
|
41
|
-
if (opts.set) {
|
|
42
|
-
version = opts.set;
|
|
43
|
-
manifest.version = version;
|
|
44
|
-
fs_1.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
45
|
-
console.log(`Set version to ${version}`);
|
|
46
|
-
process.exit(0);
|
|
47
|
-
}
|
|
48
|
-
if (opts.bump) {
|
|
49
|
-
const level = opts.bump;
|
|
50
|
-
if (!['patch', 'minor', 'major'].includes(level)) {
|
|
51
|
-
console.error('Invalid bump level. Use patch, minor or major.');
|
|
52
|
-
process.exit(2);
|
|
53
|
-
}
|
|
54
|
-
version = bumpVersion(version, level);
|
|
55
|
-
manifest.version = version;
|
|
56
|
-
fs_1.default.writeFileSync(manifestPath, JSON.stringify(manifest, null, 2), 'utf8');
|
|
57
|
-
console.log(`Bumped version to ${version}`);
|
|
58
|
-
process.exit(0);
|
|
59
|
-
}
|
|
60
|
-
console.log(version);
|
|
61
|
-
});
|
|
62
|
-
}
|
package/dist/index.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
const commander_1 = require("commander");
|
|
5
|
-
const create_1 = require("./commands/create");
|
|
6
|
-
const run_1 = require("./commands/run");
|
|
7
|
-
const validate_1 = require("./commands/validate");
|
|
8
|
-
const pack_1 = require("./commands/pack");
|
|
9
|
-
const test_1 = require("./commands/test");
|
|
10
|
-
const version_1 = require("./commands/version");
|
|
11
|
-
const publish_1 = require("./commands/publish");
|
|
12
|
-
const help_1 = require("./commands/help");
|
|
13
|
-
const pkg = require('../package.json');
|
|
14
|
-
const program = new commander_1.Command();
|
|
15
|
-
program.name('bdk').version(pkg.version).description('BoldDesk Developer Kit CLI');
|
|
16
|
-
(0, create_1.registerCreate)(program);
|
|
17
|
-
(0, run_1.registerRun)(program);
|
|
18
|
-
(0, validate_1.registerValidate)(program);
|
|
19
|
-
(0, pack_1.registerPack)(program);
|
|
20
|
-
(0, test_1.registerTest)(program);
|
|
21
|
-
(0, version_1.registerVersion)(program);
|
|
22
|
-
(0, publish_1.registerPublish)(program);
|
|
23
|
-
(0, help_1.registerHelp)(program);
|
|
24
|
-
program.parse(process.argv);
|
package/dist/lib/appPath.js
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.validateAppPath = validateAppPath;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
function validateAppPath(appPath) {
|
|
10
|
-
const resolved = path_1.default.resolve(appPath);
|
|
11
|
-
if (!fs_1.default.existsSync(resolved))
|
|
12
|
-
throw new Error(`App path does not exist: ${resolved}`);
|
|
13
|
-
const manifest = path_1.default.join(resolved, 'manifest.json');
|
|
14
|
-
if (!fs_1.default.existsSync(manifest))
|
|
15
|
-
throw new Error(`manifest.json not found in ${resolved}`);
|
|
16
|
-
return true;
|
|
17
|
-
}
|
package/dist/lib/package.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.createAppPkg = createAppPkg;
|
|
7
|
-
exports.validatePkg = validatePkg;
|
|
8
|
-
const fs_1 = __importDefault(require("fs"));
|
|
9
|
-
const path_1 = __importDefault(require("path"));
|
|
10
|
-
const os_1 = __importDefault(require("os"));
|
|
11
|
-
const archiver_1 = __importDefault(require("archiver"));
|
|
12
|
-
async function createAppPkg(targetDir, appName) {
|
|
13
|
-
const outName = `${appName.replace(/[^a-z0-9-_]/gi, '-')}-${Date.now()}.zip`;
|
|
14
|
-
const outPath = path_1.default.join(os_1.default.tmpdir(), outName);
|
|
15
|
-
return new Promise((resolve, reject) => {
|
|
16
|
-
const output = fs_1.default.createWriteStream(outPath);
|
|
17
|
-
const archive = (0, archiver_1.default)('zip', { zlib: { level: 9 } });
|
|
18
|
-
output.on('close', () => resolve(outPath));
|
|
19
|
-
output.on('error', (err) => reject(err));
|
|
20
|
-
archive.on('error', (err) => reject(err));
|
|
21
|
-
archive.pipe(output);
|
|
22
|
-
archive.directory(targetDir, false);
|
|
23
|
-
archive.finalize();
|
|
24
|
-
});
|
|
25
|
-
}
|
|
26
|
-
async function validatePkg(appPath) {
|
|
27
|
-
const manifestPath = path_1.default.join(appPath, 'manifest.json');
|
|
28
|
-
if (!fs_1.default.existsSync(manifestPath))
|
|
29
|
-
throw new Error(`manifest.json not found in ${appPath}`);
|
|
30
|
-
const manifest = JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
|
|
31
|
-
const errors = [];
|
|
32
|
-
const isEmpty = (v) => v === undefined ||
|
|
33
|
-
v === null ||
|
|
34
|
-
(typeof v === 'string' && v.trim() === '') ||
|
|
35
|
-
(Array.isArray(v) && v.length === 0) ||
|
|
36
|
-
(typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length === 0);
|
|
37
|
-
// ── Top-level required fields ──
|
|
38
|
-
if (isEmpty(manifest.name)) {
|
|
39
|
-
errors.push("Missing required field in manifest: 'name'.");
|
|
40
|
-
}
|
|
41
|
-
if (isEmpty(manifest.version)) {
|
|
42
|
-
errors.push("Missing required field in manifest: 'version'.");
|
|
43
|
-
}
|
|
44
|
-
else if (!/^\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?$/.test(manifest.version)) {
|
|
45
|
-
errors.push(`Invalid 'version' format: "${manifest.version}". Expected semver (e.g., 1.0.0).`);
|
|
46
|
-
}
|
|
47
|
-
if (isEmpty(manifest.frameworkVersion)) {
|
|
48
|
-
errors.push("Framework version (frameworkVersion) is missing.");
|
|
49
|
-
}
|
|
50
|
-
if (isEmpty(manifest.defaultLocale)) {
|
|
51
|
-
errors.push("Missing required field in manifest: 'defaultLocale'.");
|
|
52
|
-
}
|
|
53
|
-
// ── Rule: 'author' field is not allowed (replaced by 'developer') ──
|
|
54
|
-
if ('author' in manifest) {
|
|
55
|
-
errors.push("The 'author' field is not allowed. Use the 'developer' block instead.");
|
|
56
|
-
}
|
|
57
|
-
// ── Rule: 'location' top-level is no longer valid (location belongs inside each widget) ──
|
|
58
|
-
if ('location' in manifest && !Array.isArray(manifest.location)) {
|
|
59
|
-
errors.push("Top-level 'location' field is not allowed. Define 'location' inside each widget under 'widgets'.");
|
|
60
|
-
}
|
|
61
|
-
// ── Rule: developer block validation (only 'name' is required) ──
|
|
62
|
-
if (isEmpty(manifest.developer) || typeof manifest.developer !== 'object') {
|
|
63
|
-
errors.push("The 'developer' block is missing. Please provide developer information.");
|
|
64
|
-
}
|
|
65
|
-
else {
|
|
66
|
-
if (isEmpty(manifest.developer.name)) {
|
|
67
|
-
errors.push("Developer validation failed: 'developer.name' is required.");
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
// ── Rule: widgets array & widget.location ──
|
|
71
|
-
if (!('widgets' in manifest)) {
|
|
72
|
-
errors.push("Missing required field in manifest: 'widgets'.");
|
|
73
|
-
}
|
|
74
|
-
else if (!Array.isArray(manifest.widgets) || manifest.widgets.length === 0) {
|
|
75
|
-
errors.push("'widgets' must be a non-empty array.");
|
|
76
|
-
}
|
|
77
|
-
else {
|
|
78
|
-
manifest.widgets.forEach((widget, index) => {
|
|
79
|
-
const label = widget && widget.name ? widget.name : `index ${index}`;
|
|
80
|
-
if (isEmpty(widget === null || widget === void 0 ? void 0 : widget.location)) {
|
|
81
|
-
errors.push(`Widget "${label}": location value is missing.`);
|
|
82
|
-
}
|
|
83
|
-
if (isEmpty(widget === null || widget === void 0 ? void 0 : widget.url)) {
|
|
84
|
-
errors.push(`Widget "${label}": url value is missing.`);
|
|
85
|
-
}
|
|
86
|
-
if (isEmpty(widget === null || widget === void 0 ? void 0 : widget.name)) {
|
|
87
|
-
errors.push(`Widget at index ${index}: name value is missing.`);
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
// ── Rule: OAuth validations ──
|
|
92
|
-
// If 'oauth' property is NOT present in manifest → skip entirely
|
|
93
|
-
// If 'oauth' property IS present (even with empty values) → all fields are required
|
|
94
|
-
if ('oauth' in manifest) {
|
|
95
|
-
const oauth = manifest.oauth;
|
|
96
|
-
if (!oauth || typeof oauth !== 'object') {
|
|
97
|
-
errors.push("'oauth' must be a valid object.");
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
const oauthFieldMap = {
|
|
101
|
-
clientId: 'oauth.clientId',
|
|
102
|
-
redirectUri: 'oauth.redirectUri',
|
|
103
|
-
authorizeUri: 'oauth.authorizeUri',
|
|
104
|
-
clientSecret: 'oauth.clientSecret',
|
|
105
|
-
accessTokenUri: 'oauth.accessTokenUri',
|
|
106
|
-
};
|
|
107
|
-
for (const [field, label] of Object.entries(oauthFieldMap)) {
|
|
108
|
-
if (isEmpty(oauth[field])) {
|
|
109
|
-
errors.push(`Missing required field: '${label}'.`);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
// ── Rule: settings.fields OAuth type check ──
|
|
115
|
-
// Only enforce when oauth block has actual values AND settings.fields is non-empty
|
|
116
|
-
if ('settings' in manifest) {
|
|
117
|
-
const settings = manifest.settings;
|
|
118
|
-
if (!settings || typeof settings !== 'object') {
|
|
119
|
-
errors.push("'settings' must be a valid object.");
|
|
120
|
-
}
|
|
121
|
-
else if (Array.isArray(settings.fields) && settings.fields.length > 0) {
|
|
122
|
-
// Each field object must have 'key' and 'type'
|
|
123
|
-
settings.fields.forEach((field, index) => {
|
|
124
|
-
const fieldLabel = field && field.key ? `"${field.key}"` : `index ${index}`;
|
|
125
|
-
if (isEmpty(field === null || field === void 0 ? void 0 : field.key)) {
|
|
126
|
-
errors.push(`settings.fields[${index}]: 'key' is required for each field object.`);
|
|
127
|
-
}
|
|
128
|
-
if (isEmpty(field === null || field === void 0 ? void 0 : field.type)) {
|
|
129
|
-
errors.push(`settings.fields[${fieldLabel}]: 'type' is required for each field object.`);
|
|
130
|
-
}
|
|
131
|
-
});
|
|
132
|
-
}
|
|
133
|
-
// If 'oauth' property is present in manifest → settings.fields must have at least one type "OAuth" field
|
|
134
|
-
if ('oauth' in manifest) {
|
|
135
|
-
const fields = Array.isArray(settings.fields) ? settings.fields : [];
|
|
136
|
-
const hasOAuthField = fields.some((field) => field && typeof field.type === 'string' && field.type.toLowerCase() === 'oauth');
|
|
137
|
-
if (!hasOAuthField) {
|
|
138
|
-
errors.push("settings.fields must contain at least one field with type 'OAuth' when oauth is configured. " +
|
|
139
|
-
'Example: { "key": "token", "type": "OAuth", "secure": true, "required": true, ... }');
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
if (errors.length > 0) {
|
|
144
|
-
throw new Error(`Validation errors in ${manifestPath}:\n - ${errors.join('\n - ')}`);
|
|
145
|
-
}
|
|
146
|
-
}
|
package/dist/utils/appConfig.js
DELETED
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getAllConfigs = getAllConfigs;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
function getAllConfigs(appPath) {
|
|
10
|
-
// Look for a config file (config.json or app.config.json). Return parsed object or empty.
|
|
11
|
-
const candidates = ['config.json', 'app.config.json'];
|
|
12
|
-
for (const c of candidates) {
|
|
13
|
-
const p = path_1.default.join(appPath, c);
|
|
14
|
-
if (fs_1.default.existsSync(p)) {
|
|
15
|
-
try {
|
|
16
|
-
return JSON.parse(fs_1.default.readFileSync(p, 'utf8'));
|
|
17
|
-
}
|
|
18
|
-
catch (e) {
|
|
19
|
-
return {};
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return {};
|
|
24
|
-
}
|
package/dist/utils/createApp.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.uploadAppPkg = uploadAppPkg;
|
|
7
|
-
exports.deployApp = deployApp;
|
|
8
|
-
exports.createProductInstallation = createProductInstallation;
|
|
9
|
-
const fs_1 = __importDefault(require("fs"));
|
|
10
|
-
const node_fetch_1 = __importDefault(require("node-fetch"));
|
|
11
|
-
const form_data_1 = __importDefault(require("form-data"));
|
|
12
|
-
async function uploadAppPkg(apiUrl, apiToken, pkgPath) {
|
|
13
|
-
const form = new form_data_1.default();
|
|
14
|
-
form.append('file', fs_1.default.createReadStream(pkgPath));
|
|
15
|
-
const headers = form.getHeaders();
|
|
16
|
-
headers['Authorization'] = `Bearer ${apiToken}`;
|
|
17
|
-
const res = await (0, node_fetch_1.default)(`${apiUrl.replace(/\/+$/, '')}/apps/upload`, {
|
|
18
|
-
method: 'POST',
|
|
19
|
-
headers,
|
|
20
|
-
body: form
|
|
21
|
-
});
|
|
22
|
-
if (!res.ok)
|
|
23
|
-
throw new Error(`Upload failed: ${res.status} ${res.statusText}`);
|
|
24
|
-
return res.json();
|
|
25
|
-
}
|
|
26
|
-
async function deployApp(apiUrl, apiToken, uploadId, name) {
|
|
27
|
-
const res = await (0, node_fetch_1.default)(`${apiUrl.replace(/\/+$/, '')}/apps/deploy`, {
|
|
28
|
-
method: 'POST',
|
|
29
|
-
headers: {
|
|
30
|
-
'Content-Type': 'application/json',
|
|
31
|
-
'Authorization': `Bearer ${apiToken}`
|
|
32
|
-
},
|
|
33
|
-
body: JSON.stringify({ upload_id: uploadId, name })
|
|
34
|
-
});
|
|
35
|
-
if (!res.ok)
|
|
36
|
-
throw new Error(`Deploy request failed: ${res.status} ${res.statusText}`);
|
|
37
|
-
return res.json();
|
|
38
|
-
}
|
|
39
|
-
async function createProductInstallation(apiUrl, apiToken, settings, manifest, appId, product) {
|
|
40
|
-
const url = `${apiUrl.replace(/\/+$/, '')}/products/${encodeURIComponent(product)}/installations`;
|
|
41
|
-
const res = await (0, node_fetch_1.default)(url, {
|
|
42
|
-
method: 'POST',
|
|
43
|
-
headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${apiToken}` },
|
|
44
|
-
body: JSON.stringify({ app_id: appId, settings, manifest })
|
|
45
|
-
});
|
|
46
|
-
return res.ok;
|
|
47
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAppSettings = getAppSettings;
|
|
4
|
-
async function getAppSettings(manifest, configParams = {}) {
|
|
5
|
-
const params = manifest.parameters || {};
|
|
6
|
-
const settings = {};
|
|
7
|
-
for (const [k, v] of Object.entries(params)) {
|
|
8
|
-
// prefer configParams value, otherwise manifest default, otherwise empty string
|
|
9
|
-
// @ts-ignore
|
|
10
|
-
settings[k] = (configParams && configParams[k] !== undefined) ? configParams[k] : ((v && v.default) ? v.default : '');
|
|
11
|
-
}
|
|
12
|
-
return settings;
|
|
13
|
-
}
|
package/dist/utils/manifest.js
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.getManifestFile = getManifestFile;
|
|
7
|
-
const fs_1 = __importDefault(require("fs"));
|
|
8
|
-
const path_1 = __importDefault(require("path"));
|
|
9
|
-
function getManifestFile(appPath) {
|
|
10
|
-
const manifestPath = path_1.default.resolve(appPath, 'manifest.json');
|
|
11
|
-
if (!fs_1.default.existsSync(manifestPath))
|
|
12
|
-
throw new Error(`manifest.json not found in ${appPath}`);
|
|
13
|
-
return JSON.parse(fs_1.default.readFileSync(manifestPath, 'utf8'));
|
|
14
|
-
}
|
package/dist/utils/uploadApp.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getUploadJobStatus = getUploadJobStatus;
|
|
4
|
-
async function getUploadJobStatus(apiUrl, apiToken, jobId, timeoutMs = 2 * 60 * 1000) {
|
|
5
|
-
const start = Date.now();
|
|
6
|
-
while (true) {
|
|
7
|
-
const res = await fetch(`${apiUrl.replace(/\/+$/, '')}/jobs/${jobId}`, {
|
|
8
|
-
method: 'GET',
|
|
9
|
-
headers: { 'Authorization': `Bearer ${apiToken}` }
|
|
10
|
-
});
|
|
11
|
-
if (!res.ok)
|
|
12
|
-
throw new Error(`Job status request failed: ${res.status} ${res.statusText}`);
|
|
13
|
-
const body = await res.json();
|
|
14
|
-
const status = body.status || body.state || '';
|
|
15
|
-
if (status === 'success' || status === 'completed' || status === 'ok') {
|
|
16
|
-
return body;
|
|
17
|
-
}
|
|
18
|
-
if (status === 'failed' || status === 'error') {
|
|
19
|
-
throw new Error(`Job failed: ${JSON.stringify(body)}`);
|
|
20
|
-
}
|
|
21
|
-
if (Date.now() - start > timeoutMs)
|
|
22
|
-
throw new Error('Timed out waiting for job to complete');
|
|
23
|
-
await new Promise((r) => setTimeout(r, 2000));
|
|
24
|
-
}
|
|
25
|
-
}
|