mirror of
https://github.com/keymanapp/keyman.git
synced 2026-11-03 09:37:47 +00:00
Merge pull request #3122 from keymanapp/feat/web/sentry-start
feat(web): starts proper KMW Sentry integration
This commit is contained in:
commit
7742bfdb37
19 changed files with 663 additions and 11 deletions
17
common/core/web/tools/sentry-manager/.gitignore
vendored
Normal file
17
common/core/web/tools/sentry-manager/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
# Build products
|
||||
src/environment.inc.ts
|
||||
|
||||
# Legacy build folders.
|
||||
output/
|
||||
build/
|
||||
embedded/
|
||||
|
||||
# Current build output folder (matches standard node publish location).
|
||||
dist/
|
||||
|
||||
# Other local files.
|
||||
node_modules/
|
||||
unit_tests/modernizr.js
|
||||
**/.idea/**/*.xml
|
||||
**/*.iml
|
||||
**/*.kpj.user
|
||||
76
common/core/web/tools/sentry-manager/package-lock.json
generated
Normal file
76
common/core/web/tools/sentry-manager/package-lock.json
generated
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
{
|
||||
"name": "@keymanapp/web-sentry-manager",
|
||||
"version": "14.0.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@sentry/browser": {
|
||||
"version": "5.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/browser/-/browser-5.15.5.tgz",
|
||||
"integrity": "sha512-rqDvjk/EvogfdbZ4TiEpxM/lwpPKmq23z9YKEO4q81+1SwJNua53H60dOk9HpRU8nOJ1g84TMKT2Ov8H7sqDWA==",
|
||||
"requires": {
|
||||
"@sentry/core": "5.15.5",
|
||||
"@sentry/types": "5.15.5",
|
||||
"@sentry/utils": "5.15.5",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/core": {
|
||||
"version": "5.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/core/-/core-5.15.5.tgz",
|
||||
"integrity": "sha512-enxBLv5eibBMqcWyr+vApqeix8uqkfn0iGsD3piKvoMXCgKsrfMwlb/qo9Ox0lKr71qIlZVt+9/A2vZohdgnlg==",
|
||||
"requires": {
|
||||
"@sentry/hub": "5.15.5",
|
||||
"@sentry/minimal": "5.15.5",
|
||||
"@sentry/types": "5.15.5",
|
||||
"@sentry/utils": "5.15.5",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/hub": {
|
||||
"version": "5.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/hub/-/hub-5.15.5.tgz",
|
||||
"integrity": "sha512-zX9o49PcNIVMA4BZHe//GkbQ4Jx+nVofqU/Il32/IbwKhcpPlhGX3c1sOVQo4uag3cqd/JuQsk+DML9TKkN0Lw==",
|
||||
"requires": {
|
||||
"@sentry/types": "5.15.5",
|
||||
"@sentry/utils": "5.15.5",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/minimal": {
|
||||
"version": "5.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.15.5.tgz",
|
||||
"integrity": "sha512-zQkkJ1l9AjmU/Us5IrOTzu7bic4sTPKCatptXvLSTfyKW7N6K9MPIIFeSpZf9o1yM2sRYdK7GV08wS2eCT3JYw==",
|
||||
"requires": {
|
||||
"@sentry/hub": "5.15.5",
|
||||
"@sentry/types": "5.15.5",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"@sentry/types": {
|
||||
"version": "5.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.15.5.tgz",
|
||||
"integrity": "sha512-F9A5W7ucgQLJUG4LXw1ZIy4iLevrYZzbeZ7GJ09aMlmXH9PqGThm1t5LSZlVpZvUfQ2rYA8NU6BdKJSt7B5LPw=="
|
||||
},
|
||||
"@sentry/utils": {
|
||||
"version": "5.15.5",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.15.5.tgz",
|
||||
"integrity": "sha512-Nl9gl/MGnzSkuKeo3QaefoD/OJrFLB8HmwQ7HUbTXb6E7yyEzNKAQMHXGkwNAjbdYyYbd42iABP6Y5F/h39NtA==",
|
||||
"requires": {
|
||||
"@sentry/types": "5.15.5",
|
||||
"tslib": "^1.9.3"
|
||||
}
|
||||
},
|
||||
"tslib": {
|
||||
"version": "1.11.1",
|
||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.11.1.tgz",
|
||||
"integrity": "sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA=="
|
||||
},
|
||||
"typescript": {
|
||||
"version": "3.8.3",
|
||||
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.8.3.tgz",
|
||||
"integrity": "sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
}
|
||||
25
common/core/web/tools/sentry-manager/package.json
Normal file
25
common/core/web/tools/sentry-manager/package.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"name": "@keymanapp/web-sentry-manager",
|
||||
"version": "14.0.0",
|
||||
"description": "Common setup for KeymanWeb's Sentry-based error reporting",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"tsc": "tsc"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/keymanapp/keyman.git"
|
||||
},
|
||||
"author": "SIL International",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/keymanapp/keyman/issues"
|
||||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"typescript": "^3.8.3"
|
||||
},
|
||||
"dependencies": {
|
||||
"@sentry/browser": "^5.15.5"
|
||||
}
|
||||
}
|
||||
66
common/core/web/tools/sentry-manager/src/build.sh
Executable file
66
common/core/web/tools/sentry-manager/src/build.sh
Executable file
|
|
@ -0,0 +1,66 @@
|
|||
#! /bin/bash
|
||||
#
|
||||
# Compiles development-related KeymanWeb resources for use with developing/running tests.
|
||||
# - the Recorder module (for engine tests)
|
||||
# - the DOM module (for touch-alias and element-interface tests)
|
||||
|
||||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")"
|
||||
. "$(dirname "$THIS_SCRIPT")/../../../../../../resources/build/build-utils.sh"
|
||||
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
SCRIPT_DIR="$(dirname "$THIS_SCRIPT")"
|
||||
|
||||
display_usage ( ) {
|
||||
echo "build.sh [-skip-dependency-install]"
|
||||
echo
|
||||
echo " -skip-dependency-install skips the `lerna bootstrap` dependency check."
|
||||
echo " (or -S) Intended for use when this script is called by another build script."
|
||||
echo ""
|
||||
echo " If more than one target is specified, the last one will take precedence."
|
||||
exit 1
|
||||
}
|
||||
|
||||
# Establish default build parameters
|
||||
set_default_vars ( ) {
|
||||
FETCH_DEPS=true
|
||||
}
|
||||
|
||||
set_default_vars
|
||||
|
||||
# Parse args
|
||||
while [[ $# -gt 0 ]] ; do
|
||||
key="$1"
|
||||
case $key in
|
||||
-skip-package-install|-S)
|
||||
set_default_vars
|
||||
FETCH_DEPS=false
|
||||
;;
|
||||
esac
|
||||
shift # past argument
|
||||
done
|
||||
|
||||
if [ $FETCH_DEPS = true ]; then
|
||||
verify_npm_setup
|
||||
fi
|
||||
|
||||
# Definition of global compile constants
|
||||
OUTPUT_DIR="dist"
|
||||
OUTPUT="index.js"
|
||||
|
||||
# Ensures that we rely first upon the local npm-based install of Typescript.
|
||||
# (Facilitates automated setup for build agents.)
|
||||
PATH="../node_modules/.bin:$PATH"
|
||||
|
||||
# Ensure the environment definition variables are available.
|
||||
exportEnvironmentDefinitionTS
|
||||
|
||||
compiler="npm run tsc --"
|
||||
compilecmd="$compiler"
|
||||
|
||||
$compilecmd -p "$SCRIPT_DIR/tsconfig.json"
|
||||
if [ $? -ne 0 ]; then
|
||||
fail "Compilation of package for Sentry integration with KeymanWeb failed."
|
||||
fi
|
||||
147
common/core/web/tools/sentry-manager/src/index.ts
Normal file
147
common/core/web/tools/sentry-manager/src/index.ts
Normal file
|
|
@ -0,0 +1,147 @@
|
|||
///<reference path="../node_modules/@sentry/browser/build/bundle.min.js" />
|
||||
|
||||
namespace com.keyman {
|
||||
/**
|
||||
* Controls whether or not the generated Sentry event is logged to the console (true)
|
||||
* or sent to our Sentry server (false).
|
||||
*/
|
||||
let DEBUG = false;
|
||||
|
||||
type Options = typeof KeymanSentryManager.DEFAULT_OPTIONS;
|
||||
|
||||
export class KeymanSentryManager {
|
||||
keymanPlatform: string;
|
||||
|
||||
static STANDARD_ALIASABLE_FILES = {
|
||||
'keymanweb.js': 'keymanweb.js',
|
||||
'kmwuibutton.js': 'kmwuibutton.js',
|
||||
'kmwuifloat.js': 'kmwuifloat.js',
|
||||
'kmwuitoggle.js': 'kmwuitoggle.js',
|
||||
'kmwuitoolbar.js': 'kmwuitoolbar.js'
|
||||
// Also add entries for the naming system used by Android and iOS - and map them to the EMBEDDED upload, not the std 'native' one.
|
||||
}
|
||||
|
||||
static DEFAULT_OPTIONS = {
|
||||
hostPlatform: "native-web"
|
||||
}
|
||||
|
||||
constructor(options: Options = KeymanSentryManager.DEFAULT_OPTIONS) {
|
||||
this.keymanPlatform = options.hostPlatform;
|
||||
}
|
||||
|
||||
// If we've recognized one of our source files,
|
||||
aliasFilename(filename: string): string|null {
|
||||
if(!this.mayAlias(filename)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
filename = KeymanSentryManager.STANDARD_ALIASABLE_FILES[filename];
|
||||
|
||||
switch(location.protocol) {
|
||||
case 'http:':
|
||||
return 'http://' + location.host + '/' + filename;
|
||||
case 'file:':
|
||||
return 'file:///' + filename;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
mayAlias(filename: string): boolean {
|
||||
return !!KeymanSentryManager.STANDARD_ALIASABLE_FILES[filename];
|
||||
}
|
||||
|
||||
// Filters all expected but unnecessary path prefixes, affixes, and suffixes reported by Sentry from our products.
|
||||
// This allows us to mask all different sorts of installations with a single uploaded path.
|
||||
// Modifies original object.
|
||||
pathFilter(event: any) {
|
||||
// Get the underlying JS error.
|
||||
let exception = event.exception;
|
||||
|
||||
// Iterate through all wrapped exceptions.
|
||||
for(let e of exception.values) {
|
||||
for(let frame of e.stacktrace.frames) {
|
||||
let URL = frame.filename as string;
|
||||
let filename: string = '';
|
||||
try {
|
||||
filename = URL.substr(URL.lastIndexOf('/')+1);
|
||||
if(this.mayAlias(filename)) {
|
||||
// Make the file look like it's at the host's root so that the Sentry server will recognize it
|
||||
// regardless of actual filepath position.
|
||||
frame.filename = this.aliasFilename(filename) || frame.filename;
|
||||
}
|
||||
} catch {
|
||||
// not sure what to do yet, but... don't make more errors in the error handler. That's a bad idea.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Attaches some useful debugging information to the specified object, pass-by-reference style.
|
||||
attachEventMetadata(event: any) {
|
||||
// Ensure that the 'extra' object exists. (May not exist for synthetic/custom Errors.)
|
||||
event.extra = event.extra || {};
|
||||
event.extra.keymanState = window['keyman']['getDebugInfo']();
|
||||
event.extra.keymanHostPlatform = this.keymanPlatform;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-processes a Sentry event object (in-place) to provide more metadata and enhance
|
||||
* the Sentry server's ability to match the error against release artifacts.
|
||||
* @param event A Sentry-generated event
|
||||
*/
|
||||
prepareEvent(event: any): boolean {
|
||||
this.pathFilter(event);
|
||||
this.attachEventMetadata(event);
|
||||
|
||||
if(DEBUG) {
|
||||
console.log("DEBUG: event object for Sentry")
|
||||
console.log(event);
|
||||
return false; //event
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows debugging our custom event preparation code without bombarding Sentry with errors
|
||||
* during development.
|
||||
*
|
||||
* Note that Sentry expects us either to return the event object to be sent or to return `null`
|
||||
* if we want to prevent the event from being sent to the server.
|
||||
* @param event
|
||||
*/
|
||||
prepareEventDebugWrapper(event: any) {
|
||||
if(DEBUG) {
|
||||
try {
|
||||
if(this.prepareEvent(event)) {
|
||||
return event;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
} else {
|
||||
// If not in DEBUG mode, simply forward to the actual preparer; we should be notified
|
||||
// of any event-prep errors that may occur.
|
||||
if(this.prepareEvent(event)) {
|
||||
return event;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
init() {
|
||||
// Do the actual Sentry initialization.
|
||||
//@ts-ignore
|
||||
Sentry.init({
|
||||
beforeSend: this.prepareEventDebugWrapper.bind(this),
|
||||
debug: DEBUG,
|
||||
dsn: 'https://cf96f32d107c4286ab2fd82af49c4d3b@sentry.keyman.com/11', // keyman-web DSN
|
||||
release: com.keyman.environment.SENTRY_RELEASE
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
16
common/core/web/tools/sentry-manager/src/tsconfig.json
Normal file
16
common/core/web/tools/sentry-manager/src/tsconfig.json
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": true,
|
||||
"module": "none",
|
||||
"outDir": "../dist/",
|
||||
"inlineSources": true,
|
||||
"sourceMap": true,
|
||||
"target": "es5",
|
||||
"lib": ["es6", "dom"],
|
||||
"outFile": "../dist/index.js"
|
||||
},
|
||||
"files": [
|
||||
"environment.inc.ts",
|
||||
"index.ts"
|
||||
]
|
||||
}
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
"common/core/web/input-processor",
|
||||
"common/core/web/keyboard-processor",
|
||||
"common/core/web/tools/recorder",
|
||||
"common/core/web/tools/sentry-manager",
|
||||
"common/core/web/utils",
|
||||
"common/lexical-model-types",
|
||||
"common/predictive-text",
|
||||
|
|
|
|||
|
|
@ -195,6 +195,7 @@ exportEnvironmentDefinitionTS ( ) {
|
|||
namespace com.keyman.environment {
|
||||
export var VERSION = \"$VERSION_RELEASE\";
|
||||
export var BUILD = $VERSION_PATCH;
|
||||
export var SENTRY_RELEASE = \"release-$VERSION_WITH_TAG\";
|
||||
}
|
||||
" >> $ENVIRONMENT_TS
|
||||
}
|
||||
88
web/package-lock.json
generated
88
web/package-lock.json
generated
|
|
@ -4,6 +4,70 @@
|
|||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@sentry/cli": {
|
||||
"version": "1.52.3",
|
||||
"resolved": "https://registry.npmjs.org/@sentry/cli/-/cli-1.52.3.tgz",
|
||||
"integrity": "sha512-QOSIg5hxAEa6v6H7oEeF6A/Rpa0wloMhbu0Qed6zHv3lyoqf0Z34Kq2jCXdqGsOE3IzkO+3CNy81F6361j5TKg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"https-proxy-agent": "^5.0.0",
|
||||
"mkdirp": "^0.5.5",
|
||||
"node-fetch": "^2.6.0",
|
||||
"progress": "^2.0.3",
|
||||
"proxy-from-env": "^1.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"agent-base": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.0.tgz",
|
||||
"integrity": "sha512-j1Q7cSCqN+AwrmDd+pzgqc0/NpC655x2bUf5ZjRIO77DcNBFmh+OgRNzF6OKdCC9RSCb19fGd99+bhXFdkRNqw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"debug": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
|
||||
"integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ms": "^2.1.1"
|
||||
}
|
||||
},
|
||||
"https-proxy-agent": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz",
|
||||
"integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"agent-base": "6",
|
||||
"debug": "4"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "1.2.5",
|
||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz",
|
||||
"integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==",
|
||||
"dev": true
|
||||
},
|
||||
"mkdirp": {
|
||||
"version": "0.5.5",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
|
||||
"integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"minimist": "^1.2.5"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "11.9.4",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-11.9.4.tgz",
|
||||
|
|
@ -1552,12 +1616,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
"mocha-teamcity-reporter": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/mocha-teamcity-reporter/-/mocha-teamcity-reporter-3.0.0.tgz",
|
||||
"integrity": "sha512-FyGgmtFfW2nDwEZU3mrjQShAAK/zhGivwY4HCsqoDoyeS8vV8HGdq1Dn2P+SFaIoCeXTQ0Z+5xVRyikYaKrW5w==",
|
||||
"dev": true
|
||||
},
|
||||
"modernizr": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/modernizr/-/modernizr-3.7.1.tgz",
|
||||
|
|
@ -1585,6 +1643,12 @@
|
|||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
|
||||
"dev": true
|
||||
},
|
||||
"node-fetch": {
|
||||
"version": "2.6.0",
|
||||
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz",
|
||||
"integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==",
|
||||
"dev": true
|
||||
},
|
||||
"normalize-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||
|
|
@ -1736,6 +1800,18 @@
|
|||
"integrity": "sha512-oLHIdio3tZ0qH76NybpeneBhYVj0QFTfXEFTc/B3zKQspYfYYkWYgFsmzo+4kvId/bQRcNkVeguI3y+CD22BtA==",
|
||||
"dev": true
|
||||
},
|
||||
"progress": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
|
||||
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
|
||||
"dev": true
|
||||
},
|
||||
"proxy-from-env": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
|
||||
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
|
||||
"dev": true
|
||||
},
|
||||
"ps-tree": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ps-tree/-/ps-tree-1.1.1.tgz",
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@
|
|||
},
|
||||
"homepage": "https://github.com/keymanapp/keyman#readme",
|
||||
"devDependencies": {
|
||||
"@keymanapp/web-sentry-manager": "^14.0.0",
|
||||
"@sentry/cli": "^1.52.3",
|
||||
"chai": "^4.2.0",
|
||||
"google-closure-compiler-java": "^20200224.0.0",
|
||||
"html2canvas": "^1.0.0-alpha.12",
|
||||
|
|
@ -45,7 +47,8 @@
|
|||
"karma": "karma",
|
||||
"lerna": "cd ../ && npm run lerna --",
|
||||
"mocha": "mocha",
|
||||
"modernizr": "modernizr"
|
||||
"modernizr": "modernizr",
|
||||
"sentry-cli": "sentry-cli"
|
||||
},
|
||||
"dependencies": {
|
||||
"@keymanapp/input-processor": "^14.0.78",
|
||||
|
|
|
|||
|
|
@ -206,6 +206,13 @@ INTERMEDIATE="../intermediate"
|
|||
SOURCE="."
|
||||
NODE_SOURCE="source"
|
||||
|
||||
SENTRY_RELEASE_VERSION="release-$VERSION_WITH_TAG"
|
||||
|
||||
export SENTRY_URL="https://sentry.keyman.com"
|
||||
export SENTRY_ORG=keyman
|
||||
export SENTRY_PROJECT=keyman-web
|
||||
export SENTRY_LOG_LEVEL=info
|
||||
|
||||
readonly WEB_OUTPUT
|
||||
readonly EMBED_OUTPUT
|
||||
readonly SOURCE
|
||||
|
|
@ -227,6 +234,7 @@ set_default_vars ( ) {
|
|||
BUILD_DEBUG_EMBED=false
|
||||
BUILD_COREWEB=true
|
||||
DO_MINIFY=true
|
||||
DO_NATIVE_SENTRY=true
|
||||
FETCH_DEPS=true
|
||||
}
|
||||
|
||||
|
|
@ -264,6 +272,7 @@ while [[ $# -gt 0 ]] ; do
|
|||
BUILD_FULLWEB=false
|
||||
BUILD_UI=false
|
||||
BUILD_COREWEB=false
|
||||
DO_NATIVE_SENTRY=false
|
||||
;;
|
||||
-web)
|
||||
set_default_vars
|
||||
|
|
@ -276,12 +285,14 @@ while [[ $# -gt 0 ]] ; do
|
|||
BUILD_COREWEB=false
|
||||
BUILD_FULLWEB=false
|
||||
BUILD_DEBUG_EMBED=true
|
||||
DO_NATIVE_SENTRY=false
|
||||
;;
|
||||
-h|-?)
|
||||
display_usage
|
||||
;;
|
||||
-no_minify)
|
||||
DO_MINIFY=false
|
||||
DO_NATIVE_SENTRY=false
|
||||
;;
|
||||
-clean)
|
||||
clean
|
||||
|
|
@ -314,6 +325,7 @@ if [ $DO_MINIFY = true ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
# Only run if BOTH cases are true b/c it's a minification-focused 'dependency'.
|
||||
if [ $FETCH_DEPS = true ]; then
|
||||
# Also, build our sourcemap-root tool for cleaning up the minified version's sourcemaps.
|
||||
echo "Compiling build tools for minified build products"
|
||||
|
|
@ -324,6 +336,14 @@ fi
|
|||
|
||||
if [ $BUILD_CORE = true ]; then
|
||||
CORE_FLAGS="-skip-package-install"
|
||||
|
||||
# Build the sentry-manager module - it's used in embedded contexts and on one testing page.
|
||||
echo "${TERM_HEADING}Compiling KeymanWeb's sentry-manager module...${NORMAL}"
|
||||
pushd ../../common/core/web/tools/sentry-manager/src
|
||||
./build.sh $CORE_FLAGS || fail "Failed to compile the sentry-manager module"
|
||||
popd
|
||||
echo "${TERM_HEADING}sentry-manager module compiled successfully.${NORMAL}"
|
||||
|
||||
if [ $BUILD_LMLAYER = false ]; then
|
||||
CORE_FLAGS="$CORE_FLAGS -test"
|
||||
fi
|
||||
|
|
@ -381,6 +401,13 @@ if [ $BUILD_EMBED = true ]; then
|
|||
echo
|
||||
echo KMEA/KMEI version $VERSION compiled and saved under $EMBED_OUTPUT
|
||||
echo
|
||||
|
||||
# We always publish "embedded" mode to Sentry when minifying.
|
||||
pushd $EMBED_OUTPUT
|
||||
echo "Uploading to Sentry..."
|
||||
npm run sentry-cli -- releases files "$SENTRY_RELEASE_VERSION" upload-sourcemaps --strip-common-prefix release/embedded --rewrite --ext js --ext map --ext ts || fail "Sentry upload failed."
|
||||
echo "Upload successful."
|
||||
popd
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -462,6 +489,16 @@ if [ $BUILD_UI = true ]; then
|
|||
fi
|
||||
fi
|
||||
|
||||
# Has its own flag due to complex logic. Should run if $DO_MINIFY && ($BUILD_COREWEB || $BUILD_UI)
|
||||
# If only one of the two (COREWEB, UI) is run, we assume the un-run portion is 'current' and still upload it.
|
||||
if [ $DO_NATIVE_SENTRY = true ]; then
|
||||
pushd $WEB_OUTPUT
|
||||
echo "Uploading to Sentry..."
|
||||
npm run sentry-cli -- releases files "$SENTRY_RELEASE_VERSION" upload-sourcemaps --strip-common-prefix release/web/ --rewrite --ext js --ext map --ext ts || fail "Sentry upload failed."
|
||||
echo "Upload successful."
|
||||
popd
|
||||
fi
|
||||
|
||||
if [ $BUILD_DEBUG_EMBED = true ]; then
|
||||
# We currently have an issue with sourcemaps for minified versions.
|
||||
# We should use the unminified one instead for now.
|
||||
|
|
@ -470,4 +507,3 @@ if [ $BUILD_DEBUG_EMBED = true ]; then
|
|||
cp $EMBED_OUTPUT_NO_MINI/keyman.js.map $EMBED_OUTPUT/keyman.js.map
|
||||
echo Uncompiled embedded application saved as keyman.js
|
||||
fi
|
||||
|
||||
|
|
|
|||
|
|
@ -372,7 +372,7 @@ namespace com.keyman.keyboards {
|
|||
}
|
||||
|
||||
this.doBeforeKeyboardChange(PInternalName,PLgCode);
|
||||
let p = this._SetActiveKeyboard(PInternalName,PLgCode,true);
|
||||
let p: Promise<void> = this._SetActiveKeyboard(PInternalName,PLgCode,true);
|
||||
if(this.keymanweb.domManager.getLastActiveElement() != null) {
|
||||
this.keymanweb.domManager.focusLastActiveElement(); // TODO: Resolve without need for the cast.
|
||||
}
|
||||
|
|
@ -383,6 +383,14 @@ namespace com.keyman.keyboards {
|
|||
// }
|
||||
this.doKeyboardChange(PInternalName, PLgCode);
|
||||
|
||||
p.catch(function() {
|
||||
// Rejection indicates a failure of the keyboard to load.
|
||||
//
|
||||
// In case p's rejection is never caught, throwing this error will generate logs that shows up
|
||||
// in Sentry or in the console, with useful information for debugging either way.
|
||||
throw new Error("Unable to load keyboard with internal name \"" + PInternalName + "\", language code \"" + PLgCode + "\".");
|
||||
})
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -177,6 +177,25 @@ namespace com.keyman {
|
|||
dom.DOMEventHandlers.states = new dom.CommonDOMStates();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a generalized metadata object about the state of KMW for use with error reporting.
|
||||
*/
|
||||
['getDebugInfo']() {
|
||||
let metadata = {
|
||||
attachType: this.options.attachType,
|
||||
device: this.util.device,
|
||||
initialized: this.initialized,
|
||||
isEmbedded: this.isEmbedded,
|
||||
ui: this.ui ? this.ui.name : null
|
||||
}
|
||||
|
||||
if(this.util.device.touchable) {
|
||||
metadata.ui = 'touch';
|
||||
}
|
||||
|
||||
return metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose font testing to allow checking that SpecialOSK or custom font has
|
||||
* been correctly loaded by browser
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@
|
|||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>KeymanWeb 12 Testing</h1>
|
||||
<h1>KeymanWeb 14 Testing</h1>
|
||||
<h2><a href="./unminified.html">Test unminified Keymanweb</a></h2>
|
||||
<h2><a href="./unminified - manual.html">Test unminified Keymanweb in manual-attachment mode.</a></h2>
|
||||
<h2><a href="./keyboard-errors/">Tests keyboard error-handling functionality</a></h2>
|
||||
|
|
@ -30,6 +30,7 @@
|
|||
<h2><a href="./prediction-ui/">Prediction UI testing</a></h2>
|
||||
<h2><a href="./toolbar/">Toolbar UI testing</a></h2>
|
||||
<h2><a href="./build-visual-keyboard/">Tests keyboard documentation rendering.</a></h2>
|
||||
<h2><a href="./sentry-integration/">Tests Sentry error-reporting functionality</a></h2>
|
||||
<h1>Auto-attachment mode tests</h1>
|
||||
<h2><a href="./issue29">Test desktop MutationObserver functionality</a></h2>
|
||||
<h2><a href="./issue62">Light test for touch-based MutationObserver functionality</a></h2>
|
||||
|
|
|
|||
42
web/testing/sentry-integration/errorhdr.js
Normal file
42
web/testing/sentry-integration/errorhdr.js
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
// JavaScript Document samplehdr.js: Keyboard management for KeymanWeb demonstration pages
|
||||
|
||||
/*
|
||||
This script is designed to test KeymanWeb error message handling.
|
||||
*/
|
||||
|
||||
function loadKeyboards()
|
||||
{
|
||||
var kmw=keyman;
|
||||
|
||||
// We start by adding a keyboard correctly. It's best to include a 'control' in our experiment.
|
||||
kmw.addKeyboards({id:'us',name:'English',languages:{id:'en',name:'English'},
|
||||
filename:'../us-1.0.js'});
|
||||
|
||||
// Insert a keyboard that cannot be found.
|
||||
kmw.addKeyboards({id:'lao_2008_basic',name:'wrong-filename',
|
||||
languages:{
|
||||
id:'lo',name:'debugging',region:'Asia',
|
||||
font:{family:'LaoWeb',source:['../font/saysettha_web.ttf','../font/saysettha_web.woff','../font/saysettha_web.eot']}
|
||||
},
|
||||
filename:'./missing_file.js' // Intentional error - the file doesn't exist, so the <script> tag will raise an error event.
|
||||
});
|
||||
|
||||
// Insert a keyboard that will generate a timing error.
|
||||
kmw.addKeyboards({id:'unparsable',name:'non-parsable',
|
||||
languages:{
|
||||
id:'lo',name:'debugging',region:'Asia',
|
||||
font:{family:'LaoWeb',source:['../font/saysettha_web.ttf','../font/saysettha_web.woff','../font/saysettha_web.eot']}
|
||||
},
|
||||
filename:'./unparsable.js' // Intentional error - the file has no parsable keyboard, so while the <script> tag will load,
|
||||
// registration will fail.
|
||||
});
|
||||
|
||||
// Insert a keyboard that will generate a timing error.
|
||||
kmw.addKeyboards({id:'timeout',name:'timeout',
|
||||
languages:{
|
||||
id:'lo',name:'debugging',region:'Asia',
|
||||
font:{family:'LaoWeb',source:['../font/saysettha_web.ttf','../font/saysettha_web.woff','../font/saysettha_web.eot']}
|
||||
},
|
||||
filename:'./timeout.js' // Intentional (simulated) error - the file never loads, simulating a server timeout.
|
||||
});
|
||||
}
|
||||
106
web/testing/sentry-integration/index.html
Normal file
106
web/testing/sentry-integration/index.html
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
|
||||
|
||||
<!-- Set the viewport width to match phone and tablet device widths -->
|
||||
<meta name="viewport" content="width=device-width,user-scalable=no" />
|
||||
|
||||
<!-- Allow KeymanWeb to be saved to the iPhone home screen -->
|
||||
<meta name="apple-mobile-web-app-capable" content="yes" />
|
||||
|
||||
<!-- Enable IE9 Standards mode -->
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
<title>KeymanWeb Sample Page - Unminified Source</title>
|
||||
|
||||
<!-- Your page CSS -->
|
||||
<style type='text/css'>
|
||||
body {font-family: Tahoma,helvetica;}
|
||||
h3 {font-size: 1em;font-weight:normal;color: darkred; margin-bottom: 4px}
|
||||
.test {font-size: 1.5em; width:80%; min-height:30px; border: 1px solid gray;}
|
||||
#KeymanWebControl {width:50%;min-width:600px;}
|
||||
</style>
|
||||
|
||||
<!-- Insert uncompiled KeymanWeb source scripts -->
|
||||
<script src="../../release/web/keymanweb.js" type="application/javascript"></script>
|
||||
|
||||
<!--
|
||||
For desktop browsers, a script for the user interface must be inserted here.
|
||||
|
||||
Standard UIs are toggle, button, float and toolbar.
|
||||
The toolbar UI is best for any page designed to support keyboards for
|
||||
a large number of languages.
|
||||
-->
|
||||
<script src="../../release/web/kmwuitoggle.js"></script>
|
||||
|
||||
<script src="../../node_modules/@keymanapp/web-sentry-manager/dist/index.js"></script>
|
||||
|
||||
<!-- Initialization: set paths to keyboards, resources and fonts as required -->
|
||||
<script>
|
||||
var kmw=window.keyman;
|
||||
kmw.init({
|
||||
attachType:'auto'
|
||||
});
|
||||
|
||||
var sentryManager = new com.keyman.KeymanSentryManager();
|
||||
sentryManager.init();
|
||||
</script>
|
||||
|
||||
<!-- Add keyboard management script for local selection of keyboards to use -->
|
||||
<script src="errorhdr.js"></script>
|
||||
|
||||
</head>
|
||||
|
||||
<!-- Sample page HTML -->
|
||||
<body onload='loadKeyboards(1);'>
|
||||
<h2>KeymanWeb Sample Page - Sentry Setup test host</h2>
|
||||
|
||||
<div>
|
||||
<!--
|
||||
The following DIV is used to position the Button or Toolbar User Interfaces on the page.
|
||||
If omitted, those User Interfaces will appear at the top of the document body.
|
||||
(It is ignored by other User Interfaces.)
|
||||
-->
|
||||
<div id='KeymanWebControl'></div>
|
||||
|
||||
<h3>Type in your language in this text area:</h3>
|
||||
<textarea id='ta1' class='test' placeholder='Type here'></textarea>
|
||||
|
||||
<h3>or in this input field:</h3>
|
||||
<input class='test' value='' placeholder='or here'/>
|
||||
|
||||
<!-- The following elements show how the language menu can be dynamically extended at any time -->
|
||||
<h3>Add a keyboard by keyboard name:</h3>
|
||||
<input type='input' id='kbd_id1' class='kmw-disabled' onkeypress="clickOnEnter(event,1);"/>
|
||||
<input type='button' id='btn1' onclick='addKeyboard(1);' value='Add' />
|
||||
|
||||
<h3>Add a keyboard by BCP-47 language code:</h3>
|
||||
<input type='input' id='kbd_id2' class='kmw-disabled' onkeypress="clickOnEnter(event,2);"/>
|
||||
<input type='button' id='btn2' onclick='addKeyboard(2);' value='Add' />
|
||||
|
||||
<h3>Add a keyboard by language name:</h3>
|
||||
<input type='input' id='kbd_id3' class='kmw-disabled' onkeypress="clickOnEnter(event,3);"/>
|
||||
<input type='button' id='btn3' onclick='addKeyboard(3);' value='Add' />
|
||||
|
||||
<h3><a href="./">Return to testing home page</a></h3>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
|
||||
<!--
|
||||
*** DEVELOPER NOTE -- FIREFOX CONFIGURATION FOR TESTING ***
|
||||
*
|
||||
* If the URL bar starts with <b>file://</b>, Firefox may not load the font used
|
||||
* to display the special characters used in the On-Screen Keyboard.
|
||||
*
|
||||
* To work around this Firefox bug, navigate to <b>about:config</b>
|
||||
* and set <b>security.fileuri.strict_origin_policy</b> to <b>false</b>
|
||||
* while testing.
|
||||
*
|
||||
* Firefox resolves website-based CSS URI references correctly without needing
|
||||
* any configuration change, so this change should only be made for file-based testing.
|
||||
*
|
||||
***
|
||||
-->
|
||||
</html>
|
||||
10
web/testing/sentry-integration/timeout.js
Normal file
10
web/testing/sentry-integration/timeout.js
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
(function() {
|
||||
var me = document.currentScript;
|
||||
console.log(me);
|
||||
document.body.addEventListener('load', function(e) {
|
||||
// Prevent the element's onload event from firing
|
||||
if(e.srcElement == me || e.target == me) {
|
||||
e.cancelBubble = true;
|
||||
}
|
||||
}, {capture: true});
|
||||
})();
|
||||
1
web/testing/sentry-integration/unparsable.js
Normal file
1
web/testing/sentry-integration/unparsable.js
Normal file
|
|
@ -0,0 +1 @@
|
|||
// As there is no parsable keyboard here, we need to report that we couldn't register the requested keyboard.
|
||||
|
|
@ -7,11 +7,12 @@
|
|||
## START STANDARD BUILD SCRIPT INCLUDE
|
||||
# adjust relative paths as necessary
|
||||
THIS_SCRIPT="$(greadlink -f "${BASH_SOURCE[0]}" 2>/dev/null || readlink -f "${BASH_SOURCE[0]}")"
|
||||
SCRIPT_DIR="$(dirname "$THIS_SCRIPT")"
|
||||
. "$(dirname "$THIS_SCRIPT")/../../../resources/build/build-utils.sh"
|
||||
. "$KEYMAN_ROOT/resources/shellHelperFunctions.sh"
|
||||
## END STANDARD BUILD SCRIPT INCLUDE
|
||||
|
||||
SCRIPT_DIR="$(dirname "$THIS_SCRIPT")"
|
||||
|
||||
# Ensure the dependencies are downloaded. --no-optional should help block fsevents warnings.
|
||||
verify_npm_setup
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue