@cosmol-studio/cosmolkit 0.0.0-stage → 0.5.0-rc.13

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.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +194 -2
  3. package/package.json +27 -4
  4. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline0.js +1 -0
  5. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline1.js +1 -0
  6. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline10.js +1 -0
  7. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline11.js +1 -0
  8. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline12.js +1 -0
  9. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline13.js +1 -0
  10. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline14.js +1 -0
  11. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline15.js +1 -0
  12. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline16.js +1 -0
  13. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline17.js +1 -0
  14. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline18.js +1 -0
  15. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline19.js +1 -0
  16. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline2.js +1 -0
  17. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline20.js +1 -0
  18. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline21.js +1 -0
  19. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline22.js +1 -0
  20. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline23.js +1 -0
  21. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline24.js +1 -0
  22. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline25.js +1 -0
  23. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline26.js +1 -0
  24. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline27.js +1 -0
  25. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline28.js +1 -0
  26. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline29.js +1 -0
  27. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline3.js +1 -0
  28. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline30.js +1 -0
  29. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline31.js +1 -0
  30. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline32.js +1 -0
  31. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline4.js +1 -0
  32. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline5.js +1 -0
  33. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline6.js +1 -0
  34. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline7.js +1 -0
  35. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline8.js +1 -0
  36. package/snippets/wasm-wasm-2e23ff5c4614b73b/inline9.js +1 -0
  37. package/wasm_wasm.d.ts +7634 -0
  38. package/wasm_wasm.js +34001 -0
  39. package/wasm_wasm_bg.wasm +0 -0
  40. package/wasm_wasm_bg.wasm.d.ts +2804 -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,195 @@
1
- # Temporary Holding Version
1
+ # COSMolKit WASM
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
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 package is browser/bundler-oriented. It can be used from Vite, webpack,
16
+ Rollup, and other tools that support the web `WebAssembly` target.
17
+
18
+ ## Native JavaScript
19
+
20
+ Initialize the module once before using `Molecule`:
21
+
22
+ ```js
23
+ import init, { Molecule } from "@cosmol-studio/cosmolkit";
24
+
25
+ await init();
26
+
27
+ const molecule = Molecule.fromSmiles("CCO");
28
+ console.log(molecule.toSmiles());
29
+ console.log(molecule.numAtoms());
30
+ molecule.free();
31
+ ```
32
+
33
+ The published npm package is scoped as `@cosmol-studio/cosmolkit`. The Rust
34
+ binding crate remains `cosmolkit-wasm` internally.
35
+
36
+ ## Native JavaScript From A CDN
37
+
38
+ For a browser page that does not use a bundler, import the generated web
39
+ module from jsDelivr. Pin the package version in production and keep the
40
+ background `.wasm` file on the same CDN host:
41
+
42
+ ```html
43
+ <div id="molecule"></div>
44
+ <script type="module">
45
+ import init, { Molecule } from
46
+ "https://cdn.jsdelivr.net/npm/@cosmol-studio/cosmolkit@0.3.0/wasm_wasm.js";
47
+
48
+ await init(
49
+ "https://cdn.jsdelivr.net/npm/@cosmol-studio/cosmolkit@0.3.0/wasm_wasm_bg.wasm",
50
+ );
51
+ const molecule = Molecule.fromSmiles("c1ccccc1O");
52
+ document.querySelector("#molecule").textContent = molecule.toSmiles();
53
+ molecule.free();
54
+ </script>
55
+ ```
56
+
57
+ The generated wasm-bindgen module is currently named `wasm_wasm.js` because
58
+ Alef derives the generated Cargo package from the `wasm/` source directory.
59
+ The package export remains `Molecule`; the generated filename is an artifact
60
+ of the binding build and should be updated here if that output layout changes.
61
+
62
+ More focused examples are in [`examples/vanilla`](./examples/vanilla/):
63
+
64
+ - [`basic.js`](./examples/vanilla/basic.js): parse, write, and render SVG.
65
+ - [`cdn.html`](./examples/vanilla/cdn.html): run the web module directly from
66
+ jsDelivr without a bundler.
67
+ - [`descriptors.js`](./examples/vanilla/descriptors.js): descriptors and typed
68
+ coordinate arrays.
69
+ - [`fingerprints.js`](./examples/vanilla/fingerprints.js): typed fingerprint
70
+ bit vectors.
71
+ - [`binary.js`](./examples/vanilla/binary.js): binary serialization roundtrip.
72
+ - [`substructure.js`](./examples/vanilla/substructure.js): SMARTS matching and
73
+ disconnected fragments.
74
+ - [`stereo.js`](./examples/vanilla/stereo.js): stereochemistry and conformers.
75
+
76
+ ## React
77
+
78
+ The React example keeps initialization and molecule ownership in component
79
+ state. It does not call the Rust API during render:
80
+
81
+ ```jsx
82
+ import { useEffect, useState } from "react";
83
+ import init, { Molecule } from "@cosmol-studio/cosmolkit";
84
+
85
+ export function MoleculePanel({ smiles }) {
86
+ const [ready, setReady] = useState(false);
87
+ const [molecule, setMolecule] = useState(null);
88
+ const [error, setError] = useState(null);
89
+
90
+ useEffect(() => {
91
+ let active = true;
92
+ init()
93
+ .then(() => {
94
+ if (active) setReady(true);
95
+ })
96
+ .catch((value) => {
97
+ if (active) setError(String(value));
98
+ });
99
+ return () => {
100
+ active = false;
101
+ };
102
+ }, []);
103
+
104
+ useEffect(() => {
105
+ if (!ready) return;
106
+ try {
107
+ const next = Molecule.fromSmiles(smiles);
108
+ setMolecule(next);
109
+ setError(null);
110
+ } catch (value) {
111
+ setError(String(value));
112
+ }
113
+ }, [ready, smiles]);
114
+
115
+ useEffect(() => () => molecule?.free(), [molecule]);
116
+
117
+ if (error) return <pre>{error}</pre>;
118
+ if (!molecule) return <p>Loading COSMolKit...</p>;
119
+ return <output>{molecule.toSmiles()} ({molecule.numAtoms()} atoms)</output>;
120
+ }
121
+ ```
122
+
123
+ The complete copyable component is
124
+ [`examples/react/MoleculePanel.jsx`](./examples/react/MoleculePanel.jsx).
125
+
126
+ ## Vue
127
+
128
+ Vue applications should initialize in `onMounted` and replace the previous
129
+ opaque value when the input changes:
130
+
131
+ ```vue
132
+ <script setup>
133
+ import { onBeforeUnmount, onMounted, ref, watch } from "vue";
134
+ import init, { Molecule } from "@cosmol-studio/cosmolkit";
135
+
136
+ const props = defineProps({ smiles: { type: String, default: "CCO" } });
137
+ const molecule = ref(null);
138
+ const error = ref("");
139
+
140
+ async function update() {
141
+ try {
142
+ const next = Molecule.fromSmiles(props.smiles);
143
+ molecule.value?.free();
144
+ molecule.value = next;
145
+ error.value = "";
146
+ } catch (value) {
147
+ error.value = String(value);
148
+ }
149
+ }
150
+
151
+ onMounted(async () => {
152
+ try {
153
+ await init();
154
+ await update();
155
+ } catch (value) {
156
+ error.value = String(value);
157
+ }
158
+ });
159
+ watch(() => props.smiles, update);
160
+ onBeforeUnmount(() => molecule.value?.free());
161
+ </script>
162
+
163
+ <template>
164
+ <pre v-if="error">{{ error }}</pre>
165
+ <output v-else-if="molecule">{{ molecule.toSmiles() }}</output>
166
+ <p v-else>Loading COSMolKit...</p>
167
+ </template>
168
+ ```
169
+
170
+ The complete component is [`examples/vue/MoleculePanel.vue`](./examples/vue/MoleculePanel.vue).
171
+
172
+ ## Ownership And Errors
173
+
174
+ `Molecule` values own Rust allocations. Keep a value while it is in use and
175
+ call `.free()` when a long-lived UI state or worker no longer needs it. Methods
176
+ such as `withHydrogens()`, `with2dCoordinates()`, and
177
+ `with3dConformer()` return new values and leave the source value unchanged.
178
+
179
+ Fingerprint methods return `Uint32Array` set-bit lists. Coordinate methods
180
+ return flattened `Float64Array` values. Binary serialization returns a
181
+ `Uint8Array`, which can be stored or transferred through a worker.
182
+
183
+ ## Examples
184
+
185
+ The examples are intentionally small and use only the published package:
186
+
187
+ - [`examples/vanilla/basic.js`](./examples/vanilla/basic.js)
188
+ - [`examples/vanilla/cdn.html`](./examples/vanilla/cdn.html)
189
+ - [`examples/vanilla/descriptors.js`](./examples/vanilla/descriptors.js)
190
+ - [`examples/vanilla/fingerprints.js`](./examples/vanilla/fingerprints.js)
191
+ - [`examples/vanilla/binary.js`](./examples/vanilla/binary.js)
192
+ - [`examples/vanilla/substructure.js`](./examples/vanilla/substructure.js)
193
+ - [`examples/vanilla/stereo.js`](./examples/vanilla/stereo.js)
194
+ - [`examples/react/MoleculePanel.jsx`](./examples/react/MoleculePanel.jsx)
195
+ - [`examples/vue/MoleculePanel.vue`](./examples/vue/MoleculePanel.vue)
package/package.json CHANGED
@@ -1,6 +1,29 @@
1
1
  {
2
2
  "name": "@cosmol-studio/cosmolkit",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.5.0-rc.13",
4
+ "description": "WebAssembly bindings for COSMolKit",
5
+ "type": "module",
6
+ "main": "wasm_wasm.js",
7
+ "module": "wasm_wasm.js",
8
+ "types": "wasm_wasm.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./wasm_wasm.d.ts",
12
+ "default": "./wasm_wasm.js"
13
+ },
14
+ "./*": "./*"
15
+ },
16
+ "files": [
17
+ "*.js",
18
+ "*.d.ts",
19
+ "*.wasm",
20
+ "snippets",
21
+ "README.md",
22
+ "LICENSE"
23
+ ],
24
+ "license": "MIT",
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "https://github.com/cosmol-studio/COSMolKit"
28
+ }
29
+ }
@@ -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 visitScalarMorganparams(v,f){try{f(v);}catch(cause){throw new TypeError("invalid MorganParams",{cause});}} export function visitScalarMorganatom(v,f){try{f(v);}catch(cause){throw new TypeError("invalid MorganAtomInvariantsGenerator",{cause});}} export function visitScalarMorganbond(v,f){try{f(v);}catch(cause){throw new TypeError("invalid MorganBondInvariantsGenerator",{cause});}} export function visitScalarMorgancall(v,f){try{f(v);}catch(cause){throw new TypeError("invalid MorganCallParams",{cause});}} export function visitScalarMorganMolecule(v,f){try{f(v);}catch(cause){throw new TypeError("invalid Molecule",{cause});}}
@@ -0,0 +1 @@
1
+ export function visitMorganParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MorganParams',{cause});}} export function visitMorganInvariants(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MorganInvariants',{cause});}} export function visitMorganQuery(v,f){try{f(v);}catch(cause){throw new TypeError('invalid QueryGraph',{cause});}} export function visitMorganAtom(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MorganAtomInvariantsGenerator',{cause});}} export function visitMorganBond(v,f){try{f(v);}catch(cause){throw new TypeError('invalid MorganBondInvariantsGenerator',{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 visitFingerprintAdditionalOutput(value,visit){try{visit(value);}catch(cause){throw new TypeError('invalid FingerprintAdditionalOutput',{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 visitBioMoleculeParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid BioMoleculeParams',{cause});}}
@@ -0,0 +1 @@
1
+ export function visit_batch_records(records, visit) { for (const record of records) visit(record); }
@@ -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 visitDistanceMatrixParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid DistanceMatrixParams',{cause});}}
@@ -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 visitLayeredMask(value,visit){try{visit(value);}catch(cause){throw new TypeError('invalid Fingerprint',{cause});}}
@@ -0,0 +1 @@
1
+ export function attachProteinIterator(v) { Object.defineProperty(v, Symbol.iterator, {value: function() { return this; }}); return v; }
@@ -0,0 +1 @@
1
+ export function visitBioAltloc(v,f){try{f(v);}catch(cause){throw new TypeError('invalid AltLocLabel',{cause});}} export function visitBioElement(v,f){try{f(v);}catch(cause){throw new TypeError('invalid Element',{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 visitSearchCompiledQuery(v,f){try{f(v);}catch(cause){throw new TypeError('invalid CompiledQuery',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitSearchSmartsWriteParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SmartsWriteParams',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitSearchSubstructMatchParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SubstructMatchParams',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitSearchQueryGraph(v,f){try{f(v);}catch(cause){throw new TypeError('invalid QueryGraph',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitReactionQuery(v,f){try{f(v);}catch(cause){throw new TypeError('invalid QueryGraph',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitReactionMolecule(v,f){try{f(v);}catch(cause){throw new TypeError('invalid Molecule',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitTorsionParams(value,visit){try { visit(value); } catch(cause) { throw new TypeError('invalid AtomPair parameter', {cause}); }} export function visitTorsionInvariants(value,visit){try { visit(value); } catch(cause) { throw new TypeError('invalid AtomPair parameter', {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 visitSanitizeParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SanitizeParams',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitScalarTopologicalTorsionparams(v,f){try{f(v);}catch(cause){throw new TypeError("invalid TopologicalTorsionParams",{cause});}} export function visitScalarTopologicalTorsionatom(v,f){try{f(v);}catch(cause){throw new TypeError("invalid AtomPairAtomInvariantsGenerator",{cause});}} export function visitScalarTopologicalTorsioncall(v,f){try{f(v);}catch(cause){throw new TypeError("invalid TopologicalTorsionCallParams",{cause});}} export function visitScalarTopologicalTorsionMolecule(v,f){try{f(v);}catch(cause){throw new TypeError("invalid Molecule",{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 visit_execution(value, visit) { try { visit(value); } catch (cause) { throw new TypeError('invalid BatchParams', { cause }); } }
@@ -0,0 +1 @@
1
+ export function visitReactionCxSmilesFields(v,f){try{f(v);}catch(cause){throw new TypeError('invalid CxSmilesFields',{cause});}}
@@ -0,0 +1 @@
1
+ export function visitReactionCoordinateSelection(v,f){try{f(v);}catch(cause){throw new TypeError('invalid ReactionCoordinateSelection',{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 visitAtomPairParams(value,visit){try { visit(value); } catch(cause) { throw new TypeError('invalid AtomPair parameter', {cause}); }} export function visitAtomPairInvariants(value,visit){try { visit(value); } catch(cause) { throw new TypeError('invalid AtomPair parameter', {cause}); }}
@@ -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 visitKekulizeParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid KekulizeParams',{cause});}}