react-cheminfo 0.51.0 → 0.53.0

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 (137) hide show
  1. package/README.md +135 -46
  2. package/lib/host/core/connectHost.d.ts +75 -0
  3. package/lib/host/core/connectHost.d.ts.map +1 -0
  4. package/lib/host/core/connectHost.js +171 -0
  5. package/lib/host/core/connectHost.js.map +1 -0
  6. package/lib/host/core/hostStructure.d.ts +52 -0
  7. package/lib/host/core/hostStructure.d.ts.map +1 -0
  8. package/lib/host/core/hostStructure.js +106 -0
  9. package/lib/host/core/hostStructure.js.map +1 -0
  10. package/lib/host/core/index.d.ts +9 -0
  11. package/lib/host/core/index.d.ts.map +1 -0
  12. package/lib/host/core/index.js +5 -0
  13. package/lib/host/core/index.js.map +1 -0
  14. package/lib/host/core/kinds.d.ts +73 -0
  15. package/lib/host/core/kinds.d.ts.map +1 -0
  16. package/lib/host/core/kinds.js +88 -0
  17. package/lib/host/core/kinds.js.map +1 -0
  18. package/lib/host/core/protocol.d.ts +134 -0
  19. package/lib/host/core/protocol.d.ts.map +1 -0
  20. package/lib/host/core/protocol.js +92 -0
  21. package/lib/host/core/protocol.js.map +1 -0
  22. package/lib/host/testing/sciPeaks.d.ts +21 -0
  23. package/lib/host/testing/sciPeaks.d.ts.map +1 -0
  24. package/lib/host/testing/sciPeaks.js +62 -0
  25. package/lib/host/testing/sciPeaks.js.map +1 -0
  26. package/lib/host/testing/standInHost.d.ts +47 -0
  27. package/lib/host/testing/standInHost.d.ts.map +1 -0
  28. package/lib/host/testing/standInHost.js +85 -0
  29. package/lib/host/testing/standInHost.js.map +1 -0
  30. package/lib/host/ui/index.d.ts +3 -0
  31. package/lib/host/ui/index.d.ts.map +1 -0
  32. package/lib/host/ui/index.js +2 -0
  33. package/lib/host/ui/index.js.map +1 -0
  34. package/lib/host/ui/useHostConnection.d.ts +36 -0
  35. package/lib/host/ui/useHostConnection.d.ts.map +1 -0
  36. package/lib/host/ui/useHostConnection.js +62 -0
  37. package/lib/host/ui/useHostConnection.js.map +1 -0
  38. package/lib/host-testing.d.ts +8 -0
  39. package/lib/host-testing.d.ts.map +1 -0
  40. package/lib/host-testing.js +7 -0
  41. package/lib/host-testing.js.map +1 -0
  42. package/lib/host.d.ts +11 -0
  43. package/lib/host.d.ts.map +1 -0
  44. package/lib/host.js +11 -0
  45. package/lib/host.js.map +1 -0
  46. package/lib/i18n/core/chromeCatalog.d.ts +1 -1
  47. package/lib/i18n/core/chromeCatalog.d.ts.map +1 -1
  48. package/lib/language/ui/siteLanguageContext.d.ts.map +1 -1
  49. package/lib/language/ui/siteLanguageContext.js +2 -1
  50. package/lib/language/ui/siteLanguageContext.js.map +1 -1
  51. package/lib/locales/de.json +5 -0
  52. package/lib/locales/en.json +5 -0
  53. package/lib/locales/es.json +5 -0
  54. package/lib/locales/fr.json +5 -0
  55. package/lib/locales/it.json +5 -0
  56. package/lib/router/core/history.d.ts +4 -3
  57. package/lib/router/core/history.d.ts.map +1 -1
  58. package/lib/router/core/history.js +9 -13
  59. package/lib/router/core/history.js.map +1 -1
  60. package/lib/router/core/index.d.ts +2 -0
  61. package/lib/router/core/index.d.ts.map +1 -1
  62. package/lib/router/core/index.js +1 -0
  63. package/lib/router/core/index.js.map +1 -1
  64. package/lib/router/core/pageAddress.d.ts +61 -0
  65. package/lib/router/core/pageAddress.d.ts.map +1 -0
  66. package/lib/router/core/pageAddress.js +69 -0
  67. package/lib/router/core/pageAddress.js.map +1 -0
  68. package/lib/share/core/index.d.ts +4 -0
  69. package/lib/share/core/index.d.ts.map +1 -1
  70. package/lib/share/core/index.js +2 -0
  71. package/lib/share/core/index.js.map +1 -1
  72. package/lib/share/core/preferences.d.ts +2 -2
  73. package/lib/share/core/preferences.d.ts.map +1 -1
  74. package/lib/share/core/preferences.js +8 -3
  75. package/lib/share/core/preferences.js.map +1 -1
  76. package/lib/share/core/seal.d.ts +42 -0
  77. package/lib/share/core/seal.d.ts.map +1 -0
  78. package/lib/share/core/seal.js +185 -0
  79. package/lib/share/core/seal.js.map +1 -0
  80. package/lib/share/core/sealedAddress.d.ts +31 -0
  81. package/lib/share/core/sealedAddress.d.ts.map +1 -0
  82. package/lib/share/core/sealedAddress.js +38 -0
  83. package/lib/share/core/sealedAddress.js.map +1 -0
  84. package/lib/share/ui/SealedLinkRefused.d.ts +17 -0
  85. package/lib/share/ui/SealedLinkRefused.d.ts.map +1 -0
  86. package/lib/share/ui/SealedLinkRefused.js +23 -0
  87. package/lib/share/ui/SealedLinkRefused.js.map +1 -0
  88. package/lib/share/ui/ShareConfigOptions.d.ts +12 -1
  89. package/lib/share/ui/ShareConfigOptions.d.ts.map +1 -1
  90. package/lib/share/ui/ShareConfigOptions.js +4 -3
  91. package/lib/share/ui/ShareConfigOptions.js.map +1 -1
  92. package/lib/share/ui/ShareDialogContent.d.ts.map +1 -1
  93. package/lib/share/ui/ShareDialogContent.js +20 -6
  94. package/lib/share/ui/ShareDialogContent.js.map +1 -1
  95. package/lib/share/ui/ShareLinkBar.d.ts +5 -0
  96. package/lib/share/ui/ShareLinkBar.d.ts.map +1 -1
  97. package/lib/share/ui/ShareLinkBar.js +4 -4
  98. package/lib/share/ui/ShareLinkBar.js.map +1 -1
  99. package/lib/share/ui/index.d.ts +2 -0
  100. package/lib/share/ui/index.d.ts.map +1 -1
  101. package/lib/share/ui/index.js +1 -0
  102. package/lib/share/ui/index.js.map +1 -1
  103. package/lib/share/ui/useSealedUrl.d.ts +17 -0
  104. package/lib/share/ui/useSealedUrl.d.ts.map +1 -0
  105. package/lib/share/ui/useSealedUrl.js +31 -0
  106. package/lib/share/ui/useSealedUrl.js.map +1 -0
  107. package/package.json +4 -1
  108. package/src/host/core/connectHost.ts +240 -0
  109. package/src/host/core/hostStructure.ts +129 -0
  110. package/src/host/core/index.ts +46 -0
  111. package/src/host/core/kinds.ts +128 -0
  112. package/src/host/core/protocol.ts +197 -0
  113. package/src/host/testing/sciPeaks.ts +66 -0
  114. package/src/host/testing/standInHost.ts +116 -0
  115. package/src/host/ui/index.ts +2 -0
  116. package/src/host/ui/useHostConnection.ts +85 -0
  117. package/src/host-testing.ts +18 -0
  118. package/src/host.ts +11 -0
  119. package/src/language/ui/siteLanguageContext.ts +2 -1
  120. package/src/locales/de.json +5 -0
  121. package/src/locales/en.json +5 -0
  122. package/src/locales/es.json +5 -0
  123. package/src/locales/fr.json +5 -0
  124. package/src/locales/it.json +5 -0
  125. package/src/router/core/history.ts +9 -15
  126. package/src/router/core/index.ts +8 -0
  127. package/src/router/core/pageAddress.ts +110 -0
  128. package/src/share/core/index.ts +10 -0
  129. package/src/share/core/preferences.ts +10 -10
  130. package/src/share/core/seal.ts +233 -0
  131. package/src/share/core/sealedAddress.ts +48 -0
  132. package/src/share/ui/SealedLinkRefused.tsx +43 -0
  133. package/src/share/ui/ShareConfigOptions.tsx +23 -1
  134. package/src/share/ui/ShareDialogContent.tsx +37 -6
  135. package/src/share/ui/ShareLinkBar.tsx +9 -1
  136. package/src/share/ui/index.ts +2 -0
  137. package/src/share/ui/useSealedUrl.ts +40 -0
@@ -0,0 +1,106 @@
1
+ /**
2
+ * A structure a host handed over, read into the molecule a tool works on.
3
+ *
4
+ * Every tool of the family that takes a structure takes it the same way — in
5
+ * the three notations a notebook keeps, the one that says the most first — so
6
+ * the kinds, the parsing and the sentence a host reads when it fails are
7
+ * written once, here.
8
+ */
9
+ import { sourceMolecule } from "../../structure/core/sourceMolecule.js";
10
+ import { structureError } from "../../structure/core/structureError.js";
11
+ /**
12
+ * The kinds a structure input accepts, in order of preference: a molfile
13
+ * carries the layout its author drew, an idcode the exact structure, a SMILES
14
+ * only the connectivity.
15
+ */
16
+ export const STRUCTURE_KINDS = [
17
+ 'chem.molfile',
18
+ 'chem.ocl.id',
19
+ 'chem.smiles',
20
+ ];
21
+ /**
22
+ * The function a tool hands `useHostConnection` as `load` when its input is a
23
+ * structure.
24
+ *
25
+ * The structure is parsed before `show` is called, so one that cannot be read
26
+ * is answered `unreadable` with a sentence the host can show, and nothing on
27
+ * the tool's screen changes.
28
+ * @param show - Puts the molecule on screen, under the host's label for it.
29
+ * @param key - The input the structure arrives on.
30
+ * @returns The `load` function.
31
+ */
32
+ export function hostStructureLoader(show, key = 'structure') {
33
+ return (inputs) => {
34
+ for (const { key: inputKey, item, checked } of inputs) {
35
+ if (inputKey !== key || !isStructureValue(checked))
36
+ continue;
37
+ show(readHostMolecule(checked), item.label);
38
+ }
39
+ };
40
+ }
41
+ /**
42
+ * Read a structure a host sent.
43
+ *
44
+ * A molfile whose atoms all sit on one point — SciPeaks stores some that way —
45
+ * is laid out again, so a tool that draws it does not draw one dot.
46
+ * @param checked - The value, already checked against its kind.
47
+ * @returns A molecule with at least one atom.
48
+ * @throws {Error} When the notation does not parse or describes no atoms; the
49
+ * message is the sentence the host is answered with.
50
+ */
51
+ export function readHostMolecule(checked) {
52
+ const notation = NOTATIONS[checked.kind];
53
+ let molecule;
54
+ try {
55
+ molecule = sourceMolecule(hostStructureSource(checked));
56
+ }
57
+ catch (error) {
58
+ const { message } = structureError(error);
59
+ throw new Error(`The ${notation} could not be read, so nothing was loaded: ${message}`, { cause: error });
60
+ }
61
+ if (molecule.getAllAtoms() === 0) {
62
+ throw new Error(`The ${notation} describes no atoms, so nothing was loaded.`);
63
+ }
64
+ if (atomsCoincide(molecule))
65
+ molecule.inventCoordinates();
66
+ return molecule;
67
+ }
68
+ /**
69
+ * A structure a host sent, as the notation a depiction is drawn from.
70
+ * @param checked - The value, already checked against its kind.
71
+ * @returns The notation and its text; an idcode keeps its coordinates.
72
+ */
73
+ export function hostStructureSource(checked) {
74
+ if (checked.kind === 'chem.molfile') {
75
+ return { kind: 'molfile', value: checked.value.molfile };
76
+ }
77
+ if (checked.kind === 'chem.ocl.id') {
78
+ const { idCode, coordinates } = checked.value;
79
+ return coordinates === ''
80
+ ? { kind: 'idcode', value: idCode }
81
+ : { kind: 'idcode', value: idCode, coordinates };
82
+ }
83
+ return { kind: 'smiles', value: checked.value.smiles.trim() };
84
+ }
85
+ const NOTATIONS = {
86
+ 'chem.molfile': 'molfile',
87
+ 'chem.ocl.id': 'idcode',
88
+ 'chem.smiles': 'SMILES',
89
+ };
90
+ function atomsCoincide(molecule) {
91
+ const atoms = molecule.getAllAtoms();
92
+ if (atoms < 2)
93
+ return false;
94
+ const x = molecule.getAtomX(0);
95
+ const y = molecule.getAtomY(0);
96
+ for (let atom = 1; atom < atoms; atom++) {
97
+ if (molecule.getAtomX(atom) !== x || molecule.getAtomY(atom) !== y) {
98
+ return false;
99
+ }
100
+ }
101
+ return true;
102
+ }
103
+ function isStructureValue(checked) {
104
+ return Object.hasOwn(NOTATIONS, checked.kind);
105
+ }
106
+ //# sourceMappingURL=hostStructure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hostStructure.js","sourceRoot":"","sources":["../../../src/host/core/hostStructure.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,wCAAwC,CAAC;AAMxE;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,cAAc;IACd,aAAa;IACb,aAAa;CACL,CAAC;AAQX;;;;;;;;;;GAUG;AACH,MAAM,UAAU,mBAAmB,CACjC,IAA6D,EAC7D,GAAG,GAAG,WAAW;IAEjB,OAAO,CAAC,MAAM,EAAE,EAAE;QAChB,KAAK,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,MAAM,EAAE,CAAC;YACtD,IAAI,QAAQ,KAAK,GAAG,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC;gBAAE,SAAS;YAC7D,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAuB;IACtD,MAAM,QAAQ,GAAG,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IACzC,IAAI,QAAkB,CAAC;IACvB,IAAI,CAAC;QACH,QAAQ,GAAG,cAAc,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,EAAE,OAAO,EAAE,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,OAAO,QAAQ,8CAA8C,OAAO,EAAE,EACtE,EAAE,KAAK,EAAE,KAAK,EAAE,CACjB,CAAC;IACJ,CAAC;IACD,IAAI,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CACb,OAAO,QAAQ,6CAA6C,CAC7D,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,CAAC,QAAQ,CAAC;QAAE,QAAQ,CAAC,iBAAiB,EAAE,CAAC;IAC1D,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,OAAuB;IACzD,IAAI,OAAO,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;QACpC,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IAC3D,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;QACnC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;QAC9C,OAAO,WAAW,KAAK,EAAE;YACvB,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE;YACnC,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;IACrD,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,SAAS,GAA2C;IACxD,cAAc,EAAE,SAAS;IACzB,aAAa,EAAE,QAAQ;IACvB,aAAa,EAAE,QAAQ;CACxB,CAAC;AAEF,SAAS,aAAa,CAAC,QAAkB;IACvC,MAAM,KAAK,GAAG,QAAQ,CAAC,WAAW,EAAE,CAAC;IACrC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IAC5B,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC/B,MAAM,CAAC,GAAG,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC/B,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC;QACxC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACnE,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,OAAqB;IAC7C,OAAO,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type { HostConnectionOptions, HostMessageEvent, InputSelection, LoadedInput, } from './connectHost.ts';
2
+ export { connectHost, selectInputs } from './connectHost.ts';
3
+ export type { StructureValue } from './hostStructure.ts';
4
+ export { STRUCTURE_KINDS, hostStructureLoader, hostStructureSource, readHostMolecule, } from './hostStructure.ts';
5
+ export type { CheckOutcome, CheckedValue, KnownKind, MolfileValue, OclIdValue, SmilesValue, } from './kinds.ts';
6
+ export { checkValue, isKnownKind, kindAccepts } from './kinds.ts';
7
+ export type { GetRequest, HelloMessage, HostError, HostErrorCode, HostItem, HostRequest, LoadRequest, ResultMessage, ToolInput, ToolInterface, ToolOutput, UsedItem, } from './protocol.ts';
8
+ export { CONNECT_TYPE, HELLO_TYPE, MAX_ITEMS, MAX_LABEL_LENGTH, PROTOCOL_VERSION, isConnect, parseRequest, } from './protocol.ts';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/host/core/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,qBAAqB,EACrB,gBAAgB,EAChB,cAAc,EACd,WAAW,GACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAC7D,YAAY,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAClE,YAAY,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,aAAa,EACb,QAAQ,EACR,WAAW,EACX,WAAW,EACX,aAAa,EACb,SAAS,EACT,aAAa,EACb,UAAU,EACV,QAAQ,GACT,MAAM,eAAe,CAAC;AACvB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { connectHost, selectInputs } from "./connectHost.js";
2
+ export { STRUCTURE_KINDS, hostStructureLoader, hostStructureSource, readHostMolecule, } from "./hostStructure.js";
3
+ export { checkValue, isKnownKind, kindAccepts } from "./kinds.js";
4
+ export { CONNECT_TYPE, HELLO_TYPE, MAX_ITEMS, MAX_LABEL_LENGTH, PROTOCOL_VERSION, isConnect, parseRequest, } from "./protocol.js";
5
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/host/core/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7D,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,mBAAmB,EACnB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAS5B,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAelE,OAAO,EACL,YAAY,EACZ,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,gBAAgB,EAChB,SAAS,EACT,YAAY,GACb,MAAM,eAAe,CAAC"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The kinds of data a tool takes from a host, checked the way
3
+ * pipeline.cheminfo.org checks what its workers pass to each other: a dotted
4
+ * name, a JSON Schema, and ajv.
5
+ *
6
+ * The names are pipeline's (`chem.molfile.2d`, `chem.ocl.id`…), plus
7
+ * `chem.smiles`, which pipeline lists among its future schemas. A name with
8
+ * children is a category whose schema every child satisfies, so `chem.molfile`
9
+ * reads `chem.molfile.2d` and `chem.molfile.3d.h.energy` alike; the fields a
10
+ * tool does not read are stripped rather than refused, so a host sending more
11
+ * than it needs to is never turned away.
12
+ */
13
+ /** A molfile, V2000 or V3000. */
14
+ export interface MolfileValue {
15
+ molfile: string;
16
+ }
17
+ /** An OpenChemLib idcode and its 2D coordinates. */
18
+ export interface OclIdValue {
19
+ idCode: string;
20
+ coordinates: string;
21
+ }
22
+ /** A SMILES. */
23
+ export interface SmilesValue {
24
+ smiles: string;
25
+ }
26
+ /** A value that passed its kind's schema, tagged with that kind. */
27
+ export type CheckedValue = {
28
+ kind: 'chem.molfile';
29
+ value: MolfileValue;
30
+ } | {
31
+ kind: 'chem.ocl.id';
32
+ value: OclIdValue;
33
+ } | {
34
+ kind: 'chem.smiles';
35
+ value: SmilesValue;
36
+ };
37
+ /** The name of a kind a tool can read. */
38
+ export type KnownKind = CheckedValue['kind'];
39
+ /** What checking a value gave. */
40
+ export type CheckOutcome = {
41
+ valid: true;
42
+ checked: CheckedValue;
43
+ } | {
44
+ valid: false;
45
+ errors: string[];
46
+ };
47
+ /**
48
+ * Whether a kind falls under another: the same name, or a name under it on a
49
+ * segment boundary. A list (`…[]`) never stands for one value, nor one value
50
+ * for a list.
51
+ * @param accepted - The kind a tool declares, e.g. `'chem.molfile'`.
52
+ * @param offered - The kind an item carries, e.g. `'chem.molfile.2d'`.
53
+ * @returns `true` when an item of `offered` can be read as `accepted`.
54
+ */
55
+ export declare function kindAccepts(accepted: string, offered: string): boolean;
56
+ /**
57
+ * Whether there is a schema for a kind.
58
+ * @param kind - A kind name.
59
+ * @returns `true` for a {@link KnownKind}.
60
+ */
61
+ export declare function isKnownKind(kind: string): kind is KnownKind;
62
+ /**
63
+ * Check a value against a kind's schema.
64
+ *
65
+ * Fields the schema does not name are removed from `value` itself, so what the
66
+ * site reads afterwards is exactly what the kind promises.
67
+ * @param kind - The kind to read the value as.
68
+ * @param value - The value, as received.
69
+ * @returns The value tagged with its kind, or the errors as pipeline writes
70
+ * them, `'/idCode: must be string'`.
71
+ */
72
+ export declare function checkValue(kind: KnownKind, value: unknown): CheckOutcome;
73
+ //# sourceMappingURL=kinds.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.d.ts","sourceRoot":"","sources":["../../../src/host/core/kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAKH,iCAAiC;AACjC,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oDAAoD;AACpD,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,gBAAgB;AAChB,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,oEAAoE;AACpE,MAAM,MAAM,YAAY,GACpB;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,KAAK,EAAE,YAAY,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,WAAW,CAAA;CAAE,CAAC;AAEhD,0CAA0C;AAC1C,MAAM,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;AAK7C,kCAAkC;AAClC,MAAM,MAAM,YAAY,GACtB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,YAAY,CAAA;CAAE,GAAG;IAAE,KAAK,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAAC;AAE9E;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAMtE;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,IAAI,SAAS,CAE3D;AAED;;;;;;;;;GASG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,GAAG,YAAY,CAWxE"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * The kinds of data a tool takes from a host, checked the way
3
+ * pipeline.cheminfo.org checks what its workers pass to each other: a dotted
4
+ * name, a JSON Schema, and ajv.
5
+ *
6
+ * The names are pipeline's (`chem.molfile.2d`, `chem.ocl.id`…), plus
7
+ * `chem.smiles`, which pipeline lists among its future schemas. A name with
8
+ * children is a category whose schema every child satisfies, so `chem.molfile`
9
+ * reads `chem.molfile.2d` and `chem.molfile.3d.h.energy` alike; the fields a
10
+ * tool does not read are stripped rather than refused, so a host sending more
11
+ * than it needs to is never turned away.
12
+ */
13
+ import { Ajv } from 'ajv';
14
+ /**
15
+ * Whether a kind falls under another: the same name, or a name under it on a
16
+ * segment boundary. A list (`…[]`) never stands for one value, nor one value
17
+ * for a list.
18
+ * @param accepted - The kind a tool declares, e.g. `'chem.molfile'`.
19
+ * @param offered - The kind an item carries, e.g. `'chem.molfile.2d'`.
20
+ * @returns `true` when an item of `offered` can be read as `accepted`.
21
+ */
22
+ export function kindAccepts(accepted, offered) {
23
+ const list = accepted.endsWith('[]');
24
+ if (offered.endsWith('[]') !== list)
25
+ return false;
26
+ const base = list ? accepted.slice(0, -2) : accepted;
27
+ const name = list ? offered.slice(0, -2) : offered;
28
+ return name === base || name.startsWith(`${base}.`);
29
+ }
30
+ /**
31
+ * Whether there is a schema for a kind.
32
+ * @param kind - A kind name.
33
+ * @returns `true` for a {@link KnownKind}.
34
+ */
35
+ export function isKnownKind(kind) {
36
+ return Object.hasOwn(VALIDATORS, kind);
37
+ }
38
+ /**
39
+ * Check a value against a kind's schema.
40
+ *
41
+ * Fields the schema does not name are removed from `value` itself, so what the
42
+ * site reads afterwards is exactly what the kind promises.
43
+ * @param kind - The kind to read the value as.
44
+ * @param value - The value, as received.
45
+ * @returns The value tagged with its kind, or the errors as pipeline writes
46
+ * them, `'/idCode: must be string'`.
47
+ */
48
+ export function checkValue(kind, value) {
49
+ const validate = VALIDATORS[kind];
50
+ if (validate(value)) {
51
+ // The validator of `kind` just vouched for the shape of `value`.
52
+ return { valid: true, checked: { kind, value } };
53
+ }
54
+ const errors = [];
55
+ for (const error of validate.errors ?? []) {
56
+ errors.push(`${error.instancePath || '/'}: ${error.message ?? 'invalid'}`);
57
+ }
58
+ return { valid: false, errors };
59
+ }
60
+ const MOLFILE_SCHEMA = {
61
+ type: 'object',
62
+ properties: { molfile: { type: 'string' } },
63
+ required: ['molfile'],
64
+ additionalProperties: false,
65
+ };
66
+ const OCL_ID_SCHEMA = {
67
+ type: 'object',
68
+ properties: {
69
+ idCode: { type: 'string' },
70
+ coordinates: { type: 'string' },
71
+ },
72
+ required: ['idCode', 'coordinates'],
73
+ additionalProperties: false,
74
+ };
75
+ const SMILES_SCHEMA = {
76
+ type: 'object',
77
+ properties: { smiles: { type: 'string' } },
78
+ required: ['smiles'],
79
+ additionalProperties: false,
80
+ };
81
+ // `removeAdditional` strips what `additionalProperties: false` would refuse.
82
+ const ajv = new Ajv({ removeAdditional: true });
83
+ const VALIDATORS = {
84
+ 'chem.molfile': ajv.compile(MOLFILE_SCHEMA),
85
+ 'chem.ocl.id': ajv.compile(OCL_ID_SCHEMA),
86
+ 'chem.smiles': ajv.compile(SMILES_SCHEMA),
87
+ };
88
+ //# sourceMappingURL=kinds.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kinds.js","sourceRoot":"","sources":["../../../src/host/core/kinds.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAGH,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAkC1B;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,QAAgB,EAAE,OAAe;IAC3D,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;IACnD,OAAO,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,UAAU,CAAC,IAAe,EAAE,KAAc;IACxD,MAAM,QAAQ,GAAqB,UAAU,CAAC,IAAI,CAAC,CAAC;IACpD,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACpB,iEAAiE;QACjE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,KAAK,EAAkB,EAAE,CAAC;IACnE,CAAC;IACD,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,KAAK,MAAM,KAAK,IAAI,QAAQ,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC1C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,YAAY,IAAI,GAAG,KAAK,KAAK,CAAC,OAAO,IAAI,SAAS,EAAE,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,cAAc,GAAiC;IACnD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAC3C,QAAQ,EAAE,CAAC,SAAS,CAAC;IACrB,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,aAAa,GAA+B;IAChD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE;QACV,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAC1B,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KAChC;IACD,QAAQ,EAAE,CAAC,QAAQ,EAAE,aAAa,CAAC;IACnC,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,MAAM,aAAa,GAAgC;IACjD,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;IAC1C,QAAQ,EAAE,CAAC,QAAQ,CAAC;IACpB,oBAAoB,EAAE,KAAK;CAC5B,CAAC;AAEF,6EAA6E;AAC7E,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,EAAE,gBAAgB,EAAE,IAAI,EAAE,CAAC,CAAC;AAEhD,MAAM,UAAU,GAAuD;IACrE,cAAc,EAAE,GAAG,CAAC,OAAO,CAAC,cAAc,CAAC;IAC3C,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;IACzC,aAAa,EAAE,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;CAC1C,CAAC"}
@@ -0,0 +1,134 @@
1
+ /**
2
+ * The cheminfo host protocol, version 1: what a page that frames a tool — an
3
+ * electronic lab notebook, a course — and the tool say to each other.
4
+ *
5
+ * Two messages travel between the windows — `hello`, from the tool, and
6
+ * `connect`, the host's answer carrying a private `MessagePort` — and everything
7
+ * else goes through that port: the host's requests (`load`, `get`) and the
8
+ * tool's `result` for each. This module only spells the messages, and reads
9
+ * what arrives as the untrusted input it is.
10
+ */
11
+ /** The version a tool speaks; a `connect` naming another is ignored. */
12
+ export declare const PROTOCOL_VERSION = 1;
13
+ /** Posted to the parent frame or the opener at start-up: who the tool is. */
14
+ export declare const HELLO_TYPE = "cheminfo:hello";
15
+ /** The host's answer to `hello`, carrying the port the rest goes through. */
16
+ export declare const CONNECT_TYPE = "cheminfo:connect";
17
+ /** How many items one request may carry; the rest are dropped. */
18
+ export declare const MAX_ITEMS = 64;
19
+ /** How long a label may be, in characters; a longer one is cut. */
20
+ export declare const MAX_LABEL_LENGTH = 80;
21
+ /** One typed value crossing the frame boundary. */
22
+ export interface HostItem {
23
+ /** A kind name, e.g. `'chem.molfile.2d'`. */
24
+ kind: string;
25
+ /** Checked against the kind before anything reads it. */
26
+ value: unknown;
27
+ /**
28
+ * The host's name for it, opaque here, e.g. an attachment.
29
+ * @default undefined
30
+ */
31
+ id?: string;
32
+ /**
33
+ * The tool input it is meant for.
34
+ * @default undefined — any input that accepts its kind
35
+ */
36
+ key?: string;
37
+ /**
38
+ * What a notice calls it, e.g. `'Ethylbenzene'`.
39
+ * @default undefined
40
+ */
41
+ label?: string;
42
+ }
43
+ /** One value the tool takes. */
44
+ export interface ToolInput {
45
+ key: string;
46
+ /** Kinds in order of preference; a category accepts every kind under it. */
47
+ kinds: readonly string[];
48
+ }
49
+ /** One value the tool can hand back. */
50
+ export interface ToolOutput {
51
+ key: string;
52
+ kind: string;
53
+ }
54
+ /** What the tool is and takes, as `hello` announces it. */
55
+ export interface ToolInterface {
56
+ name: string;
57
+ inputs: readonly ToolInput[];
58
+ outputs: readonly ToolOutput[];
59
+ }
60
+ /** What `hello` carries: public, readable by any origin. */
61
+ export interface HelloMessage {
62
+ type: typeof HELLO_TYPE;
63
+ version: typeof PROTOCOL_VERSION;
64
+ tool: ToolInterface & {
65
+ /** The tool's origin, e.g. `'https://3d.cheminfo.org'`. */
66
+ origin: string;
67
+ /** The build that is running, as the About states it, or `null`. */
68
+ build: unknown;
69
+ };
70
+ }
71
+ /** `load`: the host's data, for one document. */
72
+ export interface LoadRequest {
73
+ type: 'load';
74
+ id: string;
75
+ /** What the data belongs to; the same document twice is applied once. */
76
+ document: string;
77
+ items: HostItem[];
78
+ }
79
+ /** `get`: the current value of some outputs. */
80
+ export interface GetRequest {
81
+ type: 'get';
82
+ id: string;
83
+ keys: string[];
84
+ }
85
+ /** A request the host sends through the port. */
86
+ export type HostRequest = LoadRequest | GetRequest;
87
+ /** Why a request could not be served. */
88
+ export type HostErrorCode = 'invalid' | 'unreadable' | 'no-input' | 'no-output';
89
+ /** What a failed request is answered with. */
90
+ export interface HostError {
91
+ code: HostErrorCode;
92
+ /** One sentence, in English. */
93
+ message: string;
94
+ /**
95
+ * What the schema found, as `'chem.ocl.id /idCode: must be string'`.
96
+ * @default undefined
97
+ */
98
+ errors?: string[];
99
+ }
100
+ /** Which item an input took. */
101
+ export interface UsedItem {
102
+ key: string;
103
+ kind: string;
104
+ }
105
+ /** The answer to one request, carrying its `id`. */
106
+ export type ResultMessage = {
107
+ type: 'result';
108
+ id: string;
109
+ ok: true;
110
+ used: UsedItem[];
111
+ } | {
112
+ type: 'result';
113
+ id: string;
114
+ ok: false;
115
+ error: HostError;
116
+ };
117
+ /**
118
+ * Read a message that arrived through the port.
119
+ *
120
+ * Anything that is not a well-formed `load` or `get` is `null`, and goes
121
+ * unanswered: an unknown request is a newer host talking, not an error. An item
122
+ * without a string `kind` is dropped, and a label is cut to
123
+ * {@link MAX_LABEL_LENGTH}.
124
+ * @param data - What the port delivered.
125
+ * @returns The request, or `null`.
126
+ */
127
+ export declare function parseRequest(data: unknown): HostRequest | null;
128
+ /**
129
+ * Whether a window message is the host's answer to `hello`, in this version.
130
+ * @param data - What the window delivered.
131
+ * @returns `true` for a `connect` of {@link PROTOCOL_VERSION}.
132
+ */
133
+ export declare function isConnect(data: unknown): boolean;
134
+ //# sourceMappingURL=protocol.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../../src/host/core/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,92 @@
1
+ /**
2
+ * The cheminfo host protocol, version 1: what a page that frames a tool — an
3
+ * electronic lab notebook, a course — and the tool say to each other.
4
+ *
5
+ * Two messages travel between the windows — `hello`, from the tool, and
6
+ * `connect`, the host's answer carrying a private `MessagePort` — and everything
7
+ * else goes through that port: the host's requests (`load`, `get`) and the
8
+ * tool's `result` for each. This module only spells the messages, and reads
9
+ * what arrives as the untrusted input it is.
10
+ */
11
+ /** The version a tool speaks; a `connect` naming another is ignored. */
12
+ export const PROTOCOL_VERSION = 1;
13
+ /** Posted to the parent frame or the opener at start-up: who the tool is. */
14
+ export const HELLO_TYPE = 'cheminfo:hello';
15
+ /** The host's answer to `hello`, carrying the port the rest goes through. */
16
+ export const CONNECT_TYPE = 'cheminfo:connect';
17
+ /** How many items one request may carry; the rest are dropped. */
18
+ export const MAX_ITEMS = 64;
19
+ /** How long a label may be, in characters; a longer one is cut. */
20
+ export const MAX_LABEL_LENGTH = 80;
21
+ /**
22
+ * Read a message that arrived through the port.
23
+ *
24
+ * Anything that is not a well-formed `load` or `get` is `null`, and goes
25
+ * unanswered: an unknown request is a newer host talking, not an error. An item
26
+ * without a string `kind` is dropped, and a label is cut to
27
+ * {@link MAX_LABEL_LENGTH}.
28
+ * @param data - What the port delivered.
29
+ * @returns The request, or `null`.
30
+ */
31
+ export function parseRequest(data) {
32
+ if (!isRecord(data) || typeof data.id !== 'string')
33
+ return null;
34
+ if (data.type === 'load') {
35
+ if (typeof data.document !== 'string' || !Array.isArray(data.items)) {
36
+ return null;
37
+ }
38
+ return {
39
+ type: 'load',
40
+ id: data.id,
41
+ document: data.document,
42
+ items: readItems(data.items),
43
+ };
44
+ }
45
+ if (data.type === 'get') {
46
+ return { type: 'get', id: data.id, keys: readStrings(data.keys) };
47
+ }
48
+ return null;
49
+ }
50
+ /**
51
+ * Whether a window message is the host's answer to `hello`, in this version.
52
+ * @param data - What the window delivered.
53
+ * @returns `true` for a `connect` of {@link PROTOCOL_VERSION}.
54
+ */
55
+ export function isConnect(data) {
56
+ return (isRecord(data) &&
57
+ data.type === CONNECT_TYPE &&
58
+ data.version === PROTOCOL_VERSION);
59
+ }
60
+ function readItems(values) {
61
+ const items = [];
62
+ const count = Math.min(values.length, MAX_ITEMS);
63
+ for (let index = 0; index < count; index++) {
64
+ const value = values[index];
65
+ if (!isRecord(value) || typeof value.kind !== 'string')
66
+ continue;
67
+ const item = { kind: value.kind, value: value.value };
68
+ if (typeof value.id === 'string')
69
+ item.id = value.id;
70
+ if (typeof value.key === 'string')
71
+ item.key = value.key;
72
+ if (typeof value.label === 'string') {
73
+ item.label = value.label.slice(0, MAX_LABEL_LENGTH);
74
+ }
75
+ items.push(item);
76
+ }
77
+ return items;
78
+ }
79
+ function readStrings(value) {
80
+ if (!Array.isArray(value))
81
+ return [];
82
+ const strings = [];
83
+ for (const entry of value) {
84
+ if (typeof entry === 'string')
85
+ strings.push(entry);
86
+ }
87
+ return strings;
88
+ }
89
+ function isRecord(value) {
90
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
91
+ }
92
+ //# sourceMappingURL=protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../../src/host/core/protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * What SciPeaks sends a tool, byte for byte: the `load` its tool tab —
3
+ * visualizer-helper's `eln/toolTab` — writes for the ethylbenzene sample its own
4
+ * tests read (`eln/__tests__/data/sample.json`). Both repositories pin this
5
+ * message, so a change on either side that the other does not expect fails a
6
+ * test rather than a notebook.
7
+ *
8
+ * The sample is a real one, and so are its quirks: its molfile is V2000 with
9
+ * every atom at the origin, its title is blank so the label is its first name,
10
+ * and its formula travels as a kind no structure input reads.
11
+ */
12
+ import type { LoadRequest } from '../core/protocol.ts';
13
+ /** How SciPeaks' tool tab introduces itself in `connect`. */
14
+ export declare const SCIPEAKS_HOST_NAME = "SciPeaks";
15
+ /** The molfile SciPeaks stores for ethylbenzene: every atom at the origin. */
16
+ export declare const SCIPEAKS_ETHYLBENZENE_MOLFILE: string;
17
+ /** The first `load` the tool tab sends for that sample, with `accept`. */
18
+ export declare const SCIPEAKS_ETHYLBENZENE_LOAD: LoadRequest & {
19
+ accept: string[];
20
+ };
21
+ //# sourceMappingURL=sciPeaks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sciPeaks.d.ts","sourceRoot":"","sources":["../../../src/host/testing/sciPeaks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAEvD,6DAA6D;AAC7D,eAAO,MAAM,kBAAkB,aAAa,CAAC;AAE7C,8EAA8E;AAC9E,eAAO,MAAM,6BAA6B,QAuB9B,CAAC;AAEb,0EAA0E;AAC1E,eAAO,MAAM,0BAA0B,EAAE,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,EAAE,CAAA;CAqBxE,CAAC"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * What SciPeaks sends a tool, byte for byte: the `load` its tool tab —
3
+ * visualizer-helper's `eln/toolTab` — writes for the ethylbenzene sample its own
4
+ * tests read (`eln/__tests__/data/sample.json`). Both repositories pin this
5
+ * message, so a change on either side that the other does not expect fails a
6
+ * test rather than a notebook.
7
+ *
8
+ * The sample is a real one, and so are its quirks: its molfile is V2000 with
9
+ * every atom at the origin, its title is blank so the label is its first name,
10
+ * and its formula travels as a kind no structure input reads.
11
+ */
12
+ /** How SciPeaks' tool tab introduces itself in `connect`. */
13
+ export const SCIPEAKS_HOST_NAME = 'SciPeaks';
14
+ /** The molfile SciPeaks stores for ethylbenzene: every atom at the origin. */
15
+ export const SCIPEAKS_ETHYLBENZENE_MOLFILE = [
16
+ '',
17
+ 'Actelion Java MolfileCreator 1.0',
18
+ '',
19
+ ' 8 8 0 0 0 0 0 0 0 0999 V2000',
20
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
21
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
22
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
23
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
24
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
25
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
26
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
27
+ ' 0.0000 0.0000 0.0000 C 0 0 0 0 0 0 0 0 0 0 0 0',
28
+ ' 1 2 1 0 0 0 0',
29
+ ' 1 3 1 0 0 0 0',
30
+ ' 2 4 2 0 0 0 0',
31
+ ' 2 5 1 0 0 0 0',
32
+ ' 4 6 1 0 0 0 0',
33
+ ' 5 7 2 0 0 0 0',
34
+ ' 6 8 2 0 0 0 0',
35
+ ' 7 8 1 0 0 0 0',
36
+ 'M END',
37
+ '',
38
+ ].join('\n');
39
+ /** The first `load` the tool tab sends for that sample, with `accept`. */
40
+ export const SCIPEAKS_ETHYLBENZENE_LOAD = {
41
+ type: 'load',
42
+ id: 'load-1',
43
+ document: 'eln:1315a6d895f431497538cb6d834feab5',
44
+ items: [
45
+ {
46
+ kind: 'chem.molfile.2d',
47
+ value: { molfile: SCIPEAKS_ETHYLBENZENE_MOLFILE },
48
+ label: 'Ethylbenzene',
49
+ },
50
+ {
51
+ kind: 'chem.ocl.id',
52
+ value: {
53
+ idCode: 'daD@@DjUZxHH@@',
54
+ coordinates: String.raw `!BbOvw?_x@?g?~_{\Bm?t`,
55
+ },
56
+ label: 'Ethylbenzene',
57
+ },
58
+ { kind: 'chem.mf', value: { mf: 'C8H10' } },
59
+ ],
60
+ accept: [],
61
+ };
62
+ //# sourceMappingURL=sciPeaks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sciPeaks.js","sourceRoot":"","sources":["../../../src/host/testing/sciPeaks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,6DAA6D;AAC7D,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,CAAC;AAE7C,8EAA8E;AAC9E,MAAM,CAAC,MAAM,6BAA6B,GAAG;IAC3C,EAAE;IACF,kCAAkC;IAClC,EAAE;IACF,yCAAyC;IACzC,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,uEAAuE;IACvE,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,uBAAuB;IACvB,QAAQ;IACR,EAAE;CACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,0EAA0E;AAC1E,MAAM,CAAC,MAAM,0BAA0B,GAAuC;IAC5E,IAAI,EAAE,MAAM;IACZ,EAAE,EAAE,QAAQ;IACZ,QAAQ,EAAE,sCAAsC;IAChD,KAAK,EAAE;QACL;YACE,IAAI,EAAE,iBAAiB;YACvB,KAAK,EAAE,EAAE,OAAO,EAAE,6BAA6B,EAAE;YACjD,KAAK,EAAE,cAAc;SACtB;QACD;YACE,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE;gBACL,MAAM,EAAE,gBAAgB;gBACxB,WAAW,EAAE,MAAM,CAAC,GAAG,CAAA,uBAAuB;aAC/C;YACD,KAAK,EAAE,cAAc;SACtB;QACD,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE;KAC5C;IACD,MAAM,EAAE,EAAE;CACX,CAAC"}