Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Analytics improvements #3874

Merged
merged 6 commits into from
Feb 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions apps/pwabuilder-vscode/src/library/package-utils.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import { writeFile } from "fs/promises";
const fetch = require('node-fetch');
import { Headers, Response } from "node-fetch";
import { Response } from "node-fetch";
import { Manifest, MsixInfo } from "../interfaces";

import * as vscode from "vscode";
import { AndroidPackageOptions } from "../android-interfaces";
import { URL } from "url";

import { trackEvent, trackException } from "../services/usage-analytics";
import { getSessionID, standard_headers, trackEvent, trackException } from "../services/usage-analytics";
import { getURL } from "../services/web-publish";

export const WindowsDocsURL =
Expand Down Expand Up @@ -72,12 +72,13 @@ export async function packageForWindows(options: any) {
let response: Response | undefined;

try {

response = await fetch(
"https://pwabuilder-winserver.centralus.cloudapp.azure.com/msix/generatezip",
{
method: "POST",
body: JSON.stringify(options),
headers: new Headers({ "content-type": "application/json" }),
headers: standard_headers,
}
);
} catch (err: any) {
Expand Down Expand Up @@ -134,7 +135,7 @@ export async function buildAndroidPackage(options: AndroidPackageOptions) {
response = await fetch(generateAppUrl, {
method: "POST",
body: JSON.stringify(options),
headers: new Headers({ "content-type": "application/json" }),
headers: standard_headers,
});
} catch (err: any) {
vscode.window.showErrorMessage(
Expand All @@ -159,7 +160,7 @@ export async function buildIOSPackage(options: IOSAppPackageOptions) {
response = await fetch(generateAppUrl, {
method: "POST",
body: JSON.stringify(options),
headers: new Headers({ "content-type": "application/json" }),
headers: standard_headers,
});
} catch (err: any) {
vscode.window.showErrorMessage(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import * as vscode from 'vscode';
const fetch = require('node-fetch');
import { writeFile } from 'fs/promises';
import { Manifest } from '../../interfaces';
import { trackEvent, trackException } from "../usage-analytics";
import { standard_headers, trackEvent, trackException } from "../usage-analytics";
import { findManifest } from './manifest-service';

const pwaAssetGenerator = require('pwa-asset-generator');
Expand Down Expand Up @@ -40,9 +40,7 @@ export async function generateScreenshots(skipPrompts?: boolean) {
try {
const response = await fetch(url, {
method: 'POST',
headers: {
'content-type': 'application/json',
},
headers: standard_headers,
body: JSON.stringify({
url: [urlToScreenshot]
}),
Expand Down
26 changes: 24 additions & 2 deletions apps/pwabuilder-vscode/src/services/usage-analytics.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,18 @@
import { setup, defaultClient } from 'applicationinsights';
import { getFlag } from '../flags';

import * as vscode from 'vscode';
import { Headers } from 'node-fetch';

const sessionID = getSessionID();
export const standard_headers = new Headers(
{
"content-type": "application/json",
"Platform-Identifier": "PWAStudio",
"Correlation-Id": sessionID,
}
)

export function initAnalytics() {
try {
// check flag first
Expand All @@ -22,13 +34,20 @@ export function initAnalytics() {
}
}

export function getSessionID() {
return vscode.env.sessionId;
}

// function to trackEvent
export function trackEvent(name: string, properties: any) {
try {
if (getFlag("analytics") === true) {

// add session id to properties
properties.sessionId = getSessionID();

defaultClient.trackEvent({
name,
name,
properties
});
}
Expand All @@ -44,7 +63,10 @@ export function trackException(err: Error) {
try {
if (getFlag("analytics") === true) {
defaultClient.trackException({
exception: err
exception: err,
properties: {
sessionId: getSessionID()
}
});
}
}
Expand Down
183 changes: 103 additions & 80 deletions libraries/manifest-validation/src/validations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,29 @@ export const maniTests: Array<Validation> = [
return value && typeof value === "string" && value.length > 0;
}
},
{
infoString: "The handle_links field specifies how links to your app are opened, either in your app itself or in the users browser",
displayString: "Manifest has handle_links field",
category: "recommended",
member: "handle_links",
defaultValue: "auto",
docsLink: "",
errorString: "handle_links is recommended and should be either auto, preferred or not-proferred",
quickFix: true,
test: (value: string) => {
if (value && typeof value === "string") {
if (value === "auto" || "preferred" || "not-preferred") {
return true;
}
else {
return false;
}
}
else {
return false;
}
}
},
{
infoString: "share_target enables your app to get shared content from other apps",
displayString: "Manifest has share_target field",
Expand All @@ -28,7 +51,7 @@ export const maniTests: Array<Validation> = [
"title": "title",
"text": "text",
"url": "url"
}
}
}),
docsLink: "https://web.dev/web-share-target/",
errorString: "share_target must be an object",
Expand Down Expand Up @@ -89,7 +112,7 @@ export const maniTests: Array<Validation> = [
quickFix: true,
test: (value: any[]) => {
const isArray = value && Array.isArray(value) && value.length > 0 ? true : false;

if (isArray) {
const anyIcon = value.find(icon => icon.purpose === "any");

Expand Down Expand Up @@ -124,7 +147,7 @@ export const maniTests: Array<Validation> = [
quickFix: false,
test: (value: any[]) => {
const isArray = value && Array.isArray(value) && value.length > 0 ? true : false;

if (isArray) {
const anyIcon = value.find(icon => isAtLeast(icon.sizes, 512, 512) && (icon.type === 'image/png' || icon.src.endsWith(".png")));

Expand Down Expand Up @@ -159,7 +182,7 @@ export const maniTests: Array<Validation> = [
quickFix: true,
test: (value: any[]) => {
const isArray = value && Array.isArray(value) && value.length > 0 ? true : false;

if (isArray) {
const wrongIcon = value.find(icon => icon.purpose === "any maskable");

Expand Down Expand Up @@ -210,8 +233,8 @@ export const maniTests: Array<Validation> = [
errorString: "short_name is required and must be a string with a length >= 3",
quickFix: true,
test: (value: string) => {
const existsAndLength = value && value.length >= 3;
return existsAndLength;
const existsAndLength = value && value.length >= 3;
return existsAndLength;
},
},
{
Expand Down Expand Up @@ -479,7 +502,7 @@ export const maniTests: Array<Validation> = [
"https://docs.pwabuilder.com/#/builder/manifest?id=prefer_related_applications-boolean",
quickFix: false, // @ Justin Willis, I added this but left it false because idk how to do quick fixes lol.
test: (value: any) => {
return typeof(value) === "boolean"
return typeof (value) === "boolean"
},
errorString: "prefer_related_applications should be set to a boolean value",
},
Expand All @@ -495,12 +518,12 @@ export const maniTests: Array<Validation> = [
quickFix: true,
test: (value: any[]) => {
let isGood;
if(value){
containsStandardCategory(value) && Array.isArray(value)
?
isGood = true
:
isGood = false;
if (value) {
containsStandardCategory(value) && Array.isArray(value)
?
isGood = true
:
isGood = false;
}

return isGood
Expand All @@ -518,7 +541,7 @@ export const maniTests: Array<Validation> = [
errorString: "lang should be set to a valid language code",
quickFix: true,
test: (value: string) =>
value && typeof value === "string" && value.length > 0 && isValidLanguageCode(value)
value && typeof value === "string" && value.length > 0 && isValidLanguageCode(value)
},
{
member: "dir",
Expand All @@ -531,7 +554,7 @@ export const maniTests: Array<Validation> = [
"https://docs.pwabuilder.com/#/builder/manifest?id=dir-string",
quickFix: true,
test: (value: string) =>
value && typeof value === "string" && value.length > 0 && (value === "ltr" || value === "rtl" || value === "auto")
value && typeof value === "string" && value.length > 0 && (value === "ltr" || value === "rtl" || value === "auto")
},
{
member: "description",
Expand Down Expand Up @@ -654,88 +677,88 @@ export const maniTests: Array<Validation> = [
export async function loopThroughKeys(manifest: Manifest): Promise<Array<Validation>> {
return new Promise((resolve) => {
let data: Array<Validation> = [];

const keys = Object.keys(manifest);

keys.forEach((key) => {
maniTests.forEach(async (test) => {
if (test.member === key && test.test) {
const testResult = await test.test(manifest[key]);
if(testResult){
test.valid = true;
data.push(test);


if (testResult) {
test.valid = true;
data.push(test);
}
else {
test.valid = false;
data.push(test);
test.valid = false;
data.push(test);
}
}
})
})

resolve(data);
})
}
export async function loopThroughRequiredKeys(manifest: Manifest): Promise<Array<Validation>> {
}

export async function loopThroughRequiredKeys(manifest: Manifest): Promise<Array<Validation>> {
return new Promise((resolve) => {
let data: Array<Validation> = [];

const keys = Object.keys(manifest);

keys.forEach((key) => {
maniTests.forEach(async (test) => {
if (test.category === "required") {
if (test.member === key && test.test) {
const testResult = await test.test(manifest[key]);

if (testResult === false) {
test.valid = false;
data.push(test);
}
else {
test.valid = true;
data.push(test);
}
}
}
let data: Array<Validation> = [];

const keys = Object.keys(manifest);

keys.forEach((key) => {
maniTests.forEach(async (test) => {
if (test.category === "required") {
if (test.member === key && test.test) {
const testResult = await test.test(manifest[key]);

if (testResult === false) {
test.valid = false;
data.push(test);
}
else {
test.valid = true;
data.push(test);
}
}
}
})
})
})

resolve(data);

resolve(data);
})
}
export async function findSingleField(field: string, value: any): Promise<singleFieldValidation> {
}

export async function findSingleField(field: string, value: any): Promise<singleFieldValidation> {
return new Promise(async (resolve) => {

// For && operations, true is the base.
let singleField = true;
let failedTests: string[] | undefined = [];

maniTests.forEach((test) => {
if (test.member === field && test.test) {

const testResult = test.test(value);

if(!testResult){
failedTests!.push(test.errorString!);
}

// If the test passes true && true = true.
// If the test fails true && false = false
// If a field has MULTIPLE tests, they will stack
// ie: true (base) && true (test 1) && false (ie test 2 fails).
singleField = singleField && testResult;

// For && operations, true is the base.
let singleField = true;
let failedTests: string[] | undefined = [];

maniTests.forEach((test) => {
if (test.member === field && test.test) {

const testResult = test.test(value);

if (!testResult) {
failedTests!.push(test.errorString!);
}

// If the test passes true && true = true.
// If the test fails true && false = false
// If a field has MULTIPLE tests, they will stack
// ie: true (base) && true (test 1) && false (ie test 2 fails).
singleField = singleField && testResult;
}
});

if (singleField) {
resolve({ "valid": singleField })
}
});

if(singleField){
resolve({"valid": singleField})
}

resolve({"valid": singleField, "errors": failedTests});

resolve({ "valid": singleField, "errors": failedTests });
})
}
Loading