@adobe/ccweb-add-on-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.c8rc.json +14 -0
- package/.mocharc.json +5 -0
- package/CODE_OF_CONDUCT.md +79 -0
- package/CONTRIBUTING.md +47 -0
- package/LICENSE +21 -0
- package/README.md +11 -0
- package/dist/config/index.d.ts +26 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +26 -0
- package/dist/config/inversify.config.d.ts +28 -0
- package/dist/config/inversify.config.d.ts.map +1 -0
- package/dist/config/inversify.config.js +33 -0
- package/dist/config/inversify.types.d.ts +30 -0
- package/dist/config/inversify.types.d.ts.map +1 -0
- package/dist/config/inversify.types.js +30 -0
- package/dist/constants.d.ts +37 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +38 -0
- package/dist/index.d.ts +28 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +28 -0
- package/dist/models/PackageJson.d.ts +61 -0
- package/dist/models/PackageJson.d.ts.map +1 -0
- package/dist/models/PackageJson.js +76 -0
- package/dist/models/PreferenceJson.d.ts +79 -0
- package/dist/models/PreferenceJson.d.ts.map +1 -0
- package/dist/models/PreferenceJson.js +88 -0
- package/dist/models/TemplateJson.d.ts +53 -0
- package/dist/models/TemplateJson.d.ts.map +1 -0
- package/dist/models/TemplateJson.js +112 -0
- package/dist/models/Types.d.ts +72 -0
- package/dist/models/Types.d.ts.map +1 -0
- package/dist/models/Types.js +25 -0
- package/dist/models/index.d.ts +28 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +28 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/dist/utilities/CLIPreferences.d.ts +45 -0
- package/dist/utilities/CLIPreferences.d.ts.map +1 -0
- package/dist/utilities/CLIPreferences.js +80 -0
- package/dist/utilities/CLIProcess.d.ts +74 -0
- package/dist/utilities/CLIProcess.d.ts.map +1 -0
- package/dist/utilities/CLIProcess.js +190 -0
- package/dist/utilities/ConsoleLogger.d.ts +64 -0
- package/dist/utilities/ConsoleLogger.d.ts.map +1 -0
- package/dist/utilities/ConsoleLogger.js +103 -0
- package/dist/utilities/Extensions.d.ts +67 -0
- package/dist/utilities/Extensions.d.ts.map +1 -0
- package/dist/utilities/Extensions.js +92 -0
- package/dist/utilities/Logger.d.ts +65 -0
- package/dist/utilities/Logger.d.ts.map +1 -0
- package/dist/utilities/Logger.js +25 -0
- package/dist/utilities/Preferences.d.ts +41 -0
- package/dist/utilities/Preferences.d.ts.map +1 -0
- package/dist/utilities/Preferences.js +25 -0
- package/dist/utilities/Process.d.ts +63 -0
- package/dist/utilities/Process.d.ts.map +1 -0
- package/dist/utilities/Process.js +25 -0
- package/dist/utilities/UncaughtExceptionHandler.d.ts +40 -0
- package/dist/utilities/UncaughtExceptionHandler.d.ts.map +1 -0
- package/dist/utilities/UncaughtExceptionHandler.js +51 -0
- package/dist/utilities/index.d.ts +32 -0
- package/dist/utilities/index.d.ts.map +1 -0
- package/dist/utilities/index.js +32 -0
- package/package.json +51 -0
- package/src/config/index.ts +26 -0
- package/src/config/inversify.config.ts +39 -0
- package/src/config/inversify.types.ts +30 -0
- package/src/constants.ts +41 -0
- package/src/index.ts +28 -0
- package/src/models/PackageJson.ts +83 -0
- package/src/models/PreferenceJson.ts +112 -0
- package/src/models/TemplateJson.ts +121 -0
- package/src/models/Types.ts +80 -0
- package/src/models/index.ts +28 -0
- package/src/test/models/PackageJson.spec.ts +198 -0
- package/src/test/models/PreferenceJson.spec.ts +184 -0
- package/src/test/models/TemplateJson.spec.ts +179 -0
- package/src/test/utilities/CLIPreferences.spec.ts +208 -0
- package/src/test/utilities/CLIProcess.spec.ts +363 -0
- package/src/test/utilities/ConsoleLogger.spec.ts +165 -0
- package/src/test/utilities/Extensions.spec.ts +240 -0
- package/src/test/utilities/UncaughtExceptionHandler.spec.ts +83 -0
- package/src/types/applicationConfigPath.d.ts +1 -0
- package/src/utilities/CLIPreferences.ts +84 -0
- package/src/utilities/CLIProcess.ts +200 -0
- package/src/utilities/ConsoleLogger.ts +111 -0
- package/src/utilities/Extensions.ts +98 -0
- package/src/utilities/Logger.ts +70 -0
- package/src/utilities/Preferences.ts +43 -0
- package/src/utilities/Process.ts +66 -0
- package/src/utilities/UncaughtExceptionHandler.ts +55 -0
- package/src/utilities/index.ts +32 -0
- package/tsconfig.json +31 -0
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* MIT License
|
|
3
|
+
|
|
4
|
+
* © Copyright 2023 Adobe. All rights reserved.
|
|
5
|
+
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
********************************************************************************/
|
|
24
|
+
|
|
25
|
+
import { assert } from "chai";
|
|
26
|
+
import chalk from "chalk";
|
|
27
|
+
import "mocha";
|
|
28
|
+
import type { SinonSandbox } from "sinon";
|
|
29
|
+
import sinon from "sinon";
|
|
30
|
+
import type { Logger } from "../../utilities/index.js";
|
|
31
|
+
import { ConsoleLogger } from "../../utilities/index.js";
|
|
32
|
+
|
|
33
|
+
describe("ConsoleLogger", () => {
|
|
34
|
+
let sandbox: SinonSandbox;
|
|
35
|
+
let logger: Logger;
|
|
36
|
+
|
|
37
|
+
beforeEach(() => {
|
|
38
|
+
sandbox = sinon.createSandbox();
|
|
39
|
+
logger = new ConsoleLogger();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
afterEach(() => {
|
|
43
|
+
sandbox.restore();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe("message ...", () => {
|
|
47
|
+
const runs = [{ message: "" }, { message: " " }, { message: "Information Message" }];
|
|
48
|
+
runs.forEach(run => {
|
|
49
|
+
it(`should log message: '${run.message}' in console.`, () => {
|
|
50
|
+
const consoleLogStub = sandbox.stub(console, "log");
|
|
51
|
+
logger.message(run.message);
|
|
52
|
+
assert.equal(consoleLogStub.callCount, 1);
|
|
53
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(run.message));
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
describe("information ...", () => {
|
|
59
|
+
const runs = [
|
|
60
|
+
{ message: "" },
|
|
61
|
+
{ message: " " },
|
|
62
|
+
{ message: "Information Message" },
|
|
63
|
+
{ message: "Information Message", postfix: "\n" }
|
|
64
|
+
];
|
|
65
|
+
runs.forEach(run => {
|
|
66
|
+
it(`should log message: '${run.message}' in console.`, () => {
|
|
67
|
+
const consoleLogStub = sandbox.stub(console, "log");
|
|
68
|
+
|
|
69
|
+
logger.information(run.message, { postfix: run.postfix });
|
|
70
|
+
|
|
71
|
+
let loggedMessage = run.message;
|
|
72
|
+
if (run.postfix) {
|
|
73
|
+
loggedMessage = `${loggedMessage}${run.postfix}`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
assert.equal(consoleLogStub.callCount, 1);
|
|
77
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(chalk.cyan.bold(loggedMessage)));
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
describe("success ...", () => {
|
|
83
|
+
const runs = [
|
|
84
|
+
{ message: "" },
|
|
85
|
+
{ message: " " },
|
|
86
|
+
{ message: "Success Message" },
|
|
87
|
+
{ message: "Success Message", prefix: "\n" }
|
|
88
|
+
];
|
|
89
|
+
runs.forEach(run => {
|
|
90
|
+
it(`should log message: '${run.message}' in console.`, () => {
|
|
91
|
+
const consoleLogStub = sandbox.stub(console, "log");
|
|
92
|
+
|
|
93
|
+
logger.success(run.message, { prefix: run.prefix });
|
|
94
|
+
|
|
95
|
+
let loggedMessage = run.message;
|
|
96
|
+
if (run.prefix) {
|
|
97
|
+
loggedMessage = `${run.prefix}${run.message}`;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
assert.equal(consoleLogStub.callCount, 1);
|
|
101
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(chalk.green.bold(loggedMessage)));
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe("warning ...", () => {
|
|
107
|
+
const runs = [
|
|
108
|
+
{ message: "" },
|
|
109
|
+
{ message: " " },
|
|
110
|
+
{ message: "Warning Message" },
|
|
111
|
+
{ message: "Warning Message", prefix: "[", postfix: "]" }
|
|
112
|
+
];
|
|
113
|
+
runs.forEach(run => {
|
|
114
|
+
it(`should log message: '${run.message}' in console.`, () => {
|
|
115
|
+
const consoleLogStub = sandbox.stub(console, "log");
|
|
116
|
+
|
|
117
|
+
logger.warning(run.message, { prefix: run.prefix, postfix: run.postfix });
|
|
118
|
+
|
|
119
|
+
let loggedMessage = run.message;
|
|
120
|
+
if (run.prefix) {
|
|
121
|
+
loggedMessage = `${run.prefix}${run.message}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (run.postfix) {
|
|
125
|
+
loggedMessage = `${loggedMessage}${run.postfix}`;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
assert.equal(consoleLogStub.callCount, 1);
|
|
129
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(chalk.hex("#E59400").bold(loggedMessage)));
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
describe("error ...", () => {
|
|
135
|
+
const runs = [
|
|
136
|
+
{ message: "" },
|
|
137
|
+
{ message: " " },
|
|
138
|
+
{ message: "Error Message" },
|
|
139
|
+
{ message: new Error("Error Message") },
|
|
140
|
+
{ message: new Error("Error Message"), prefix: "\n", postfix: "\n" }
|
|
141
|
+
];
|
|
142
|
+
runs.forEach(run => {
|
|
143
|
+
it(`should log message: '${run.message}' in console.`, () => {
|
|
144
|
+
const consoleLogStub = sandbox.stub(console, "log");
|
|
145
|
+
|
|
146
|
+
logger.error(run.message, { prefix: run.prefix, postfix: run.postfix });
|
|
147
|
+
|
|
148
|
+
let consoleLogStubCount = 1;
|
|
149
|
+
if (run.prefix) {
|
|
150
|
+
consoleLogStubCount++;
|
|
151
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(chalk.red(run.prefix)));
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(chalk.red(run.message)));
|
|
155
|
+
|
|
156
|
+
if (run.postfix) {
|
|
157
|
+
consoleLogStubCount++;
|
|
158
|
+
sinon.assert.calledWith(consoleLogStub, sinon.match(chalk.red(run.prefix)));
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
assert.equal(consoleLogStub.callCount, consoleLogStubCount);
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
});
|
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* MIT License
|
|
3
|
+
|
|
4
|
+
* © Copyright 2023 Adobe. All rights reserved.
|
|
5
|
+
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
********************************************************************************/
|
|
24
|
+
|
|
25
|
+
import { assert } from "chai";
|
|
26
|
+
import type { Stats } from "fs";
|
|
27
|
+
import type { Dirent } from "fs-extra";
|
|
28
|
+
import fs from "fs-extra";
|
|
29
|
+
import "mocha";
|
|
30
|
+
import path from "path";
|
|
31
|
+
import type { SinonSandbox } from "sinon";
|
|
32
|
+
import sinon from "sinon";
|
|
33
|
+
import {
|
|
34
|
+
getBaseUrl,
|
|
35
|
+
getJSONString,
|
|
36
|
+
isFile,
|
|
37
|
+
isNullOrWhiteSpace,
|
|
38
|
+
isObject,
|
|
39
|
+
removeSymbols,
|
|
40
|
+
traverseDirectory
|
|
41
|
+
} from "../../utilities/Extensions.js";
|
|
42
|
+
|
|
43
|
+
describe("Extensions", () => {
|
|
44
|
+
describe("getJSONString", () => {
|
|
45
|
+
it(`should return stringify-ed PackageJson with properties except for the undefined ones.`, () => {
|
|
46
|
+
const item = {
|
|
47
|
+
foo: "bar",
|
|
48
|
+
baz: "etc"
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const itemJSONString = getJSONString(item);
|
|
52
|
+
|
|
53
|
+
assert.equal(removeSymbols(itemJSONString), removeSymbols(`{ "foo": "bar", "baz": "etc"}`));
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
describe("isNullOrWhiteSpace", () => {
|
|
58
|
+
let runs = [{ value: null }, { value: undefined }, { value: "" }, { value: " " }, { value: " " }];
|
|
59
|
+
runs.forEach(run => {
|
|
60
|
+
it("should return true for a null, undefined or whitespace.", () => {
|
|
61
|
+
assert.equal(isNullOrWhiteSpace(run.value), true);
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
runs = [{ value: "foo bar" }, { value: " foo bar " }];
|
|
66
|
+
runs.forEach(run => {
|
|
67
|
+
it("should return false for not a null or undefined or whitespace.", () => {
|
|
68
|
+
assert.equal(isNullOrWhiteSpace(run.value), false);
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("isObject", () => {
|
|
74
|
+
let runs: { value: unknown }[] = [
|
|
75
|
+
{ value: null },
|
|
76
|
+
{ value: undefined },
|
|
77
|
+
{ value: "hello world" },
|
|
78
|
+
{ value: 10 },
|
|
79
|
+
{ value: true }
|
|
80
|
+
];
|
|
81
|
+
runs.forEach(run => {
|
|
82
|
+
it("should return false for a null, undefined or any primitive type.", () => {
|
|
83
|
+
assert.equal(isObject(run.value), false);
|
|
84
|
+
});
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
runs = [
|
|
88
|
+
{ value: { foo: "bar" } },
|
|
89
|
+
{ value: ["hello", "world"] },
|
|
90
|
+
{ value: new Set([1, 2, 3]) },
|
|
91
|
+
{ value: new Map([["foo", "bar"]]) }
|
|
92
|
+
];
|
|
93
|
+
runs.forEach(run => {
|
|
94
|
+
it("should return true for an object, array or any iterable.", () => {
|
|
95
|
+
assert.equal(isObject(run.value), true);
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("traverseDirectory", () => {
|
|
101
|
+
let sandbox: SinonSandbox;
|
|
102
|
+
beforeEach(() => {
|
|
103
|
+
sandbox = sinon.createSandbox();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
afterEach(() => {
|
|
107
|
+
sandbox.restore();
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("should traverse through all files recursively in a directory and execute action on each file.", () => {
|
|
111
|
+
const logStub = sandbox.stub(console, "log");
|
|
112
|
+
logStub.returns();
|
|
113
|
+
|
|
114
|
+
const rootDirectory = "root";
|
|
115
|
+
const childDirectory = "child";
|
|
116
|
+
const rootFiles = [
|
|
117
|
+
{ name: "file-1.html" },
|
|
118
|
+
{ name: "file-2.js" },
|
|
119
|
+
{ name: "file-3.css" },
|
|
120
|
+
{ name: childDirectory }
|
|
121
|
+
] as Dirent[];
|
|
122
|
+
const readDirStub = sandbox.stub(fs, "readdirSync");
|
|
123
|
+
readDirStub.withArgs(rootDirectory, { withFileTypes: true }).returns(rootFiles);
|
|
124
|
+
|
|
125
|
+
const directoryStats = <Stats>{
|
|
126
|
+
isDirectory: () => {
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
const fileStats = <Stats>{
|
|
131
|
+
isDirectory: () => {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
const lstatStub = sandbox.stub(fs, "lstatSync");
|
|
137
|
+
rootFiles.forEach(file => {
|
|
138
|
+
if (file.name === childDirectory) {
|
|
139
|
+
lstatStub.withArgs(path.join(rootDirectory, file.name)).returns(directoryStats);
|
|
140
|
+
} else {
|
|
141
|
+
lstatStub.withArgs(path.join(rootDirectory, file.name)).returns(fileStats);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const childFiles = [{ name: "file-4.ts" }, { name: "file-5.tsx" }] as Dirent[];
|
|
146
|
+
readDirStub.withArgs(path.join(rootDirectory, childDirectory), { withFileTypes: true }).returns(childFiles);
|
|
147
|
+
childFiles.forEach(file => {
|
|
148
|
+
lstatStub.withArgs(path.join(rootDirectory, childDirectory, file.name)).returns(fileStats);
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
traverseDirectory(rootDirectory, file => console.log(file));
|
|
152
|
+
|
|
153
|
+
assert.equal(logStub.callCount, 5);
|
|
154
|
+
sinon.assert.calledWith(logStub.getCall(0), sinon.match(path.join(rootDirectory, "file-1.html")));
|
|
155
|
+
sinon.assert.calledWith(logStub.getCall(1), sinon.match(path.join(rootDirectory, "file-2.js")));
|
|
156
|
+
sinon.assert.calledWith(logStub.getCall(2), sinon.match(path.join(rootDirectory, "file-3.css")));
|
|
157
|
+
sinon.assert.calledWith(
|
|
158
|
+
logStub.getCall(3),
|
|
159
|
+
sinon.match(path.join(rootDirectory, childDirectory, "file-4.ts"))
|
|
160
|
+
);
|
|
161
|
+
sinon.assert.calledWith(
|
|
162
|
+
logStub.getCall(4),
|
|
163
|
+
sinon.match(path.join(rootDirectory, childDirectory, "file-5.tsx"))
|
|
164
|
+
);
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe("getBaseUrl", () => {
|
|
169
|
+
const runs = [
|
|
170
|
+
{
|
|
171
|
+
protocol: "https",
|
|
172
|
+
host: "localhost:5241",
|
|
173
|
+
expectedBaseUrl: "https://localhost:5241/"
|
|
174
|
+
},
|
|
175
|
+
{
|
|
176
|
+
protocol: "https",
|
|
177
|
+
host: "spice.adobe.com",
|
|
178
|
+
expectedBaseUrl: "https://spice.adobe.com/"
|
|
179
|
+
},
|
|
180
|
+
{ protocol: "wss", host: "localhost:5241", expectedBaseUrl: "wss://localhost:5241/" },
|
|
181
|
+
{ protocol: "wss", host: "spice.adobe.com", expectedBaseUrl: "wss://spice.adobe.com/" }
|
|
182
|
+
];
|
|
183
|
+
runs.forEach(run => {
|
|
184
|
+
it("should return the Base URL from protocol and host.", () => {
|
|
185
|
+
const baseUrl = getBaseUrl(run.protocol, run.host);
|
|
186
|
+
assert.equal(baseUrl, run.expectedBaseUrl);
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
describe("removeSymbols", () => {
|
|
192
|
+
it("should remove symbols from a string.", () => {
|
|
193
|
+
const value = "Hello\n\r\tWorld";
|
|
194
|
+
const expectedValue = "HelloWorld";
|
|
195
|
+
|
|
196
|
+
assert.equal(removeSymbols(value), expectedValue);
|
|
197
|
+
});
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
describe("isFile", () => {
|
|
201
|
+
let sandbox: SinonSandbox;
|
|
202
|
+
beforeEach(() => {
|
|
203
|
+
sandbox = sinon.createSandbox();
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
afterEach(() => {
|
|
207
|
+
sandbox.restore();
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("should return false when the path does not exist.", () => {
|
|
211
|
+
const path = "foo/bar/";
|
|
212
|
+
|
|
213
|
+
sandbox.stub(fs, "existsSync").returns(false);
|
|
214
|
+
|
|
215
|
+
assert.equal(isFile(path), false);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("should return false when the path is a directory.", () => {
|
|
219
|
+
const path = "foo/bar/";
|
|
220
|
+
|
|
221
|
+
sandbox.stub(fs, "existsSync").returns(true);
|
|
222
|
+
|
|
223
|
+
const directoryStats = <Stats>{ isFile: () => false };
|
|
224
|
+
sandbox.stub(fs, "lstatSync").returns(directoryStats);
|
|
225
|
+
|
|
226
|
+
assert.equal(isFile(path), false);
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it("should return true when the path is of a file.", () => {
|
|
230
|
+
const path = "foo/bar/";
|
|
231
|
+
|
|
232
|
+
sandbox.stub(fs, "existsSync").returns(true);
|
|
233
|
+
|
|
234
|
+
const directoryStats = <Stats>{ isFile: () => true };
|
|
235
|
+
sandbox.stub(fs, "lstatSync").returns(directoryStats);
|
|
236
|
+
|
|
237
|
+
assert.equal(isFile(path), true);
|
|
238
|
+
});
|
|
239
|
+
});
|
|
240
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* MIT License
|
|
3
|
+
|
|
4
|
+
* © Copyright 2023 Adobe. All rights reserved.
|
|
5
|
+
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
********************************************************************************/
|
|
24
|
+
|
|
25
|
+
import { assert } from "chai";
|
|
26
|
+
import "mocha";
|
|
27
|
+
import process from "process";
|
|
28
|
+
import type { SinonSandbox } from "sinon";
|
|
29
|
+
import sinon from "sinon";
|
|
30
|
+
import type { StubbedInstance } from "ts-sinon";
|
|
31
|
+
import { stubInterface } from "ts-sinon";
|
|
32
|
+
import { IContainer, ITypes } from "../../config/index.js";
|
|
33
|
+
import type { Logger } from "../../utilities/Logger.js";
|
|
34
|
+
import { UncaughtExceptionHandler } from "../../utilities/index.js";
|
|
35
|
+
|
|
36
|
+
describe("UncaughtExceptionHandler", () => {
|
|
37
|
+
let sandbox: SinonSandbox;
|
|
38
|
+
let logger: StubbedInstance<Logger>;
|
|
39
|
+
|
|
40
|
+
beforeEach(() => {
|
|
41
|
+
sandbox = sinon.createSandbox();
|
|
42
|
+
logger = stubInterface<Logger>();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
sandbox.restore();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("registerExceptionHandler", () => {
|
|
50
|
+
it("should register a handler for an 'uncaughtException'.", () => {
|
|
51
|
+
const processOnStub = sandbox.stub(process, "on");
|
|
52
|
+
processOnStub.resolves();
|
|
53
|
+
|
|
54
|
+
const programName = "test-program";
|
|
55
|
+
UncaughtExceptionHandler.registerExceptionHandler(programName);
|
|
56
|
+
|
|
57
|
+
assert.equal(processOnStub.getCall(0).args[0], "uncaughtException");
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
describe("handleUncaughtException", () => {
|
|
62
|
+
it("should log error and exit when an uncaught exception is encountered.", async () => {
|
|
63
|
+
const processExitStub = sandbox.stub(process, "exit");
|
|
64
|
+
processExitStub.resolves();
|
|
65
|
+
|
|
66
|
+
logger.error.returns();
|
|
67
|
+
|
|
68
|
+
const coreContainerStub = sandbox.stub(IContainer, "get");
|
|
69
|
+
coreContainerStub.withArgs(ITypes.Logger).returns(logger);
|
|
70
|
+
|
|
71
|
+
const programName = "test-program";
|
|
72
|
+
const error = new Error("Unexpected error.");
|
|
73
|
+
|
|
74
|
+
UncaughtExceptionHandler.handleUncaughtException(programName, error);
|
|
75
|
+
|
|
76
|
+
assert.equal(
|
|
77
|
+
logger.error.calledWith(`${programName} failed. Reason: ${error.message}`, { postfix: "\n" }),
|
|
78
|
+
true
|
|
79
|
+
);
|
|
80
|
+
assert.equal(processExitStub.calledWith(0), true);
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
declare module "application-config-path";
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* MIT License
|
|
3
|
+
|
|
4
|
+
* © Copyright 2023 Adobe. All rights reserved.
|
|
5
|
+
|
|
6
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
* of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
* in the Software without restriction, including without limitation the rights
|
|
9
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
* copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
* furnished to do so, subject to the following conditions:
|
|
12
|
+
*
|
|
13
|
+
* The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
* copies or substantial portions of the Software.
|
|
15
|
+
*
|
|
16
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
* SOFTWARE.
|
|
23
|
+
********************************************************************************/
|
|
24
|
+
|
|
25
|
+
import applicationConfigPath from "application-config-path";
|
|
26
|
+
import fs from "fs-extra";
|
|
27
|
+
import hjson from "hjson";
|
|
28
|
+
import { injectable } from "inversify";
|
|
29
|
+
import os from "os";
|
|
30
|
+
import path from "path";
|
|
31
|
+
import "reflect-metadata";
|
|
32
|
+
import { ADD_ON_PREFERENCES_FILE, CCWEB_ADDON_DIRECTORY } from "../constants.js";
|
|
33
|
+
import { PreferenceJson } from "../models/PreferenceJson.js";
|
|
34
|
+
import type { Preferences } from "./Preferences.js";
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Implementation class for configuring CCWeb Add-on CLI related preferences.
|
|
38
|
+
*/
|
|
39
|
+
@injectable()
|
|
40
|
+
export class CLIPreferences implements Preferences {
|
|
41
|
+
private _cachedPreference?: PreferenceJson;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get the CCWeb Add-on CLI related user preferences.
|
|
45
|
+
* @param fromCache - (Optional) Whether to return the cached user preference.
|
|
46
|
+
* @returns User preference represented as {@link PreferenceJson}.
|
|
47
|
+
*/
|
|
48
|
+
get(fromCache?: boolean): PreferenceJson {
|
|
49
|
+
if (fromCache && this._cachedPreference !== undefined) {
|
|
50
|
+
return this._cachedPreference;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
try {
|
|
54
|
+
const preferenceFilePath = this._preferenceFilePath;
|
|
55
|
+
if (!fs.existsSync(preferenceFilePath)) {
|
|
56
|
+
fs.ensureFileSync(preferenceFilePath);
|
|
57
|
+
fs.writeFileSync(preferenceFilePath, JSON.stringify({}, undefined, 4) + os.EOL);
|
|
58
|
+
|
|
59
|
+
return new PreferenceJson({});
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const preferenceData = fs.readFileSync(preferenceFilePath, "utf-8").trim();
|
|
63
|
+
this._cachedPreference = new PreferenceJson(hjson.parse(preferenceData));
|
|
64
|
+
|
|
65
|
+
return this._cachedPreference;
|
|
66
|
+
} catch {
|
|
67
|
+
// Do not cache the preference when any error is encountered.
|
|
68
|
+
return new PreferenceJson({});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Set the CCWeb Add-on CLI related user preferences.
|
|
74
|
+
* @param preferenceJson - {@link PreferenceJson} reference.
|
|
75
|
+
*/
|
|
76
|
+
set(preferenceJson: PreferenceJson): void {
|
|
77
|
+
fs.writeFileSync(this._preferenceFilePath, preferenceJson.toJSON() + os.EOL);
|
|
78
|
+
this._cachedPreference = preferenceJson;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private get _preferenceFilePath(): string {
|
|
82
|
+
return path.join(applicationConfigPath(CCWEB_ADDON_DIRECTORY), ADD_ON_PREFERENCES_FILE);
|
|
83
|
+
}
|
|
84
|
+
}
|