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

Offline usage examples #160

Open
MichelML opened this issue Aug 7, 2022 · 5 comments
Open

Offline usage examples #160

MichelML opened this issue Aug 7, 2022 · 5 comments
Labels
documentation Improvements or additions to documentation enhancement New feature or request

Comments

@MichelML
Copy link
Collaborator

MichelML commented Aug 7, 2022

Add examples on how to use rdkit-js in a offline-first app

see context here #150 (comment)

@MichelML MichelML added documentation Improvements or additions to documentation enhancement New feature or request labels Aug 7, 2022
@adam-of-barot
Copy link
Contributor

adam-of-barot commented Oct 11, 2022

I started experimenting with using the module in a browser-less / Node.js only setting. I've managed to load the module relatively easily and do some basic things with it.

I'm a little unsure as to what would count as an "offline-first" app. Just some bare .js / .ts files, without any browser interaction or HTML?

Edit:

Very basic example

// index.js
import initRDKitModule from '@rdkit/rdkit'

initRDKitModule()
.then((rdkit) => {
    console.log(rdkit.version())
})

// console output
> 2022.03.5

@swamidass
Copy link

Just being able to do server-side rendering would be very useful, both of depictions (particularly SVGs), and also (and likely easier) for molecule canonization.

@Acylation
Copy link

Acylation commented Mar 11, 2024

Showcase here. I'm building a plugin for the note-taking app Obsidian, aiming to render SMILES strings as chemical structures. Repo link

Challenges

  • Obsidian is built on Electron, so I can't access local assets directly via file paths
  • The plugins are recommended to write in TypeScript
  • I want to implement asynchronous loading to ensure that the structures are rendered correctly, rather than invoking an undefined window.RDKit when the notes are ready

Solutions

  • Create an object URL from local wasm file (indirectly calling fs and conducted a binary read), then provide it to param locateFile for initRDKitModule()
  • Follow the instructions in TypeScript/README.md and create a type definition
  • Asynchronously read .wasm file as binary and .js script as text. The former is turned into an object URL and loaded. Create a script tag and set .js text as its innerHTML
    • I used unpkg distributions as a backup. The wasm URL works fine for locateFile, but I can't simply set the URL of .js script as the src attribute for a script tag. It's still necessary to conduct an async fetch and set the innerHTML as the response text.

@ptosco
Copy link

ptosco commented Mar 12, 2024

@Acylation You may want to look at how I deal with this in rdkit-structure-renderer. There are several examples of plain HTML pages that bootstrap themselves by loading the bundle through a script tag:
https://github.com/rdkit/rdkit-structure-renderer/blob/master/index.html
https://github.com/rdkit/rdkit-structure-renderer/blob/master/api_examples/svg_using_bundle.html
Structures are rendered as soon as the bundle has loaded and initialized.

@Acylation
Copy link

Acylation commented Mar 12, 2024

@ptosco yes using onload callback here is quite reasonable and elegant. As I want to get a return value from the async onload (comparing to calling window.RDKit directly, this can ensure that I get a initialized reference), I need to do some "promisify". Following are the two versions for loading the package and they both work well.

Thanks a lot for providing these efficient examples!

Before

const loadRDKitUnpkg = async () => {
	const rdkitBundler = document.createElement('script');
        document.body.appendChild(rdkitBundler);
	console.log('Fetching RDKit.js from unpkg...');

        //requestUrl() is an API that fetching js scripts as text asynchoronously, based on `fetch()` API
	rdkitBundler.innerHTML = await requestUrl( 'https://unpkg.com/@rdkit/rdkit/dist/RDKit_minimal.js').text;

	const RDKit = await window.initRDKitModule({
		locateFile: () => 'https://unpkg.com/@rdkit/rdkit/dist/RDKit_minimal.wasm',
	});
	console.log('RDKit.js has been successfully loaded.');
	return RDKit;
};

After

const loadRDKitUnpkg = async () => {
	const rdkitBundler = document.createElement('script');
        document.body.appendChild(rdkitBundler);
	console.log('Fetching RDKit.js from unpkg...');

	rdkitBundler.src = 'https://unpkg.com/@rdkit/rdkit/dist/RDKit_minimal.js';
	return new Promise<RDKitModule>((resolve, reject) => {
		rdkitBundler.onload = async () => {
			const RDKit = await window.initRDKitModule({
				locateFile: () => 'https://unpkg.com/@rdkit/rdkit/dist/RDKit_minimal.wasm',
			});
			console.log('RDKit.js has been successfully loaded.');
			resolve(RDKit);
			rdkitBundler.onerror = (error) => {
				reject(error);
			};
		};
	});
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants