From b7eaa67143f7ec851ccc38e74176544da8e202c3 Mon Sep 17 00:00:00 2001 From: Fadi George Date: Thu, 27 Feb 2025 12:49:23 -0800 Subject: [PATCH] handle additional parameters --- .eslintrc.js | 1 - .github/workflows/cd.yml | 4 +- OneSignalSDKWorker.js | 1 + README.md | 6 +- build/scripts/ngrok.sh | 90 ++++++++++++++++++++++ build/scripts/publish.sh | 39 ---------- express_webpack/README.md | 21 +++-- index.html | 2 - package.json | 5 +- src/page/services/DynamicResourceLoader.ts | 2 +- src/page/stylesheets/helpers.scss | 13 +++- src/page/utils/OneSignalShimLoader.ts | 11 +-- src/shared/managers/SdkEnvironment.test.ts | 10 ++- src/shared/managers/SdkEnvironment.ts | 22 ++---- vite.config.ts | 13 ++-- vitest.config.ts | 11 ++- 16 files changed, 154 insertions(+), 97 deletions(-) create mode 100644 build/scripts/ngrok.sh delete mode 100755 build/scripts/publish.sh diff --git a/.eslintrc.js b/.eslintrc.js index c470c6c4c..97b67c8af 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -24,5 +24,4 @@ module.exports = { }, }, ], - ignores: ['build/**/*'], }; diff --git a/.github/workflows/cd.yml b/.github/workflows/cd.yml index 47b2d5dab..077754cf6 100644 --- a/.github/workflows/cd.yml +++ b/.github/workflows/cd.yml @@ -18,9 +18,9 @@ jobs: - name: '[Build] Staging' env: STAGING_DOMAIN: ${{ secrets.STAGING_DOMAIN }} - run: BUILD_ORIGIN=${STAGING_DOMAIN} API=staging API_ORIGIN=${STAGING_DOMAIN} npm run build-old:staging + run: BUILD_ORIGIN=${STAGING_DOMAIN} API=staging API_ORIGIN=${STAGING_DOMAIN} npm run build:staging - name: '[Build] Production' - run: npm run build-old:prod + run: npm run build:prod - name: 'Authenticate to Google Cloud' uses: 'google-github-actions/auth@v1' with: diff --git a/OneSignalSDKWorker.js b/OneSignalSDKWorker.js index fcfbc8628..9e935c30e 100644 --- a/OneSignalSDKWorker.js +++ b/OneSignalSDKWorker.js @@ -1 +1,2 @@ +// Not part of bundle, just for local development import './src/entries/worker'; diff --git a/README.md b/README.md index ec852fb9a..d91dc9c86 100644 --- a/README.md +++ b/README.md @@ -11,9 +11,13 @@ This SDK allows your site's visitors to receive push notifications from you. Send visitors custom notification content, target specific users, and send automatically based on triggers. - ## Getting Started View our [documentation](https://documentation.onesignal.com/docs/web-push-quickstart) to get started. Please reference the OneSignal SDK on your webpage via our CDN URL (listed in our setup documentation) instead of copying the source into another file. This is because our SDK updates frequently for new features and bug fixes. + +## Local Development + +Install the dependencies `npm install` then you can `npm run dev`. This will start a dev server on port 4001. +The code will use navigator register on OneSignalSDKWorker.js to register the code as service worker. diff --git a/build/scripts/ngrok.sh b/build/scripts/ngrok.sh new file mode 100644 index 000000000..56c4b5723 --- /dev/null +++ b/build/scripts/ngrok.sh @@ -0,0 +1,90 @@ +#!/bin/bash + +startNgrokHTTPSForwarding() { + processesIncludeNgrok=$(ps aux | grep ngrok | wc -l) + if [ $processesIncludeNgrok -gt 3 ]; then + existing_url=$(cat ngrok_last_url) + echo "ngrok is already running on at: $existing_url" + echo -e "run 'killall ngrok' if you want a new URL or it isn't working.\n" + retval=$existing_url + return + fi + + # Start ngrok + rm ngrok.log + ngrok http https://localhost:4001 --log=ngrok.log > /dev/null & + echo "starting ngrok..." + + # Wait for ngrok to start + sleep 5 + + # Get the ngrok url + read -r rawurl < <(curl localhost:4040/api/tunnels | jq -r '.tunnels | .[0] | .public_url') + url=$(echo $rawurl | sed 's/https:\/\///') + echo "ngrok url: $url" + rm -f ngrok_last_url + echo $url > ngrok_last_url + echo "" + + retval=$url + return +} + +buildSDK() { + local url=${1} + + # Build the SDK + echo -e "Building SDK with build origin $url\n" + # If you want to test with staging, change to build:dev-stag and add -a MY_API_URL + docker-compose exec onesignal-web-sdk-dev BUILD_ORIGIN=$url NO_DEV_PORT=true npm run build:dev-prod + + echo -e "BuildSDK() Done.\n" +} + +# Open the ngrok url in your default browser +openBrowserToUrl() { + local url=${1} + + if [ -x "$(command -v open)" ]; then + # macOS + open $url + else + # Linux + xdg-open $url + fi +} + +updateSiteUrlNoteToUserAndOpenTestSite() { + local url=${1} + + echo -e "Open your default browser to $url" + + echo -e \ + "#############################\n" \ + "NOTE: Last Step:\n" \ + "Open your browser to" \ + "https://dashboard.onesignal.com/apps/{{ONESIGNAL_APP_ID_HERE}}/settings/webpush/configure\n" \ + "then update your site URL to https://$url/\n" \ + "#############################\n" + + openBrowserToUrl "https://$url" +} + +checkIfNgrokIsInstalled() { + # Check if ngrok is installed + if ! [ -x "$(command -v ngrok)" ]; then + echo 'ngrok is not installed.' + echo 'Please install ngrok to use this script.' + exit 1 + fi + + echo -e 'ngrok is installed. Continuing with script execution.\n' +} + +checkIfNgrokIsInstalled + +startNgrokHTTPSForwarding +url=$retval + +buildSDK $url +updateSiteUrlNoteToUserAndOpenTestSite $url diff --git a/build/scripts/publish.sh b/build/scripts/publish.sh deleted file mode 100755 index 2835d878f..000000000 --- a/build/scripts/publish.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash - -getPrefix() { - if [ "$ENV" = "production" ]; then - echo "" - elif [ "$ENV" = "staging" ]; then - echo "Staging-" - else - echo "Dev-" - fi -} - -PREFIX=$(getPrefix) -set -x - -pwd - -mkdir -p build/releases - -# Copy files with the prefix -cp build/bundles/OneSignalSDK.page.js build/releases/$PREFIX"OneSignalSDK.page.js" -cp build/bundles/OneSignalSDK.page.js.map build/releases/$PREFIX"OneSignalSDK.page.js.map" - -cp build/bundles/OneSignalSDK.page.es6.js build/releases/$PREFIX"OneSignalSDK.page.es6.js" -cp build/bundles/OneSignalSDK.page.es6.js.map build/releases/$PREFIX"OneSignalSDK.page.es6.js.map" - -cp build/bundles/OneSignalSDK.sw.js build/releases/$PREFIX"OneSignalSDK.sw.js" -cp build/bundles/OneSignalSDK.sw.js.map build/releases/$PREFIX"OneSignalSDK.sw.js.map" - -cp build/bundles/OneSignalSDK.page.styles.css build/releases/$PREFIX"OneSignalSDK.page.styles.css" -cp build/bundles/OneSignalSDK.page.styles.css.map build/releases/$PREFIX"OneSignalSDK.page.styles.css.map" - -# Update sourceMappingURL to include the prefix -for file in build/releases/$PREFIX*.js build/releases/$PREFIX*.css; do - # Ensure we're only updating files with a sourceMappingURL - if grep -q "sourceMappingURL=" "$file"; then - sed -i "s|sourceMappingURL=OneSignal|sourceMappingURL=${PREFIX}OneSignal|g" "$file" - fi -done diff --git a/express_webpack/README.md b/express_webpack/README.md index 784644ab0..c1a72270d 100644 --- a/express_webpack/README.md +++ b/express_webpack/README.md @@ -55,11 +55,10 @@ npm run build:- ### CUSTOM ORIGIN PARAMS: -You can pass two additional parameters to the above command, the first being the origin of the build environment and the second being that of the api environment. These parameters use option flags. +You can pass two additional variables to the above command, the first being the origin of the build environment and the second being that of the api environment. These env vars are: -- Option flags are: - - `-b` or `--build` - - `-a` or `--api` +- BUILD_ORIGIN +- API_ORIGIN If no custom origins are set, defaults will be used: `localhost` for build and `onesignal.com` for api. @@ -68,22 +67,22 @@ If no custom origins are set, defaults will be used: `localhost` for build and ` **Examples**: ``` -npm run build-old:dev-prod -b texas +API_ORIGIN=texas npm run build:dev-prod ``` This sets the BUILD environment origin to `texas` which will result in SDK files being fetched from `https://texas:4001/sdks/web/v##/` and the API environment origin to production which will make all onesignal api calls to the production origin `https://onesignal.com/api/v1/apps/` ``` -npm run build-old:dev-dev -b localhost -a texas +BUILD_ORIGIN=localhost API_ORIGIN=texas npm run build:dev-dev ``` This sets the BUILD environment origin to `localhost` which will result in SDK files being fetched from `https://localhost:4001/sdks/web/v##/` and the API environment origin to the default `https://texas:3001/api/v1/apps/` ### HTTP -All builds default to `https` unless `--http` is passed to the end of the build command... +All builds default to `https` unless `HTTPS=false` is passed to the build command... -**Example**: `npm run build-old:dev-prod --http` or `npm run build-old:dev-prod -b localhost --http` +**Example**: `HTTPS=false npm run build:dev-prod` or `HTTPS=false BUILD_ORIGIN=localhost npm run build:dev-prod` ### NOTE ON PORTS: @@ -92,7 +91,7 @@ All builds default to `https` unless `--http` is passed to the end of the build - HTTP: `4000` - HTTPS: `4001` -Use the **`--no-port`** build flag to build without a port number. This is useful when using a reverse proxy like [ngrok](https://ngrok.com/) to serve your localhost environment on the web. +Use the **`NO_DEV_PORT=true`** build env var to build without a port number. This is useful when using a reverse proxy like [ngrok](https://ngrok.com/) to serve your localhost environment on the web. **API**: dev-environment API calls will be made to the `3001` port (e.g: `:3001`) @@ -116,13 +115,11 @@ You may want to run the Web SDK Sandbox with the configuration `dev-dev`. You wi - change the URLs in the file `development.rb` so that they point to the files' absolute paths (these are the files in the `build` directory after running `npm run build:<>-<>`) -4. Remove the `$PREFIX` var from the `publish.sh` script for all map files - ## Troubleshooting ### Custom origin mismatch -Check the network tab in the browser dev tools to see what origin the SDK is using for network calls. If you set the `-a` flag origin to something other than `onesignal.com` but it is still using that, make sure you are using the correct build command. For example, if you set the origin to `staging.onesignal.com` you should _not_ be using the `dev-prod` environment since the `prod` will result in the ignoring of the custom origin parameter. The fix in this case would be to use `dev-stag`. +Check the network tab in the browser dev tools to see what origin the SDK is using for network calls. If you set the `API_ORIGIN` var to something other than `onesignal.com` but it is still using that, make sure you are using the correct build command. For example, if you set the origin to `staging.onesignal.com` you should _not_ be using the `dev-prod` environment since the `prod` will result in the ignoring of the custom origin parameter. The fix in this case would be to use `dev-stag`. ## Debugging Tips for OneSignal WebSDK Sandbox diff --git a/index.html b/index.html index 9e5d66427..dedefc670 100644 --- a/index.html +++ b/index.html @@ -11,8 +11,6 @@ OneSignalDeferred.push(async function (OneSignal) { await OneSignal.init({ appId: '%VITE_APP_ID%', // add yours to .env.local\ - // serviceWorkerParam: { scope: '/' }, - // serviceWorkerPath: './src/entries/worker.ts', }); }); diff --git a/package.json b/package.json index 49ff61cef..bab9ba3a1 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,10 @@ "build": "npm run build:sdk && npm run build:page && npm run build:sw", "build:dev": "ENV=development npm run build", "build:staging": "ENV=staging npm run build", - "build:prod": "ENV=production npm run build && size-limit", + "build:prod": "ENV=production API=production npm run build && size-limit", + "build:dev-dev": "API=development npm run build:dev", + "build:dev-prod": "API=production API_ORIGIN=onesignal.com npm run build:dev", + "build:dev-stag": "API=staging API_ORIGIN=onesignal.com npm run build:dev", "test": "vitest run --coverage", "test:watch": "vitest watch --coverage", "lint": "eslint src --ext .js,.jsx,.ts,.tsx; prettylint 'src/**/*' 'test/**/*' '__test__/**/*' --no-editorconfig" diff --git a/src/page/services/DynamicResourceLoader.ts b/src/page/services/DynamicResourceLoader.ts index 6d2ed0f10..b531a10c7 100644 --- a/src/page/services/DynamicResourceLoader.ts +++ b/src/page/services/DynamicResourceLoader.ts @@ -1,5 +1,5 @@ -import SdkEnvironment from '../../shared/managers/SdkEnvironment'; import Environment from '../../shared/helpers/Environment'; +import SdkEnvironment from '../../shared/managers/SdkEnvironment'; export const enum ResourceType { Stylesheet, diff --git a/src/page/stylesheets/helpers.scss b/src/page/stylesheets/helpers.scss index bd9c1e2ae..f45d4fea2 100755 --- a/src/page/stylesheets/helpers.scss +++ b/src/page/stylesheets/helpers.scss @@ -1,6 +1,6 @@ -@use "sass:list"; -@use "sass:map"; -@use "sass:meta"; +@use 'sass:list'; +@use 'sass:map'; +@use 'sass:meta'; /* http://stackoverflow.com/a/6900392 */ @mixin unselectable() { -webkit-touch-callout: none; @@ -60,7 +60,12 @@ @mixin _position($position, $args) { @each $o in top right bottom left { $i: list.index($args, $o); - @if $i and $i + 1 <= list.length($args) and meta.type-of(list.nth($args, $i + 1)) == number + @if $i and + $i + + 1 <= + list.length($args) and + meta.type-of(list.nth($args, $i + 1)) == + number { #{$o}: list.nth($args, $i + 1); } diff --git a/src/page/utils/OneSignalShimLoader.ts b/src/page/utils/OneSignalShimLoader.ts index dbe56c6eb..f3dc216e1 100644 --- a/src/page/utils/OneSignalShimLoader.ts +++ b/src/page/utils/OneSignalShimLoader.ts @@ -20,17 +20,10 @@ export class OneSignalShimLoader { // Same logic from SdkEnvironment private static getPathAndPrefix(): string { - const buildOrigin = - typeof __BUILD_ORIGIN__ !== 'undefined' - ? __BUILD_ORIGIN__ || 'localhost' - : 'localhost'; + const buildOrigin = __BUILD_ORIGIN__; const productionOrigin = 'https://cdn.onesignal.com/sdks/web/v16/'; - if (typeof __BUILD_TYPE__ === 'undefined') { - return productionOrigin; - } - - const isHttps = typeof __IS_HTTPS__ !== 'undefined' ? __IS_HTTPS__ : true; + const isHttps = __IS_HTTPS__; const protocol = isHttps ? 'https' : 'http'; const port = isHttps ? 4001 : 4000; diff --git a/src/shared/managers/SdkEnvironment.test.ts b/src/shared/managers/SdkEnvironment.test.ts index 60d30a0ce..c65264621 100644 --- a/src/shared/managers/SdkEnvironment.test.ts +++ b/src/shared/managers/SdkEnvironment.test.ts @@ -1,8 +1,15 @@ // @vitest-environment node -import { WindowEnvironmentKind } from '../models/WindowEnvironmentKind'; import { EnvironmentKind } from '../models/EnvironmentKind'; +import { WindowEnvironmentKind } from '../models/WindowEnvironmentKind'; import SdkEnvironment from './SdkEnvironment'; +let apiType: string = global.__API_TYPE__; +let apiOrigin: string = global.__API_ORIGIN__; +afterEach(() => { + global.__API_TYPE__ = apiType; + global.__API_ORIGIN__ = apiOrigin; +}); + describe('SdkEnvironment', () => { test('can determine window environment', () => { // @ts-expect-error - mock self to test host environment @@ -31,6 +38,7 @@ describe('SdkEnvironment', () => { ); // development - turbine endpoint + global.__API_ORIGIN__ = 'localhost'; expect( SdkEnvironment.getOneSignalApiUrl(EnvironmentKind.Development).toString(), ).toBe('http://localhost:3000/api/v1'); diff --git a/src/shared/managers/SdkEnvironment.ts b/src/shared/managers/SdkEnvironment.ts index d82865112..0c572450d 100644 --- a/src/shared/managers/SdkEnvironment.ts +++ b/src/shared/managers/SdkEnvironment.ts @@ -1,10 +1,10 @@ -import { EnvironmentKind } from '../models/EnvironmentKind'; -import { WindowEnvironmentKind } from '../models/WindowEnvironmentKind'; import { InvalidArgumentError, InvalidArgumentReason, } from '../errors/InvalidArgumentError'; import Environment from '../helpers/Environment'; +import { EnvironmentKind } from '../models/EnvironmentKind'; +import { WindowEnvironmentKind } from '../models/WindowEnvironmentKind'; const RESOURCE_HTTP_PORT = 4000; const RESOURCE_HTTPS_PORT = 4001; @@ -22,9 +22,6 @@ export default class SdkEnvironment { * building the SDK. */ public static getBuildEnv(): EnvironmentKind { - if (typeof __BUILD_TYPE__ === 'undefined') { - return EnvironmentKind.Production; - } switch (__BUILD_TYPE__) { case 'development': return EnvironmentKind.Development; @@ -43,9 +40,6 @@ export default class SdkEnvironment { * Refers to which API environment should be used. These constants are set when building the SDK */ public static getApiEnv(): EnvironmentKind { - if (typeof __API_TYPE__ === 'undefined') { - return EnvironmentKind.Production; - } switch (__API_TYPE__) { case 'development': return EnvironmentKind.Development; @@ -119,10 +113,7 @@ export default class SdkEnvironment { buildEnv: EnvironmentKind = SdkEnvironment.getApiEnv(), action?: string, ): URL { - const apiOrigin = - typeof __API_ORIGIN__ !== 'undefined' - ? __API_ORIGIN__ || 'localhost' - : 'localhost'; + const apiOrigin = __API_ORIGIN__; switch (buildEnv) { case EnvironmentKind.Development: @@ -152,11 +143,8 @@ export default class SdkEnvironment { public static getOneSignalResourceUrlPath( buildEnv: EnvironmentKind = SdkEnvironment.getBuildEnv(), ): URL { - const buildOrigin = - typeof __BUILD_ORIGIN__ !== 'undefined' - ? __BUILD_ORIGIN__ || 'localhost' - : 'localhost'; - const isHttps = typeof __IS_HTTPS__ !== 'undefined' ? __IS_HTTPS__ : true; + const buildOrigin = __BUILD_ORIGIN__; + const isHttps = __IS_HTTPS__; let origin: string; const protocol = isHttps ? 'https' : 'http'; const port = isHttps ? RESOURCE_HTTPS_PORT : RESOURCE_HTTP_PORT; diff --git a/vite.config.ts b/vite.config.ts index 5693fa116..53c256037 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -76,14 +76,15 @@ export default defineConfig(({ mode }) => { }, }, }, + // Could move some of these to .env.[ENV] file define: { - __API_ORIGIN__: JSON.stringify(process.env.API_ORIGIN), - __API_TYPE__: JSON.stringify(process.env.API), - __BUILD_ORIGIN__: JSON.stringify(process.env.BUILD_ORIGIN), - __BUILD_TYPE__: JSON.stringify(process.env.ENV), - __IS_HTTPS__: JSON.stringify(true), + __API_ORIGIN__: JSON.stringify(process.env.API_ORIGIN || 'localhost'), + __API_TYPE__: JSON.stringify(process.env.API || 'development'), + __BUILD_ORIGIN__: JSON.stringify(process.env.BUILD_ORIGIN || 'localhost'), + __BUILD_TYPE__: JSON.stringify(process.env.ENV || 'development'), + __IS_HTTPS__: JSON.stringify(process.env.HTTPS ?? true), __LOGGING__: JSON.stringify(isDevMode), - __NO_DEV_PORT__: JSON.stringify(process.env.NO_DEV_PORT), + __NO_DEV_PORT__: JSON.stringify(process.env.NO_DEV_PORT ?? false), __VERSION__: JSON.stringify(process.env.npm_package_config_sdkVersion), }, server: { diff --git a/vitest.config.ts b/vitest.config.ts index 4022c5255..0a523c700 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -1,6 +1,15 @@ -import { defineConfig } from 'vitest/config'; import path from 'path'; +import { defineConfig } from 'vitest/config'; + export default defineConfig({ + define: { + __BUILD_ORIGIN__: JSON.stringify('onesignal.com'), + __BUILD_TYPE__: JSON.stringify('production'), + __API_TYPE__: JSON.stringify('staging'), + __API_ORIGIN__: JSON.stringify('onesignal.com'), + __IS_HTTPS__: JSON.stringify(true), + __NO_DEV_PORT__: JSON.stringify(true), + }, resolve: { alias: { src: path.resolve(__dirname, 'src'),