@cosmol-studio/cosmolkit-core-analysis 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.
Files changed (33) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +239 -2
  3. package/package.json +33 -4
  4. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline0.js +1 -0
  5. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline1.js +1 -0
  6. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline10.js +1 -0
  7. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline11.js +1 -0
  8. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline12.js +1 -0
  9. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline13.js +1 -0
  10. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline14.js +1 -0
  11. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline15.js +1 -0
  12. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline16.js +1 -0
  13. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline17.js +1 -0
  14. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline18.js +1 -0
  15. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline19.js +1 -0
  16. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline2.js +1 -0
  17. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline20.js +1 -0
  18. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline21.js +1 -0
  19. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline22.js +1 -0
  20. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline23.js +1 -0
  21. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline24.js +1 -0
  22. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline25.js +1 -0
  23. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline3.js +1 -0
  24. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline4.js +1 -0
  25. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline5.js +1 -0
  26. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline6.js +1 -0
  27. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline7.js +1 -0
  28. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline8.js +1 -0
  29. package/snippets/wasm-wasm-caf920d9aee5a9bb/inline9.js +1 -0
  30. package/wasm_wasm.d.ts +3588 -0
  31. package/wasm_wasm.js +17377 -0
  32. package/wasm_wasm_bg.wasm +0 -0
  33. package/wasm_wasm_bg.wasm.d.ts +1397 -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
- # 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 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-analysis",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.5.0-rc.19",
4
+ "cosmolkitPreset": "core-analysis",
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 visitFingerprintAdditionalOutput(value,visit){try{visit(value);}catch(cause){throw new TypeError('invalid FingerprintAdditionalOutput',{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 visitLayeredParams(value,visit){visit(value);}
@@ -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 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 visitRingSearchParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid RingSearchParams',{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 visitSearchSmartsWriteParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid SmartsWriteParams',{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 visitSearchCompiledQuery(v,f){try{f(v);}catch(cause){throw new TypeError('invalid CompiledQuery',{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 visitKekulizeParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid KekulizeParams',{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 visitDistanceMatrixParams(v,f){try{f(v);}catch(cause){throw new TypeError('invalid DistanceMatrixParams',{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 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 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 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 visit_sanitize_operations(value, visit) { try { visit(value); } catch (cause) { throw new TypeError('invalid SanitizeOperations', { cause }); } }