@cosmol-studio/cosmolkit-core-3d 0.0.0-stage → 0.5.0-rc.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +239 -2
- package/package.json +33 -4
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline0.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline1.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline10.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline11.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline12.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline13.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline2.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline3.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline4.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline5.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline6.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline7.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline8.js +1 -0
- package/snippets/wasm-wasm-caf920d9aee5a9bb/inline9.js +1 -0
- package/wasm_wasm.d.ts +2614 -0
- package/wasm_wasm.js +12181 -0
- package/wasm_wasm_bg.wasm +0 -0
- package/wasm_wasm_bg.wasm.d.ts +988 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 COSMolKit Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,240 @@
|
|
|
1
|
-
#
|
|
1
|
+
# COSMolKit WASM
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
`@cosmol-studio/cosmolkit` is the WebAssembly projection of the Rust `cosmolkit` facade. The
|
|
4
|
+
package uses the `wasm-bindgen` `web` target and exposes an opaque
|
|
5
|
+
`Molecule` value. Parsing and chemistry errors are thrown as JavaScript
|
|
6
|
+
exceptions; successful methods return strings, numbers, typed arrays, or new
|
|
7
|
+
`Molecule` values.
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm install @cosmol-studio/cosmolkit
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
The default package is **full**. Each smaller distribution has its own package
|
|
16
|
+
name, so upgrading it cannot select a different feature combination:
|
|
17
|
+
|
|
18
|
+
| Package name (under `@cosmol-studio/`) | Included public features |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `cosmolkit-core` | `core`, including molecular IO and batch processing |
|
|
21
|
+
| `cosmolkit-core-search` | `core + search` |
|
|
22
|
+
| `cosmolkit-core-fingerprints` | `core + fingerprints` |
|
|
23
|
+
| `cosmolkit-core-analysis` | `core + search + fingerprints + descriptors` |
|
|
24
|
+
| `cosmolkit-core-reaction` | `core + reaction` (including search) |
|
|
25
|
+
| `cosmolkit-core-depict` | `core + depict` |
|
|
26
|
+
| `cosmolkit-core-3d` | `core + conformer` (including forcefields and alignment) |
|
|
27
|
+
| `cosmolkit-core-bio` | `core + bio` |
|
|
28
|
+
| `cosmolkit-core-inchi` | `core + inchi` |
|
|
29
|
+
| `cosmolkit` | `full` |
|
|
30
|
+
|
|
31
|
+
For example: `npm install @cosmol-studio/cosmolkit-core-bio`, then import from
|
|
32
|
+
`"@cosmol-studio/cosmolkit-core-bio"`. Omitted domains are absent from both exports and TypeScript
|
|
33
|
+
declarations; they are not runtime placeholders.
|
|
34
|
+
|
|
35
|
+
WASM uses the Rust facade's feature tree, generated from its Cargo manifest.
|
|
36
|
+
The platform exception is binary archives: `toBinary`/`fromBinary` and the
|
|
37
|
+
binary-only encoding dependencies are not compiled, even in `full`.
|
|
38
|
+
Query IO needs `search`; automatic 2D coordinate generation needs `depict`.
|
|
39
|
+
Without these capabilities, shared IO entrypoints report an explicit error.
|
|
40
|
+
|
|
41
|
+
All packages use the Rust release version, without a feature suffix. Stable
|
|
42
|
+
releases update `latest`; RC releases update `rc`, not `latest`. To install an
|
|
43
|
+
RC, use e.g. `npm install @cosmol-studio/cosmolkit-core-bio@rc`. Tags identify
|
|
44
|
+
release channels, never feature combinations. Pin a version or use a lockfile
|
|
45
|
+
for reproducible installs.
|
|
46
|
+
|
|
47
|
+
Existing installations using feature dist-tags such as `cosmolkit@core-bio`
|
|
48
|
+
must switch once to the corresponding package name. New releases do not update
|
|
49
|
+
those old feature tags.
|
|
50
|
+
|
|
51
|
+
InChI is available in `core-inchi` and the default full package:
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
const molecule = Molecule.fromSmiles("CCO");
|
|
55
|
+
console.log(molecule.toInchi());
|
|
56
|
+
console.log(molecule.toInchiKey());
|
|
57
|
+
const restored = Molecule.fromInchi(molecule.toInchi());
|
|
58
|
+
restored.free();
|
|
59
|
+
molecule.free();
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The package is browser/bundler-oriented. It can be used from Vite, webpack,
|
|
63
|
+
Rollup, and other tools that support the web `WebAssembly` target.
|
|
64
|
+
|
|
65
|
+
## Native JavaScript
|
|
66
|
+
|
|
67
|
+
Initialize the module once before using `Molecule`:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import init, { Molecule } from "@cosmol-studio/cosmolkit";
|
|
71
|
+
|
|
72
|
+
await init();
|
|
73
|
+
|
|
74
|
+
const molecule = Molecule.fromSmiles("CCO");
|
|
75
|
+
console.log(molecule.toSmiles());
|
|
76
|
+
console.log(molecule.numAtoms());
|
|
77
|
+
molecule.free();
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
The published npm package is scoped as `@cosmol-studio/cosmolkit`. The Rust
|
|
81
|
+
binding crate remains `cosmolkit-wasm` internally.
|
|
82
|
+
|
|
83
|
+
## Native JavaScript From A CDN
|
|
84
|
+
|
|
85
|
+
For a browser page that does not use a bundler, import the generated web
|
|
86
|
+
module from jsDelivr. Pin the package version in production and keep the
|
|
87
|
+
background `.wasm` file on the same CDN host:
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<div id="molecule"></div>
|
|
91
|
+
<script type="module">
|
|
92
|
+
import init, { Molecule } from
|
|
93
|
+
"https://cdn.jsdelivr.net/npm/@cosmol-studio/cosmolkit@0.5.0/wasm_wasm.js";
|
|
94
|
+
|
|
95
|
+
await init(
|
|
96
|
+
"https://cdn.jsdelivr.net/npm/@cosmol-studio/cosmolkit@0.5.0/wasm_wasm_bg.wasm",
|
|
97
|
+
);
|
|
98
|
+
const molecule = Molecule.fromSmiles("c1ccccc1O");
|
|
99
|
+
document.querySelector("#molecule").textContent = molecule.toSmiles();
|
|
100
|
+
molecule.free();
|
|
101
|
+
</script>
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
The generated wasm-bindgen module is currently named `wasm_wasm.js` because
|
|
105
|
+
Alef derives the generated Cargo package from the `wasm/` source directory.
|
|
106
|
+
The package export remains `Molecule`; the generated filename is an artifact
|
|
107
|
+
of the binding build and should be updated here if that output layout changes.
|
|
108
|
+
|
|
109
|
+
More focused examples are in [`examples/vanilla`](./examples/vanilla/):
|
|
110
|
+
|
|
111
|
+
- [`basic.js`](./examples/vanilla/basic.js): parse, write, and render SVG.
|
|
112
|
+
- [`cdn.html`](./examples/vanilla/cdn.html): run the web module directly from
|
|
113
|
+
jsDelivr without a bundler.
|
|
114
|
+
- [`descriptors.js`](./examples/vanilla/descriptors.js): descriptors and typed
|
|
115
|
+
coordinate arrays.
|
|
116
|
+
- [`fingerprints.js`](./examples/vanilla/fingerprints.js): typed fingerprint
|
|
117
|
+
bit vectors.
|
|
118
|
+
- [`substructure.js`](./examples/vanilla/substructure.js): SMARTS matching and
|
|
119
|
+
disconnected fragments.
|
|
120
|
+
- [`stereo.js`](./examples/vanilla/stereo.js): stereochemistry and conformers.
|
|
121
|
+
|
|
122
|
+
## React
|
|
123
|
+
|
|
124
|
+
The React example keeps initialization and molecule ownership in component
|
|
125
|
+
state. It does not call the Rust API during render:
|
|
126
|
+
|
|
127
|
+
```jsx
|
|
128
|
+
import { useEffect, useState } from "react";
|
|
129
|
+
import init, { Molecule } from "@cosmol-studio/cosmolkit";
|
|
130
|
+
|
|
131
|
+
export function MoleculePanel({ smiles }) {
|
|
132
|
+
const [ready, setReady] = useState(false);
|
|
133
|
+
const [molecule, setMolecule] = useState(null);
|
|
134
|
+
const [error, setError] = useState(null);
|
|
135
|
+
|
|
136
|
+
useEffect(() => {
|
|
137
|
+
let active = true;
|
|
138
|
+
init()
|
|
139
|
+
.then(() => {
|
|
140
|
+
if (active) setReady(true);
|
|
141
|
+
})
|
|
142
|
+
.catch((value) => {
|
|
143
|
+
if (active) setError(String(value));
|
|
144
|
+
});
|
|
145
|
+
return () => {
|
|
146
|
+
active = false;
|
|
147
|
+
};
|
|
148
|
+
}, []);
|
|
149
|
+
|
|
150
|
+
useEffect(() => {
|
|
151
|
+
if (!ready) return;
|
|
152
|
+
try {
|
|
153
|
+
const next = Molecule.fromSmiles(smiles);
|
|
154
|
+
setMolecule(next);
|
|
155
|
+
setError(null);
|
|
156
|
+
} catch (value) {
|
|
157
|
+
setError(String(value));
|
|
158
|
+
}
|
|
159
|
+
}, [ready, smiles]);
|
|
160
|
+
|
|
161
|
+
useEffect(() => () => molecule?.free(), [molecule]);
|
|
162
|
+
|
|
163
|
+
if (error) return <pre>{error}</pre>;
|
|
164
|
+
if (!molecule) return <p>Loading COSMolKit...</p>;
|
|
165
|
+
return <output>{molecule.toSmiles()} ({molecule.numAtoms()} atoms)</output>;
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
The complete copyable component is
|
|
170
|
+
[`examples/react/MoleculePanel.jsx`](./examples/react/MoleculePanel.jsx).
|
|
171
|
+
|
|
172
|
+
## Vue
|
|
173
|
+
|
|
174
|
+
Vue applications should initialize in `onMounted` and replace the previous
|
|
175
|
+
opaque value when the input changes:
|
|
176
|
+
|
|
177
|
+
```vue
|
|
178
|
+
<script setup>
|
|
179
|
+
import { onBeforeUnmount, onMounted, ref, watch } from "vue";
|
|
180
|
+
import init, { Molecule } from "@cosmol-studio/cosmolkit";
|
|
181
|
+
|
|
182
|
+
const props = defineProps({ smiles: { type: String, default: "CCO" } });
|
|
183
|
+
const molecule = ref(null);
|
|
184
|
+
const error = ref("");
|
|
185
|
+
|
|
186
|
+
async function update() {
|
|
187
|
+
try {
|
|
188
|
+
const next = Molecule.fromSmiles(props.smiles);
|
|
189
|
+
molecule.value?.free();
|
|
190
|
+
molecule.value = next;
|
|
191
|
+
error.value = "";
|
|
192
|
+
} catch (value) {
|
|
193
|
+
error.value = String(value);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
onMounted(async () => {
|
|
198
|
+
try {
|
|
199
|
+
await init();
|
|
200
|
+
await update();
|
|
201
|
+
} catch (value) {
|
|
202
|
+
error.value = String(value);
|
|
203
|
+
}
|
|
204
|
+
});
|
|
205
|
+
watch(() => props.smiles, update);
|
|
206
|
+
onBeforeUnmount(() => molecule.value?.free());
|
|
207
|
+
</script>
|
|
208
|
+
|
|
209
|
+
<template>
|
|
210
|
+
<pre v-if="error">{{ error }}</pre>
|
|
211
|
+
<output v-else-if="molecule">{{ molecule.toSmiles() }}</output>
|
|
212
|
+
<p v-else>Loading COSMolKit...</p>
|
|
213
|
+
</template>
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
The complete component is [`examples/vue/MoleculePanel.vue`](./examples/vue/MoleculePanel.vue).
|
|
217
|
+
|
|
218
|
+
## Ownership And Errors
|
|
219
|
+
|
|
220
|
+
`Molecule` values own Rust allocations. Keep a value while it is in use and
|
|
221
|
+
call `.free()` when a long-lived UI state or worker no longer needs it. Methods
|
|
222
|
+
such as `withHydrogens()`, `with2dCoordinates()`, and
|
|
223
|
+
`with3dConformer()` return new values and leave the source value unchanged.
|
|
224
|
+
|
|
225
|
+
Fingerprint methods return `Uint32Array` set-bit lists. Coordinate methods
|
|
226
|
+
return flattened `Float64Array` values. Native binary archives are intentionally
|
|
227
|
+
not part of the WASM API.
|
|
228
|
+
|
|
229
|
+
## Examples
|
|
230
|
+
|
|
231
|
+
The examples are intentionally small and use only the published package:
|
|
232
|
+
|
|
233
|
+
- [`examples/vanilla/basic.js`](./examples/vanilla/basic.js)
|
|
234
|
+
- [`examples/vanilla/cdn.html`](./examples/vanilla/cdn.html)
|
|
235
|
+
- [`examples/vanilla/descriptors.js`](./examples/vanilla/descriptors.js)
|
|
236
|
+
- [`examples/vanilla/fingerprints.js`](./examples/vanilla/fingerprints.js)
|
|
237
|
+
- [`examples/vanilla/substructure.js`](./examples/vanilla/substructure.js)
|
|
238
|
+
- [`examples/vanilla/stereo.js`](./examples/vanilla/stereo.js)
|
|
239
|
+
- [`examples/react/MoleculePanel.jsx`](./examples/react/MoleculePanel.jsx)
|
|
240
|
+
- [`examples/vue/MoleculePanel.vue`](./examples/vue/MoleculePanel.vue)
|
package/package.json
CHANGED
|
@@ -1,6 +1,35 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cosmol-studio/cosmolkit-core-3d",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.5.0-rc.19",
|
|
4
|
+
"cosmolkitPreset": "core-3d",
|
|
5
|
+
"cosmolkitVersion": "0.5.0-rc.19",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"access": "public",
|
|
8
|
+
"tag": "rc"
|
|
9
|
+
},
|
|
10
|
+
"description": "WebAssembly bindings for COSMolKit",
|
|
11
|
+
"type": "module",
|
|
12
|
+
"main": "wasm_wasm.js",
|
|
13
|
+
"module": "wasm_wasm.js",
|
|
14
|
+
"types": "wasm_wasm.d.ts",
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"types": "./wasm_wasm.d.ts",
|
|
18
|
+
"default": "./wasm_wasm.js"
|
|
19
|
+
},
|
|
20
|
+
"./*": "./*"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"*.js",
|
|
24
|
+
"*.d.ts",
|
|
25
|
+
"*.wasm",
|
|
26
|
+
"snippets",
|
|
27
|
+
"README.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "https://github.com/cosmol-studio/COSMolKit"
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitSdfBatchRead(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SdfReadParams',{cause});}} export function visitSdfBatchExport(v,f){try{f(v);}catch(cause){throw new TypeError('invalid BatchExportParams',{cause});}} export function visitSdfDataset(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SdfDataset',{cause});}} export function attachSdfBatchIterator(v){Object.defineProperty(v,Symbol.iterator,{value:function(){return this;}});return v;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitSdfReadParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SdfReadParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitDistanceMatrix3dParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid DistanceMatrix3dParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitSanitizeParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SanitizeParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitMol2Params(v,f){try{f(v);}catch(cause){throw new TypeError('invalid Mol2ReadParams',{cause});}} export function visitXyzParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid XyzWriteParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitHydrogenAddParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid AddHsParams',{cause});}} export function visitHydrogenRemoveParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid RemoveHsParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitGroupId(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SubstanceGroupId',{cause});}} export function visitGroupKind(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SubstanceGroupKind',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitSupplierParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SdfReadParams',{cause});}} export function attachSdfIterator(v){Object.defineProperty(v,Symbol.iterator,{value:function(){return this;}});return v;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visit_batch_records(records, visit) { for (const record of records) visit(record); }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitMolSelection(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MolCoordinateSelection',{cause});}} export function visitMolWriteParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MolBlockWriteParams',{cause});}} export function visitMolQuery(v,f){try{f(v);}catch(cause){throw new TypeError('invalid QueryGraph',{cause});}} export function visitMolProperties(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MoleculeProperties',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visit_sanitize_operations(value, visit) { try { visit(value); } catch (cause) { throw new TypeError('invalid SanitizeOperations', { cause }); } }
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitRingSearchParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid RingSearchParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitKekulizeParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid KekulizeParams',{cause});}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function visitDistanceMatrixParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid DistanceMatrixParams',{cause});}}
|