How to access loaded script in Salesforce Lightning Web Component? - salesforce

When loading an external library in a Lightning Web Component, I can't seem to access the actual script.
Instead, I can only find the reference to the static resource by checking the resolved import string.
phone.js:
import { LightningElement } from 'lwc';
import { loadScript } from 'lightning/platformResourceLoader';
import JsSIP from '#salesforce/resourceUrl/jssip';
// import * as JsSIP from 'jssip';
export default class Phone extends LightningElement
{
...
async connectedCallback() {
console.log(JsSIP); // This resolves to the static resource location inside the connected org in a string.
loadScript(this, JsSIP + '/jssip.js')
.then(() => {
console.log(JsSIP.version); // This is only accessing the resource reference, not the actual script; so result is *undefined*.
...
}
So my question is: "How to access the loaded script instead of the resource reference?".
I've followed the guides here and here and found this GitHub issue that seems to be dealing with the same referencing problem. The solution however is not apparent for my specific case.
Any help with this would be much appreciated!

I think your library creates a "global" object called JsSIP once it finishes loading. And the name clashes with the name for the file reference. Can you name it import jssip or jsSipLibrary or something and see what happens?
Put debugger; statement into then and enable debugging in Setup -> debug mode. Open the page with browser's console (F12 most of the time)

Related

Importing JSON file - should not import the named export from default-exporting module

I have a sample JSON response from an API that is about 52,000 lines. I've saved it as TestJSONFile.json in my NextJS project.
This isn't permanent, but just a temporary measure so I can have access to a sample API response without needing to connect/implement the actual API calls at the moment.
The project is working fine and there are no crashes, but there is this warning message:
./src/components/CurrentComponent.js
Should not import the named export 'something' (imported as 'TestJSONFile') from default-exporting module (only default export is available soon)
printWarnings # hot-dev-client.js?a8a2:88
What can I do to get rid of this warning, just to make sure there are no issues later? I'm not entirely familiar with React so I'm not sure what the best way to handle this would be.
I don't need to call JSON.parse(), since once I manually added the sample response into my project (copy/paste the entire response), the data is already interpreted as a Javascript object and not a JSON string. I tried changing the filename from .json to .js to see if I could work with it that way without the warning, but the file had errors once I changed the extension.
TestJSONFile.json looks like:
{
"something": [
{
"prop1": "prop1value",
"prop2": "prop2value",
...
},
{
"prop1": "prop1value",
"prop2": "prop2value",
...
},
...
}
In CurrentComponent.js, I'm importing the JSON values:
import * as SampleResponse from '../tools/TestJSONFile'
And then accessing the data like this:
const data = SampleResponse.something // Already a JS object, no need to parse
And then can work with it like any other object:
for (let item of data) { const prop1 = item.prop1 }
Currently you are importing the JSON file as below
import * as SampleResponse from '../tools/TestJSONFile'
Change it to
import SampleResponse from '../tools/TestJSONFile'

Next.js renders blank screen in Safari due to Typescript enums

The website works fine in Chrome and Edge but not in Safari (for iOS).
It loads all the elements, styling, and scripts but nothing is displayed.
After several hours of debugging, turns out it's due to an enum import (not any specific one). I know this because when I remove the import everything starts to work just fine.
I'm working in a mono repo (using Yarn workspaces) and all the enums are located in a "shared" package. Importing a class from this "shared" package that already implements the enum works fine, however, importing any enum directly into the web app causes the issue.
// #*/shared
// ./enums/Protocol.ts
export enum Protocol {
ETHEREUM = 'ETHEREUM'
}
// ./index.js
...
export * from './enums';
export * from './types';
export * from './utils';
...
// #*/web
// ./modules/api/ApiClient.ts
import { Protocol } from '#*/shared'; // This does NOT work
// Here's an example that implements the enum indirectly.
// #*/shared
import { Protocol } from '../enums';
export class Wallet {
protocol: Protocol;
}
// #*/web
// ./components/User.tsx
import { Wallet } from '#*/shared'; // This works
If the same enum is defined locally, in the "web" package (no import), that also works.
// #*/web
// ./modules/api/ApiClient.ts
enum Protocol {
ETHEREUM = "ETHEREUM"
}
class ApiClient {
getWallet(protocol: Protocol, address: string) {
... // Also works
}
}
No errors are displayed whatsoever, hence I'm really struggling to find out what the issue is. Also, as aforementioned, this issue is only present in Safari.
Any help would be appreciated.
Solved. I learnt that importing (and actually using) anything from that "shared" package caused the issue. The reason behind this was an unsupported regex (lookbehind is still not supported by Safari).
To summarise: importing anything from a package that exports a malformed/unsupported regex will cause an issue.

Cesium using local/offline tileserver (TypeScript)

I am trying to set up a local/offline tileserver to serve Cesium's tiles for the 3D Planet/Globe. I have completed my setup for Resium and Cesium based on the following thread I created. After the necessary setup I then retrieved a Precompiled Cesium Assets provided by cesium and placed it within my Python Server. I Have also came across the following guide for Offline Cesium as well as an example for Online Cesium.
After following the guide I noticed that it wasn't working as expected and found out that createTileMapServiceImageryProvider has been deprecated, so I decided to use UrlTemplateImageryProvider instead.
Next, I began to render react cesium using the following code.
First, I did the necessary Imports
import * as cesium from 'cesium';
import * as React from 'react';
import { Entity, PointGraphics, Viewer } from 'resium';
Secondly, I created my Tile Server Properties
const tms = new cesium.UrlTemplateImageryProvider({
url: 'https://localhost:5000/{z}/{x}/{y}.png',
maximumLevel:10,
})
Once created I used it for my Viewer.
<Viewer
baseLayerPicker={ false }
geocoder={ false }
imageryProvider={ tms }
full={ false }
homeButton={ false }
fullscreenButton={ false }
vrButton={ false }
infoBox={ false }
navigationHelpButton={ false }
>
<Entity position= { cesium.Cartesian3.fromDegree(-74, 40, 100) }>
<PointGraphics pixelSize={ 10 }/>
</Entity>
</Viewer>
Even with the following settings above I noticed that my "Network" tab is not retrieving the necessary PNG Files. Which means that cesium is not even attempting to render my Planet/Globe for some reason.
Currently, there are two errors within my console which states importScripts failed for Workers/createVerticesFromHeightmap..... and TypeError: data.loaderConfig is undefined
It can be noted that geocoder and baseLayerPicker is set as false to prevent an error related to cesium ion default access token.

How to use the new #Shopify/app-bridge with #Shopify/polaris-react

Shopify recently released their new #shopify/app-bridge, but it is unclear to me how it should be used alongside #shopify/polaris.
For example, I have tried to make a React component that will use the app-bridge and polaris to display a toast.
import React, { Component } from "react";
import * as PropTypes from "prop-types";
import { Toast } from "#shopify/app-bridge/actions";
import { Page } from "#shopify/polaris";
class Start extends Component {
static contextTypes = {
polaris: PropTypes.object
};
showToast() {
console.log("SHOW TOAST");
console.log(this.context.polaris.appBridge);
const toastNotice = Toast.create(this.context.polaris.appBridge, {
message: "Test Toast",
duration: 5000
});
toastNotice.dispatch(Toast.Action.SHOW);
}
render() {
this.showToast();
return (
<Page title="Do you see toast?">
<p>I do not see toast.</p>
</Page>
);
}
}
export default Start;
But it does not seem to dispatch the action. Any ideas on why not? Note that my app is wrapped in the AppProvider and app-bridge is initialized.
ReactDOM.render(
<AppProvider
apiKey={process.env.REACT_APP_SHOPIFY_API_KEY}
shopOrigin={queryString.parse(window.location.search).shop}
>
<Start />
</AppProvider>,
document.getElementById("root")
);
Any suggestions?
So after a lot of debugging, I found out from Shopify that inside App Bridge, before taking any action, they check that the localOrigin matches the appURL (one that's entered in the partners dashboard). In my case, I have a backend (node.js on heroku used for authentication) and a frontend (react bundle on firebase) my app starts by hitting the backend, and then if authentication checks out, it redirects to the front end. And hence the localOrigin does not match... hmmm, I'm very glad to have figured this out since I lost a lot of sleep over it. Now the question is what to do about it... maybe this is something that could be updated with AppBridge? Or is there a better design I should be considering?
There is now #shopify/app-bridge-react,
https://www.npmjs.com/package/#shopify/app-bridge-react
Shopify supposedly doesn't have docs for it yet though... But, someone can update my answer when they come out with them. :)
NOTE:
Be sure to have, static contextType = Context; to get access to this.context for dispatching actions/etc in your components.
(Hopefully this saves you days of suffering haha I'm not a React developer, so, yeah... this was not marked as "crucial" or anything in the examples).
I also wanted to address #SomethingOn's comment, but I don't have enough reputation to comment...
You actually can debug an iframe. In chrome dev tools, on top where it says "top", you can actually select a frame that you want to debug.
https://stackoverflow.com/a/8581276/10076085
Once you select the Shopify App iframe, type in "window.location" or whatever you want!
Shopify's docs and examples are limited and I'm running into a bunch of issues myself working on a Shopify App, so I just want to spread help as much as possible!

Play 2.5.3 ScriptException: TypeError: Cannot call undefined in <eval> at line number 1

I managed to download and run successfully the project here but then it broke after upgrading to Play 2.5.3. Any help? The error is on the last instruction
package controllers
import javax.inject._
import play.api._
import play.api.http._
import play.api.mvc._
import play.twirl.api.Html
import java.io.FileReader
import javax.script.ScriptEngineManager
#Singleton
class HomeController #Inject()(webJarAssets: WebJarAssets) extends Controller {
/**
* Create an Action to render an HTML page with a welcome message.
* The configuration in the `routes` file means that this method
* will be called when the application receives a `GET` request with
* a path of `/`.
*/
def index2 = Action {
Ok(views.html.index("Your new application is ready.",webJarAssets))
}
def index = Action {
// Pass 'null' to force the correct class loader. Without passing any param,
// the "nashorn" JavaScript engine is not found by the `ScriptEngineManager`.
//
// See: https://github.com/playframework/playframework/issues/2532
val engine = new ScriptEngineManager(null).getEngineByName("nashorn")
if (engine == null) {
BadRequest("Nashorn script engine not found. Are you using JDK 8?")
} else {
// React expects `window` or `global` to exist. Create a `global` pointing
// to Nashorn's context to give React a place to define its global
// namespace.
engine.eval("var global = this;")
// Define `console.log`, etc. to send messages to Nashorn's global `print`
// function so the messages are written to standard out.
engine.eval("var console = {error: print, log: print, warn: print};")
// Evaluate React and the application code.
engine.eval(new FileReader("target/web/web-modules/main/webjars/lib/react/react-with-addons.js"))
engine.eval(new FileReader("target/web/public/main/javascripts/components/App.js"))
Ok(views.html.main("React on Play",webJarAssets) {
play.twirl.api.Html(engine.eval("React.renderToString(React.createElement(App));").toString)
})
}
}
}

Resources