askui 0.2.0 → 0.2.1
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/README.md +2 -2
- package/bin/askui-postinstall +35 -0
- package/dist/cjs/core/model/test-case-dto/index.js +1 -3
- package/dist/cjs/core/model/test-case-dto/test-step.d.ts +3 -7
- package/dist/cjs/core/model/test-case-dto/test-step.js +0 -12
- package/dist/cjs/core/ui-control-commands/control-command.d.ts +1 -0
- package/dist/cjs/core/ui-control-commands/control-command.js +5 -0
- package/dist/cjs/core/ui-control-commands/input-event.d.ts +1 -2
- package/dist/cjs/core/ui-control-commands/input-event.js +0 -1
- package/dist/cjs/execution/execution-runtime.d.ts +2 -0
- package/dist/cjs/execution/execution-runtime.js +27 -15
- package/dist/cjs/execution/inference-client.d.ts +1 -1
- package/dist/cjs/execution/inference-client.js +1 -1
- package/dist/cjs/execution/ui-control-client.d.ts +46 -1
- package/dist/cjs/execution/ui-control-client.js +55 -5
- package/dist/cjs/lib/copy-example-project.js +2 -1
- package/dist/cjs/lib/download-binaries.js +2 -1
- package/dist/cjs/lib/ui-controller-linux.js +2 -2
- package/dist/cjs/utils/analytics/analytics.js +7 -1
- package/dist/cjs/utils/analytics/installation-timestamp-create-error.d.ts +4 -0
- package/dist/cjs/utils/analytics/installation-timestamp-create-error.js +9 -0
- package/dist/cjs/utils/analytics/installation-timestamp-get-error.d.ts +4 -0
- package/dist/cjs/utils/analytics/installation-timestamp-get-error.js +9 -0
- package/dist/cjs/utils/analytics/installation-timestamp.d.ts +7 -0
- package/dist/cjs/utils/analytics/installation-timestamp.js +68 -0
- package/dist/cjs/utils/path.d.ts +1 -0
- package/dist/cjs/utils/path.js +11 -0
- package/dist/esm/core/model/test-case-dto/index.js +0 -1
- package/dist/esm/core/model/test-case-dto/test-step.d.ts +3 -7
- package/dist/esm/core/model/test-case-dto/test-step.js +1 -10
- package/dist/esm/core/ui-control-commands/control-command.d.ts +1 -0
- package/dist/esm/core/ui-control-commands/control-command.js +5 -0
- package/dist/esm/core/ui-control-commands/input-event.d.ts +1 -2
- package/dist/esm/core/ui-control-commands/input-event.js +0 -1
- package/dist/esm/execution/execution-runtime.d.ts +2 -0
- package/dist/esm/execution/execution-runtime.js +27 -15
- package/dist/esm/execution/inference-client.d.ts +1 -1
- package/dist/esm/execution/inference-client.js +1 -1
- package/dist/esm/execution/ui-control-client.d.ts +46 -1
- package/dist/esm/execution/ui-control-client.js +56 -6
- package/dist/esm/lib/copy-example-project.js +2 -1
- package/dist/esm/lib/download-binaries.js +2 -1
- package/dist/esm/lib/ui-controller-linux.js +2 -2
- package/dist/esm/utils/analytics/analytics.js +7 -1
- package/dist/esm/utils/analytics/installation-timestamp-create-error.d.ts +4 -0
- package/dist/esm/utils/analytics/installation-timestamp-create-error.js +5 -0
- package/dist/esm/utils/analytics/installation-timestamp-get-error.d.ts +4 -0
- package/dist/esm/utils/analytics/installation-timestamp-get-error.js +5 -0
- package/dist/esm/utils/analytics/installation-timestamp.d.ts +7 -0
- package/dist/esm/utils/analytics/installation-timestamp.js +61 -0
- package/dist/esm/utils/path.d.ts +1 -0
- package/dist/esm/utils/path.js +4 -0
- package/package.json +7 -3
- package/dist/cjs/utils/base_64_image/base-64-image-path-error.d.ts +0 -4
- package/dist/cjs/utils/base_64_image/base-64-image-path-error.js +0 -11
- package/dist/cjs/utils/image-resize-errors/invalid-base64-image-error.d.ts +0 -3
- package/dist/cjs/utils/image-resize-errors/invalid-base64-image-error.js +0 -7
- package/dist/esm/utils/base_64_image/base-64-image-path-error.d.ts +0 -4
- package/dist/esm/utils/base_64_image/base-64-image-path-error.js +0 -7
- package/dist/esm/utils/image-resize-errors/invalid-base64-image-error.d.ts +0 -3
- package/dist/esm/utils/image-resize-errors/invalid-base64-image-error.js +0 -3
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Action } from './action';
|
|
2
2
|
import { ControlCommandCode } from './control-command-code';
|
|
3
|
+
import { InputEvent } from './input-event';
|
|
3
4
|
export class ControlCommand {
|
|
4
5
|
constructor(code, actions, tryToRepeat = false) {
|
|
5
6
|
this.code = code;
|
|
@@ -9,4 +10,8 @@ export class ControlCommand {
|
|
|
9
10
|
static fromJson(json, resizeRatio = 1) {
|
|
10
11
|
return new ControlCommand(ControlCommandCode[json.code], json.actions.map((action) => Action.fromJson(action, resizeRatio)), json.tryToRepeat);
|
|
11
12
|
}
|
|
13
|
+
setTextToBeTyped(text) {
|
|
14
|
+
this.actions = this.actions.map((action) => ([InputEvent.TYPE, InputEvent.TYPE_TEXT].includes(action.inputEvent)
|
|
15
|
+
? new Action(action.inputEvent, action.position, text) : action));
|
|
16
|
+
}
|
|
12
17
|
}
|
|
@@ -8,6 +8,7 @@ export declare class ExecutionRuntime {
|
|
|
8
8
|
private inferenceClient;
|
|
9
9
|
constructor(uiControllerClient: UiControllerClient, inferenceClient: InferenceClient);
|
|
10
10
|
executeTestStep(step: TestStep): Promise<void>;
|
|
11
|
+
private requestControl;
|
|
11
12
|
/**
|
|
12
13
|
* @param {TestStep} step - Test step used for predicting command.
|
|
13
14
|
*/
|
|
@@ -20,6 +21,7 @@ export declare class ExecutionRuntime {
|
|
|
20
21
|
* --> retry with linear back-off
|
|
21
22
|
*/
|
|
22
23
|
private predictCommandWithRetry;
|
|
24
|
+
private getImageIfRequired;
|
|
23
25
|
private predictCommand;
|
|
24
26
|
annotateInteractively(): Promise<void>;
|
|
25
27
|
takeScreenshotIfImageisNotProvided(imagePath?: string): Promise<string>;
|
|
@@ -27,6 +27,11 @@ export class ExecutionRuntime {
|
|
|
27
27
|
yield this.executeCommand(step);
|
|
28
28
|
});
|
|
29
29
|
}
|
|
30
|
+
requestControl(controlCommand) {
|
|
31
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
32
|
+
yield this.uiControllerClient.requestControl(controlCommand);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
30
35
|
/**
|
|
31
36
|
* @param {TestStep} step - Test step used for predicting command.
|
|
32
37
|
*/
|
|
@@ -35,15 +40,13 @@ export class ExecutionRuntime {
|
|
|
35
40
|
return __awaiter(this, void 0, void 0, function* () {
|
|
36
41
|
const controlCommand = yield this.predictCommandWithRetry(step);
|
|
37
42
|
if (controlCommand.code === ControlCommandCode.OK) {
|
|
38
|
-
|
|
43
|
+
return this.requestControl(controlCommand);
|
|
39
44
|
}
|
|
40
|
-
|
|
41
|
-
yield this.
|
|
42
|
-
this.executeCommandRepeatedly(step);
|
|
43
|
-
}
|
|
44
|
-
else {
|
|
45
|
-
throw new ControlCommandError(((_a = controlCommand.actions[0]) === null || _a === void 0 ? void 0 : _a.text) || '');
|
|
45
|
+
if (controlCommand.tryToRepeat) {
|
|
46
|
+
yield this.requestControl(controlCommand);
|
|
47
|
+
return this.executeCommandRepeatedly(step);
|
|
46
48
|
}
|
|
49
|
+
throw new ControlCommandError(((_a = controlCommand.actions[0]) === null || _a === void 0 ? void 0 : _a.text) || '');
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
executeCommandRepeatedly(step) {
|
|
@@ -60,8 +63,8 @@ export class ExecutionRuntime {
|
|
|
60
63
|
if (controlCommand.code === ControlCommandCode.OK) {
|
|
61
64
|
break;
|
|
62
65
|
}
|
|
63
|
-
|
|
64
|
-
yield this.
|
|
66
|
+
if (controlCommand.tryToRepeat) {
|
|
67
|
+
yield this.requestControl(controlCommand);
|
|
65
68
|
}
|
|
66
69
|
else {
|
|
67
70
|
throw new ControlCommandError(((_a = controlCommand.actions[0]) === null || _a === void 0 ? void 0 : _a.text) || '');
|
|
@@ -91,15 +94,24 @@ export class ExecutionRuntime {
|
|
|
91
94
|
return command;
|
|
92
95
|
});
|
|
93
96
|
}
|
|
97
|
+
getImageIfRequired(instruction) {
|
|
98
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
99
|
+
const isImageRequired = yield this.inferenceClient.isImageRequired(instruction);
|
|
100
|
+
if (!isImageRequired) {
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
const screenshotResponse = yield this.uiControllerClient.requestScreenshot();
|
|
104
|
+
return screenshotResponse.data.image;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
94
107
|
predictCommand(step) {
|
|
95
108
|
return __awaiter(this, void 0, void 0, function* () {
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
if (
|
|
99
|
-
|
|
100
|
-
image = screenshotResponse.data.image;
|
|
109
|
+
const image = yield this.getImageIfRequired(step.instruction);
|
|
110
|
+
const controlCommand = yield this.inferenceClient.predictControlCommand(step.instruction, step.customElements, image);
|
|
111
|
+
if (step.secretText !== undefined) {
|
|
112
|
+
controlCommand.setTextToBeTyped(step.secretText);
|
|
101
113
|
}
|
|
102
|
-
return
|
|
114
|
+
return controlCommand;
|
|
103
115
|
});
|
|
104
116
|
}
|
|
105
117
|
annotateInteractively() {
|
|
@@ -8,6 +8,6 @@ export declare class InferenceClient {
|
|
|
8
8
|
constructor(url: string, httpClient: HttpClientGot);
|
|
9
9
|
isImageRequired(instruction: string): Promise<boolean>;
|
|
10
10
|
private resizeIfNeeded;
|
|
11
|
-
predictControlCommand(instruction: string, customElements
|
|
11
|
+
predictControlCommand(instruction: string, customElements?: CustomElement[], image?: string): Promise<ControlCommand>;
|
|
12
12
|
predictImageAnnotation(image: string, customElements?: CustomElement[]): Promise<Annotation>;
|
|
13
13
|
}
|
|
@@ -35,7 +35,7 @@ export class InferenceClient {
|
|
|
35
35
|
return resizeBase64ImageWithSameRatio(image);
|
|
36
36
|
});
|
|
37
37
|
}
|
|
38
|
-
predictControlCommand(instruction, customElements, image) {
|
|
38
|
+
predictControlCommand(instruction, customElements = [], image) {
|
|
39
39
|
return __awaiter(this, void 0, void 0, function* () {
|
|
40
40
|
const resizedImage = yield this.resizeIfNeeded(customElements, image);
|
|
41
41
|
const httpBody = {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CustomElementJson } from '../core/model/test-case-dto';
|
|
2
|
-
import { Executable, FluentCommand } from './dsl';
|
|
2
|
+
import { Exec, Executable, FluentCommand, FluentFilters } from './dsl';
|
|
3
3
|
import { UiControllerClientConnectionState } from './ui-controller-client-connection-state';
|
|
4
4
|
import { Annotation } from '../core/annotation/annotation';
|
|
5
5
|
import { AnnotationRequest } from '../core/model/annotation-result/annotation-interface';
|
|
@@ -18,6 +18,51 @@ export declare class UiControlClient extends FluentCommand {
|
|
|
18
18
|
annotate(annotationRequest?: AnnotationRequest): Promise<Annotation>;
|
|
19
19
|
annotateInteractively(): Promise<void>;
|
|
20
20
|
exec(instruction: string, customElementJson?: CustomElementJson[]): Promise<void>;
|
|
21
|
+
private secretText;
|
|
22
|
+
/**
|
|
23
|
+
* Types a text inside the filtered element.
|
|
24
|
+
*
|
|
25
|
+
* By default, the `text` is included in the logs and sent over to the askui Inference server to
|
|
26
|
+
* predict in which context the typing has to occur. You can exclude the `text` from the logs
|
|
27
|
+
* and the request to the askui Inference server setting `options.isSecret` to `true`.
|
|
28
|
+
* This should not change the quality of the prediction of the askui Inference server. In this
|
|
29
|
+
* case, `options.secretMask` is included in logs and sent over instead of the `text`.
|
|
30
|
+
*
|
|
31
|
+
* @param {string} text - A text to type.
|
|
32
|
+
* @param {Object} [options]
|
|
33
|
+
* @param {boolean} [options.isSecret = false] - If set to `true`, `text` is neither included in
|
|
34
|
+
* logs of askui nor sent over to askui Inference for prediction.
|
|
35
|
+
* @param {string} [options.secretMask = '****'] - If `options.isSecret` is set to `true`, this
|
|
36
|
+
* is included in logs and sent over to askui Inference for prediction instead of the `text`.
|
|
37
|
+
*
|
|
38
|
+
* @return {FluentFilters}
|
|
39
|
+
*/
|
|
40
|
+
typeIn(text: string, { isSecret, secretMask }?: {
|
|
41
|
+
isSecret?: boolean | undefined;
|
|
42
|
+
secretMask?: string | undefined;
|
|
43
|
+
}): FluentFilters;
|
|
44
|
+
/**
|
|
45
|
+
* Types a text at the current position.
|
|
46
|
+
*
|
|
47
|
+
* By default, the `text` is included in the logs and sent over to the askui Inference server to
|
|
48
|
+
* predict in which context the typing has to occur. You can exclude the `text` from the logs
|
|
49
|
+
* and the request to the askui Inference server setting `options.isSecret` to `true`.
|
|
50
|
+
* This should not change the quality of the prediction of the askui Inference server. In this
|
|
51
|
+
* case, `options.secretMask` is included in logs and sent over instead of the `text`.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} text - A text to type.
|
|
54
|
+
* @param {Object} options
|
|
55
|
+
* @param {boolean} [options.isSecret = false] - If set to `true`, `text` is neither included in
|
|
56
|
+
* logs of askui nor sent over to askui Inference for prediction.
|
|
57
|
+
* @param {string} [options.secretMask = '****'] - If `options.isSecret` is set to `true`, this
|
|
58
|
+
* is included in logs and sent over to askui Inference for prediction instead of the `text`.
|
|
59
|
+
*
|
|
60
|
+
* @return {Exec}
|
|
61
|
+
*/
|
|
62
|
+
type(text: string, { isSecret, secretMask }?: {
|
|
63
|
+
isSecret?: boolean | undefined;
|
|
64
|
+
secretMask?: string | undefined;
|
|
65
|
+
}): Exec;
|
|
21
66
|
/**
|
|
22
67
|
* Waits for `<delayInMs>` ms, e.g., 1000 ms. The exact delay may be a little longer
|
|
23
68
|
* than `<delayInMs>` but never shorter than that.
|
|
@@ -8,7 +8,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
10
|
import { CustomElement } from '../core/model/test-case-dto';
|
|
11
|
-
import { FluentCommand } from './dsl';
|
|
11
|
+
import { FluentCommand, } from './dsl';
|
|
12
12
|
import { HttpClientGot } from '../utils/http/http-client-got';
|
|
13
13
|
import { UiControllerClient } from './ui-controller-client';
|
|
14
14
|
import { ExecutionRuntime } from './execution-runtime';
|
|
@@ -26,6 +26,7 @@ export class UiControlClient extends FluentCommand {
|
|
|
26
26
|
super();
|
|
27
27
|
this.httpClient = httpClient;
|
|
28
28
|
this.clientArgs = clientArgs;
|
|
29
|
+
this.secretText = undefined;
|
|
29
30
|
}
|
|
30
31
|
static build(clientArgs) {
|
|
31
32
|
return __awaiter(this, void 0, void 0, function* () {
|
|
@@ -85,16 +86,15 @@ export class UiControlClient extends FluentCommand {
|
|
|
85
86
|
}
|
|
86
87
|
});
|
|
87
88
|
}
|
|
88
|
-
exec(instruction, customElementJson) {
|
|
89
|
+
exec(instruction, customElementJson = []) {
|
|
89
90
|
return __awaiter(this, void 0, void 0, function* () {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
customElements = yield CustomElement.fromJsonListWithImagePathOrImage(customElementJson);
|
|
93
|
-
}
|
|
91
|
+
const customElements = yield CustomElement.fromJsonListWithImagePathOrImage(customElementJson);
|
|
92
|
+
const { secretText } = this;
|
|
94
93
|
try {
|
|
95
94
|
yield this.executionRuntime.executeTestStep({
|
|
96
95
|
instruction,
|
|
97
96
|
customElements,
|
|
97
|
+
secretText,
|
|
98
98
|
});
|
|
99
99
|
yield this.annotateByDefault(TestStepState.PASSED, customElements);
|
|
100
100
|
return yield Promise.resolve();
|
|
@@ -105,6 +105,56 @@ export class UiControlClient extends FluentCommand {
|
|
|
105
105
|
}
|
|
106
106
|
});
|
|
107
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* Types a text inside the filtered element.
|
|
110
|
+
*
|
|
111
|
+
* By default, the `text` is included in the logs and sent over to the askui Inference server to
|
|
112
|
+
* predict in which context the typing has to occur. You can exclude the `text` from the logs
|
|
113
|
+
* and the request to the askui Inference server setting `options.isSecret` to `true`.
|
|
114
|
+
* This should not change the quality of the prediction of the askui Inference server. In this
|
|
115
|
+
* case, `options.secretMask` is included in logs and sent over instead of the `text`.
|
|
116
|
+
*
|
|
117
|
+
* @param {string} text - A text to type.
|
|
118
|
+
* @param {Object} [options]
|
|
119
|
+
* @param {boolean} [options.isSecret = false] - If set to `true`, `text` is neither included in
|
|
120
|
+
* logs of askui nor sent over to askui Inference for prediction.
|
|
121
|
+
* @param {string} [options.secretMask = '****'] - If `options.isSecret` is set to `true`, this
|
|
122
|
+
* is included in logs and sent over to askui Inference for prediction instead of the `text`.
|
|
123
|
+
*
|
|
124
|
+
* @return {FluentFilters}
|
|
125
|
+
*/
|
|
126
|
+
typeIn(text, { isSecret = false, secretMask = '****' } = {}) {
|
|
127
|
+
if (isSecret) {
|
|
128
|
+
this.secretText = text;
|
|
129
|
+
return super.typeIn(secretMask);
|
|
130
|
+
}
|
|
131
|
+
return super.typeIn(text);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Types a text at the current position.
|
|
135
|
+
*
|
|
136
|
+
* By default, the `text` is included in the logs and sent over to the askui Inference server to
|
|
137
|
+
* predict in which context the typing has to occur. You can exclude the `text` from the logs
|
|
138
|
+
* and the request to the askui Inference server setting `options.isSecret` to `true`.
|
|
139
|
+
* This should not change the quality of the prediction of the askui Inference server. In this
|
|
140
|
+
* case, `options.secretMask` is included in logs and sent over instead of the `text`.
|
|
141
|
+
*
|
|
142
|
+
* @param {string} text - A text to type.
|
|
143
|
+
* @param {Object} options
|
|
144
|
+
* @param {boolean} [options.isSecret = false] - If set to `true`, `text` is neither included in
|
|
145
|
+
* logs of askui nor sent over to askui Inference for prediction.
|
|
146
|
+
* @param {string} [options.secretMask = '****'] - If `options.isSecret` is set to `true`, this
|
|
147
|
+
* is included in logs and sent over to askui Inference for prediction instead of the `text`.
|
|
148
|
+
*
|
|
149
|
+
* @return {Exec}
|
|
150
|
+
*/
|
|
151
|
+
type(text, { isSecret = false, secretMask = '****' } = {}) {
|
|
152
|
+
if (isSecret) {
|
|
153
|
+
this.secretText = text;
|
|
154
|
+
return super.type(secretMask);
|
|
155
|
+
}
|
|
156
|
+
return super.type(text);
|
|
157
|
+
}
|
|
108
158
|
/**
|
|
109
159
|
* Waits for `<delayInMs>` ms, e.g., 1000 ms. The exact delay may be a little longer
|
|
110
160
|
* than `<delayInMs>` but never shorter than that.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
|
+
import { getPathToNodeModulesRoot } from '../utils/path';
|
|
4
5
|
const createProgram = () => {
|
|
5
6
|
const program = new Command('askui');
|
|
6
7
|
program.usage('<command> [options]');
|
|
@@ -8,7 +9,7 @@ const createProgram = () => {
|
|
|
8
9
|
};
|
|
9
10
|
function copyExampleProject() {
|
|
10
11
|
const exampleProjectPath = path.join('example_projects_templates', 'typescript_jest');
|
|
11
|
-
fs.copySync(path.join(
|
|
12
|
+
fs.copySync(path.join(getPathToNodeModulesRoot(), exampleProjectPath), '.');
|
|
12
13
|
}
|
|
13
14
|
export function init(argv) {
|
|
14
15
|
const args = argv || process.argv;
|
|
@@ -2,6 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import got from 'got';
|
|
3
3
|
import os from 'os';
|
|
4
4
|
import path from 'path';
|
|
5
|
+
import { getPathToNodeModulesRoot } from '../utils/path';
|
|
5
6
|
import { logger } from './logger';
|
|
6
7
|
var SupportedPlatform;
|
|
7
8
|
(function (SupportedPlatform) {
|
|
@@ -28,7 +29,7 @@ function buildBinaryNotAvailbleError(binaryVersion) {
|
|
|
28
29
|
return new Error(`It seems that the UI Controller version "${binaryVersion}" for your system "${platform()} ${os.arch}" is not availble, Please contact as at info@askui.com for more information`);
|
|
29
30
|
}
|
|
30
31
|
export function getBinaryPath(version) {
|
|
31
|
-
return path.join(
|
|
32
|
+
return path.join(getPathToNodeModulesRoot(), 'release', version, ...binarySubPathsByPlatform[platform()]);
|
|
32
33
|
}
|
|
33
34
|
function getBinaryDownloadUrl(binaryVersion) {
|
|
34
35
|
const baseUrl = `https://askui-public.s3.eu-central-1.amazonaws.com/releases/askui-ui-controller/${binaryVersion}`;
|
|
@@ -24,7 +24,7 @@ export class UiControllerLinux extends UiControllerFacade {
|
|
|
24
24
|
const runCommand = promisify(exec);
|
|
25
25
|
const waylandStatus = yield runCommand('echo $WAYLAND_DISPLAY');
|
|
26
26
|
if (waylandStatus.stdout.trim().includes('wayland')) {
|
|
27
|
-
throw new WaylandError('Wayland is not supported: https://docs.askui.com/docs/general/Troubleshooting/askui-ui-controller
|
|
27
|
+
throw new WaylandError('Wayland is not supported: https://docs.askui.com/docs/general/Troubleshooting/askui-ui-controller#wayland');
|
|
28
28
|
}
|
|
29
29
|
/* First we want to check if the user is using a debian distribution.
|
|
30
30
|
* and in the following if libfuse2 is installed.
|
|
@@ -41,7 +41,7 @@ export class UiControllerLinux extends UiControllerFacade {
|
|
|
41
41
|
yield runCommand('dpkg -s libfuse2 | grep Status');
|
|
42
42
|
}
|
|
43
43
|
catch (_a) {
|
|
44
|
-
throw new LibfuseError('Libfuse2 package is missing: https://docs.askui.com/docs/general/Troubleshooting/askui-ui-controller
|
|
44
|
+
throw new LibfuseError('Libfuse2 package is missing: https://docs.askui.com/docs/general/Troubleshooting/askui-ui-controller#libfuse2');
|
|
45
45
|
}
|
|
46
46
|
});
|
|
47
47
|
}
|
|
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import os from 'os';
|
|
11
11
|
import { UserIdentifier } from './user-identifier';
|
|
12
|
+
import { InstallationTimestamp } from './installation-timestamp';
|
|
12
13
|
export class Analytics {
|
|
13
14
|
constructor() {
|
|
14
15
|
this.userIdentifier = new UserIdentifier();
|
|
@@ -16,10 +17,15 @@ export class Analytics {
|
|
|
16
17
|
getAnalyticsHeaders() {
|
|
17
18
|
return __awaiter(this, void 0, void 0, function* () {
|
|
18
19
|
const userID = yield this.userIdentifier.userId();
|
|
19
|
-
|
|
20
|
+
const headers = {
|
|
20
21
|
'askui-user-id': userID,
|
|
21
22
|
'askui-user-agent': `os:${os.platform()};arch:${os.arch()}`,
|
|
22
23
|
};
|
|
24
|
+
const askuiInstalledAt = yield InstallationTimestamp.get();
|
|
25
|
+
if (askuiInstalledAt) {
|
|
26
|
+
headers['askui-installed-at'] = askuiInstalledAt.toISOString();
|
|
27
|
+
}
|
|
28
|
+
return headers;
|
|
23
29
|
});
|
|
24
30
|
}
|
|
25
31
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import fs from 'fs';
|
|
11
|
+
import path from 'path';
|
|
12
|
+
import { logger } from '../../lib';
|
|
13
|
+
import { InstallationTimestampCreateError } from './installation-timestamp-create-error';
|
|
14
|
+
import { InstallationTimestampGetError } from './installation-timestamp-get-error';
|
|
15
|
+
import { getPathToNodeModulesRoot } from '../path';
|
|
16
|
+
export class InstallationTimestamp {
|
|
17
|
+
static create() {
|
|
18
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
19
|
+
const timestamp = new Date().toISOString();
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
fs.writeFile(InstallationTimestamp.fileName, timestamp, { encoding: 'utf-8' }, (err) => {
|
|
22
|
+
if (err) {
|
|
23
|
+
reject(new InstallationTimestampCreateError(err));
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
resolve();
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
static get() {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
if (InstallationTimestamp.value === undefined) {
|
|
35
|
+
try {
|
|
36
|
+
InstallationTimestamp.value = yield this.getFromFile();
|
|
37
|
+
}
|
|
38
|
+
catch (err) {
|
|
39
|
+
InstallationTimestamp.value = null;
|
|
40
|
+
logger.warn(err.message);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return InstallationTimestamp.value;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
static getFromFile() {
|
|
47
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
48
|
+
return new Promise((resolve, reject) => {
|
|
49
|
+
fs.readFile(InstallationTimestamp.fileName, 'utf-8', (err, isoDateStr) => {
|
|
50
|
+
if (err) {
|
|
51
|
+
reject(new InstallationTimestampGetError(err));
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
resolve(new Date(isoDateStr));
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
InstallationTimestamp.fileName = path.join(getPathToNodeModulesRoot(), 'install-timestamp');
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function getPathToNodeModulesRoot(): string;
|
package/package.json
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "askui",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"main": "./dist/cjs/main.js",
|
|
5
5
|
"module": "./dist/esm/main.js",
|
|
6
|
-
"bin":
|
|
6
|
+
"bin": {
|
|
7
|
+
"askui": "bin/askui",
|
|
8
|
+
"askui-postinstall": "bin/askui-postinstall"
|
|
9
|
+
},
|
|
7
10
|
"scripts": {
|
|
8
11
|
"build": "tsc -p tsconfig.json && tsc -p tsconfig-cjs.json && npm run copyTemplate && npm run copyExampleProject",
|
|
9
12
|
"copyTemplate": "shx cp -r src/core/annotation/template.html dist/cjs/core/annotation/ && shx cp -r src/core/annotation/template.html dist/esm/core/annotation/",
|
|
10
13
|
"copyExampleProject": "shx cp -r example_projects_templates/ dist/ && shx cp -r bin/* dist/",
|
|
11
14
|
"lint": "eslint --cache --fix --max-warnings 0 \"./**/*.{js,ts}\"",
|
|
12
15
|
"lint:staged": "lint-staged",
|
|
13
|
-
"test": "jest '/src'"
|
|
16
|
+
"test": "jest '/src'",
|
|
17
|
+
"postinstall": "$npm_package_bin_askui-postinstall"
|
|
14
18
|
},
|
|
15
19
|
"files": [
|
|
16
20
|
"dist/cjs/",
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.Base64ImagePathError = void 0;
|
|
4
|
-
const base_64_image_error_1 = require("./base-64-image-error");
|
|
5
|
-
class Base64ImagePathError extends base_64_image_error_1.Base64ImageError {
|
|
6
|
-
constructor(path) {
|
|
7
|
-
super(`Can't create Base64Image instance from path:\n${path}\n\n` +
|
|
8
|
-
`No image exists at path.`);
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
exports.Base64ImagePathError = Base64ImagePathError;
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.InvalidBase64Image = void 0;
|
|
4
|
-
const image_resizing_base_error_1 = require("./image-resizing-base-error");
|
|
5
|
-
class InvalidBase64Image extends image_resizing_base_error_1.ImageResizingError {
|
|
6
|
-
}
|
|
7
|
-
exports.InvalidBase64Image = InvalidBase64Image;
|