From 08677c2e28a0567350aac2ce344679391430e472 Mon Sep 17 00:00:00 2001 From: Garrett Bjerkhoel Date: Wed, 13 Dec 2023 23:21:17 -0800 Subject: [PATCH 1/6] Bump version for start of work --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 214b5b4..ed6405f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "isinstock-extension", - "version": "0.1.3", + "version": "0.1.4", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "isinstock-extension", - "version": "0.1.3", + "version": "0.1.4", "dependencies": { "preact": "^10.11.3" }, diff --git a/package.json b/package.json index 9f1e831..8a628d7 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "isinstock-extension", "private": true, - "version": "0.1.3", + "version": "0.1.4", "prettier": "@github/prettier-config", "eslintConfig": { "extends": "preact" From 0d2b6ce96d440100e5f05e0ccae79e873c4eb3be Mon Sep 17 00:00:00 2001 From: Garrett Bjerkhoel Date: Thu, 14 Dec 2023 10:04:19 -0800 Subject: [PATCH 2/6] Setup version --- build.js | 1 - src/@types/global.d.ts | 1 - src/utils/fetch-api.ts | 7 ++++++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/build.js b/build.js index 53adbe3..2b3096a 100755 --- a/build.js +++ b/build.js @@ -67,7 +67,6 @@ const config = { minify: isProduction, target: ['ios15', 'chrome100', 'edge100', 'firefox100', 'safari15'], define: { - VERSION: `"${pkg.version}"`, ISINSTOCK_URL: isProduction ? '"https://isinstock.com"' : '"http://localhost:3000"', CHROME_EXTENSION_ID: '"bnglflgcpflggbpbcbpgeaknekceeojd"', }, diff --git a/src/@types/global.d.ts b/src/@types/global.d.ts index d91cc86..bbea4a2 100644 --- a/src/@types/global.d.ts +++ b/src/@types/global.d.ts @@ -1,4 +1,3 @@ -declare const VERSION: string declare const ISINSTOCK_URL: string declare const CHROME_EXTENSION_ID: string diff --git a/src/utils/fetch-api.ts b/src/utils/fetch-api.ts index 4fa5588..7c4cb86 100644 --- a/src/utils/fetch-api.ts +++ b/src/utils/fetch-api.ts @@ -1,19 +1,24 @@ import browser from 'webextension-polyfill' +import {getBrowserExtensionInstallToken} from './browser-extension-install-token' + +const browserExtensionInstallTokenHeader = 'X-Browser-Extension-Install-Token' const fetchApi = async ( path: string, - method: 'POST' | 'GET', + method: 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE', body?: BodyInit | null | undefined, signal?: AbortSignal | null | undefined, ) => { const {accessToken} = await browser.storage.local.get({ accessToken: '', }) + const browserExtensionInstallToken = await getBrowserExtensionInstallToken() const headers: HeadersInit = { 'Content-Type': 'application/json', Accept: 'application/json', 'X-Extension-Version': VERSION, + [browserExtensionInstallTokenHeader]: browserExtensionInstallToken, } if (accessToken !== '' && accessToken !== null) { headers['Authorization'] = `Bearer ${accessToken}` From 5265d8ab4e83526ec58758d7f3c71c90231fc7cd Mon Sep 17 00:00:00 2001 From: Garrett Bjerkhoel Date: Thu, 14 Dec 2023 10:04:28 -0800 Subject: [PATCH 3/6] Add a small API --- src/api/browser-extension-install.ts | 38 ++++++++++++++++++++ src/background.ts | 29 +++++++++++++++ src/utils/browser-extension-install-token.ts | 13 +++++++ src/utils/fetch-api.ts | 6 +++- src/utils/fetch-error.ts | 12 +++++++ 5 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 src/api/browser-extension-install.ts create mode 100644 src/utils/browser-extension-install-token.ts create mode 100644 src/utils/fetch-error.ts diff --git a/src/api/browser-extension-install.ts b/src/api/browser-extension-install.ts new file mode 100644 index 0000000..321310b --- /dev/null +++ b/src/api/browser-extension-install.ts @@ -0,0 +1,38 @@ +import fetchApi from '../utils/fetch-api' +import {FetchError} from '../utils/fetch-error' + +export type BrowserExtensionInstallResponseToken = { + token: string +} + +export type BrowserExtensionInstallResponseError = { + error: string +} + +export type BrowserExtensionInstallResponse = + | BrowserExtensionInstallResponseToken + | BrowserExtensionInstallResponseError + +export async function createBrowserExtensionInstall(version: string): Promise { + const body = JSON.stringify({version}) + const response = await fetchApi('/api/browser-extension-installs', 'POST', body) + if (!response.ok) { + throw new FetchError(response) + } + + return (await response.json()) as BrowserExtensionInstallResponseToken +} + +export async function updateBrowserExtensionInstall( + token: string, + version: string, +): Promise { + const path = `/api/browser-extension-installs/${token}` + const body = JSON.stringify({version}) + const response = await fetchApi(path, 'PATCH', body) + if (!response.ok) { + throw new FetchError(response) + } + + return (await response.json()) as BrowserExtensionInstallResponseToken +} diff --git a/src/background.ts b/src/background.ts index 623d2f3..86e4da0 100644 --- a/src/background.ts +++ b/src/background.ts @@ -2,6 +2,9 @@ import browser from 'webextension-polyfill' import {InventoryStateNormalized} from './@types/inventory-states' import {Message, MessageAction} from './@types/messages' +import {createBrowserExtensionInstall, updateBrowserExtensionInstall} from './api/browser-extension-install' +import {getBrowserExtensionInstallToken, setBrowserExtensionInstallToken} from './utils/browser-extension-install-token' +import {FetchError} from './utils/fetch-error' // As browser navigation changes, inform the content script as a hook for certain retailers to perform custom querying. const loadedTabs = new Map() @@ -22,6 +25,32 @@ browser.tabs.onUpdated.addListener( }, ) +// Register the install +browser.runtime.onInstalled.addListener(async () => { + try { + const existingToken = await getBrowserExtensionInstallToken() + if (existingToken !== '') { + await updateBrowserExtensionInstall(existingToken, browser.runtime.getManifest().version) + return + } + } catch (error) { + if (error instanceof FetchError && error.status === 404) { + console.debug('Browser extension install not found, creating new one') + } else { + throw error + } + } + + try { + const manifest = browser.runtime.getManifest() + const version = manifest.version + const {token} = await createBrowserExtensionInstall(version) + await setBrowserExtensionInstallToken(token) + } catch (e) { + console.debug('Error creating browser extension install', e) + } +}) + // Receives messages from content scripts browser.runtime.onMessage.addListener(({action, value}: Message, _sender) => { if (action === MessageAction.InventoryState) { diff --git a/src/utils/browser-extension-install-token.ts b/src/utils/browser-extension-install-token.ts new file mode 100644 index 0000000..abb9c5a --- /dev/null +++ b/src/utils/browser-extension-install-token.ts @@ -0,0 +1,13 @@ +import browser from 'webextension-polyfill' + +export async function setBrowserExtensionInstallToken(browserExtensionInstallToken: string) { + await browser.storage.sync.set({browserExtensionInstallToken}) +} + +export async function getBrowserExtensionInstallToken(): Promise { + const {browserExtensionInstallToken} = await browser.storage.sync.get({ + browserExtensionInstallToken: '', + }) + + return browserExtensionInstallToken +} diff --git a/src/utils/fetch-api.ts b/src/utils/fetch-api.ts index 7c4cb86..f8c2136 100644 --- a/src/utils/fetch-api.ts +++ b/src/utils/fetch-api.ts @@ -3,6 +3,10 @@ import browser from 'webextension-polyfill' import {getBrowserExtensionInstallToken} from './browser-extension-install-token' const browserExtensionInstallTokenHeader = 'X-Browser-Extension-Install-Token' +const browserExtensionVersionHeader = 'X-Browser-Extension-Version' +const manifest = browser.runtime.getManifest() +const version = manifest.version + const fetchApi = async ( path: string, method: 'POST' | 'GET' | 'PUT' | 'PATCH' | 'DELETE', @@ -17,7 +21,7 @@ const fetchApi = async ( const headers: HeadersInit = { 'Content-Type': 'application/json', Accept: 'application/json', - 'X-Extension-Version': VERSION, + [browserExtensionVersionHeader]: version, [browserExtensionInstallTokenHeader]: browserExtensionInstallToken, } if (accessToken !== '' && accessToken !== null) { diff --git a/src/utils/fetch-error.ts b/src/utils/fetch-error.ts new file mode 100644 index 0000000..6e31f7b --- /dev/null +++ b/src/utils/fetch-error.ts @@ -0,0 +1,12 @@ +export class FetchError extends Error { + status: number + response: Response + + constructor(response: Response) { + super(`Could not fetch ${response.url} (${response.status})`) + + this.status = response.status + this.response = response + this.name = 'FetchError' + } +} From 6a5a85fadb24a9c1e6b1521c050c9a19cc0e6bed Mon Sep 17 00:00:00 2001 From: Garrett Bjerkhoel Date: Sat, 16 Dec 2023 10:50:22 -0800 Subject: [PATCH 4/6] Track startups --- src/api/browser-extension-install.ts | 15 +++++++++++++-- src/background.ts | 25 ++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 5 deletions(-) diff --git a/src/api/browser-extension-install.ts b/src/api/browser-extension-install.ts index 321310b..e5e6a70 100644 --- a/src/api/browser-extension-install.ts +++ b/src/api/browser-extension-install.ts @@ -26,9 +26,10 @@ export async function createBrowserExtensionInstall(version: string): Promise
{ + reason: string, +): Promise { const path = `/api/browser-extension-installs/${token}` - const body = JSON.stringify({version}) + const body = JSON.stringify({version, reason}) const response = await fetchApi(path, 'PATCH', body) if (!response.ok) { throw new FetchError(response) @@ -36,3 +37,13 @@ export async function updateBrowserExtensionInstall( return (await response.json()) as BrowserExtensionInstallResponseToken } + +export async function browserExtensionStartup(token: string): Promise { + const path = `/api/browser-extension-installs/${token}/startup` + const response = await fetchApi(path, 'POST') + if (!response.ok) { + throw new FetchError(response) + } + + return true +} diff --git a/src/background.ts b/src/background.ts index 86e4da0..ec23120 100644 --- a/src/background.ts +++ b/src/background.ts @@ -2,7 +2,11 @@ import browser from 'webextension-polyfill' import {InventoryStateNormalized} from './@types/inventory-states' import {Message, MessageAction} from './@types/messages' -import {createBrowserExtensionInstall, updateBrowserExtensionInstall} from './api/browser-extension-install' +import { + browserExtensionStartup, + createBrowserExtensionInstall, + updateBrowserExtensionInstall, +} from './api/browser-extension-install' import {getBrowserExtensionInstallToken, setBrowserExtensionInstallToken} from './utils/browser-extension-install-token' import {FetchError} from './utils/fetch-error' @@ -25,12 +29,27 @@ browser.tabs.onUpdated.addListener( }, ) +browser.runtime.onStartup.addListener(async () => { + try { + const token = await getBrowserExtensionInstallToken() + if (token !== '') { + await browserExtensionStartup(token) + } + } catch (error) { + if (error instanceof FetchError && error.status === 404) { + console.debug('Browser extension install not found') + } else { + throw error + } + } +}) + // Register the install -browser.runtime.onInstalled.addListener(async () => { +browser.runtime.onInstalled.addListener(async ({reason}) => { try { const existingToken = await getBrowserExtensionInstallToken() if (existingToken !== '') { - await updateBrowserExtensionInstall(existingToken, browser.runtime.getManifest().version) + await updateBrowserExtensionInstall(existingToken, browser.runtime.getManifest().version, reason) return } } catch (error) { From a16b2037b3122dc7dfe8155e4b100e0b132716f3 Mon Sep 17 00:00:00 2001 From: Garrett Bjerkhoel Date: Sat, 16 Dec 2023 11:28:04 -0800 Subject: [PATCH 5/6] Don't always run jest tests --- .vscode/settings.json | 1 + 1 file changed, 1 insertion(+) diff --git a/.vscode/settings.json b/.vscode/settings.json index c2fa47e..b64a4c3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -16,6 +16,7 @@ "**/node_modules": true, "**/dist": true }, + "jest.autoRun": "off", "eslint.validate": ["javascript", "javascriptreact", "html", "typescript", "typescriptreact"], "eslint.alwaysShowStatus": true, "eslint.lintTask.enable": true, From 1ac70764bfbedb811ee01f3ad23bef96d5dddc47 Mon Sep 17 00:00:00 2001 From: Garrett Bjerkhoel Date: Sat, 16 Dec 2023 15:42:16 -0800 Subject: [PATCH 6/6] Clean up tests --- .vscode/settings.json | 2 +- safari/Is In Stock.xcodeproj/project.pbxproj | 16 ++++++++-------- .../UserInterfaceState.xcuserstate | Bin 43186 -> 43784 bytes src/__tests__/amazon.test.ts | 6 ++---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index b64a4c3..5b395aa 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -41,6 +41,6 @@ "javascript.preferences.quoteStyle": "single", "javascript.preferences.importModuleSpecifier": "relative", "editor.codeActionsOnSave": { - "source.fixAll.eslint": true + "source.fixAll.eslint": "explicit" } } diff --git a/safari/Is In Stock.xcodeproj/project.pbxproj b/safari/Is In Stock.xcodeproj/project.pbxproj index 8873662..4e024c6 100644 --- a/safari/Is In Stock.xcodeproj/project.pbxproj +++ b/safari/Is In Stock.xcodeproj/project.pbxproj @@ -433,7 +433,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = "Safari Extension/Is In Stock Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = PB45PKVTW4; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -446,7 +446,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 0.1.4; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -464,7 +464,7 @@ buildSettings = { CODE_SIGN_ENTITLEMENTS = "Safari Extension/Is In Stock Extension.entitlements"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = PB45PKVTW4; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -477,7 +477,7 @@ "@executable_path/../../../../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 1.0; + MARKETING_VERSION = 0.1.4; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -499,7 +499,7 @@ CODE_SIGN_ENTITLEMENTS = "macOS/Is In Stock.entitlements"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = PB45PKVTW4; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -514,7 +514,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 0.1.0; + MARKETING_VERSION = 0.1.4; OTHER_LDFLAGS = ( "-framework", SafariServices, @@ -537,7 +537,7 @@ CODE_SIGN_ENTITLEMENTS = "macOS/Is In Stock.entitlements"; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - CURRENT_PROJECT_VERSION = 1; + CURRENT_PROJECT_VERSION = 3; DEVELOPMENT_TEAM = PB45PKVTW4; ENABLE_HARDENED_RUNTIME = YES; GENERATE_INFOPLIST_FILE = YES; @@ -552,7 +552,7 @@ "@executable_path/../Frameworks", ); MACOSX_DEPLOYMENT_TARGET = 10.14; - MARKETING_VERSION = 0.1.0; + MARKETING_VERSION = 0.1.4; OTHER_LDFLAGS = ( "-framework", SafariServices, diff --git a/safari/Is In Stock.xcodeproj/project.xcworkspace/xcuserdata/dewski.xcuserdatad/UserInterfaceState.xcuserstate b/safari/Is In Stock.xcodeproj/project.xcworkspace/xcuserdata/dewski.xcuserdatad/UserInterfaceState.xcuserstate index bf9c620fc47872fccf8673802dddb74b41116c0b..73ae545e9c472bbc502d3cf48e6f027f7bd6de78 100644 GIT binary patch delta 21926 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 QQ2krFUj2LEIB((q2Q4|ij{pDw delta 21157 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 diff --git a/src/__tests__/amazon.test.ts b/src/__tests__/amazon.test.ts index e05ed41..bd97969 100644 --- a/src/__tests__/amazon.test.ts +++ b/src/__tests__/amazon.test.ts @@ -141,11 +141,10 @@ describe('Browser Extension Test', () => { test('popstate to restore page searches for products', async () => { await page.goto('https://www.amazon.com/dp/B08G58D42M/') await page.waitForSelector('#isinstock-button') - await page.goto('https://www.amazon.com/') await page.goBack() - const element = await page.waitForSelector('#isinstock-button') + const element = await page.waitForSelector('#isinstock-button') expect(element).not.toBe(null) }) @@ -166,8 +165,7 @@ describe('Browser Extension Test', () => { }) await page.goto('https://www.amazon.com/dp/B088HH6LW5/') - await page.click('[data-dp-url] button') - + await page.click(`[data-dp-url] button, [data-asin='B0BLF2RWNV'] input.a-button-input`) await page.waitForRequest(request => isValidationRequest(request)) expect(interceptedValidationsRequests).toStrictEqual([