ocp-viewer-core 1.0.0 → 1.0.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ocp-viewer-core",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Shared viewer policy for ocp_vscode, ocp_viewer, Jupyter CadQuery and build123d Studio",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
package/src/index.js CHANGED
@@ -63,3 +63,6 @@ export { createNotifier, EVENT_KEYS } from "./notify.js";
63
63
  // The splash. Data rather than policy, and here for the same reason the policy
64
64
  // is: every client shows it, and four of them had their own copy.
65
65
  export { logo } from "./logo.js";
66
+
67
+ // The JavaScript half's version, for the major.minor handshake with Python.
68
+ export { VERSION } from "./version.js";
package/src/page.js CHANGED
@@ -36,9 +36,40 @@ import { createNotifier } from "./notify.js";
36
36
  import { buildDisplayOptions, preset } from "./options.js";
37
37
  import { createRenderer } from "./render.js";
38
38
  import { currentStates, restoreStates } from "./states.js";
39
+ import { VERSION } from "./version.js";
39
40
 
40
41
  const MIN_WIDTH = 450;
41
42
 
43
+ // The version handshake: the Python half sends `_core_version` in every
44
+ // model's config, and major.minor is the contract - the patch level is each
45
+ // half's own. Warned once per page, loudly, because a contract mismatch shows
46
+ // up as the vaguest of symptoms otherwise: an option that does nothing, a key
47
+ // nobody answers.
48
+ let versionWarned = false;
49
+
50
+ function consumeCoreVersion(config, send) {
51
+ if (config == null || config._core_version === undefined) {
52
+ return;
53
+ }
54
+ const python = String(config._core_version);
55
+ delete config._core_version;
56
+ if (versionWarned) {
57
+ return;
58
+ }
59
+ const [pyMajor, pyMinor] = python.split(".");
60
+ const [jsMajor, jsMinor] = VERSION.split(".");
61
+ if (pyMajor !== jsMajor || pyMinor !== jsMinor) {
62
+ versionWarned = true;
63
+ const msg =
64
+ `ocp-viewer-core version mismatch: Python ${python}, JavaScript ${VERSION} - ` +
65
+ "major.minor must match; update the older side";
66
+ console.error(msg);
67
+ if (send != null) {
68
+ send("log", msg);
69
+ }
70
+ }
71
+ }
72
+
42
73
  /**
43
74
  * Build the page.
44
75
  *
@@ -302,7 +333,11 @@ export function createPage({
302
333
  * function rather than a listener body.
303
334
  */
304
335
  function resize() {
305
- if (viewer != null) {
336
+ // `ready` and not only null: clear() returns the viewer to its
337
+ // never-rendered state, where resizeCadView throws - a splitter drag
338
+ // over an emptied pane must not be an error. The next show measures
339
+ // the surface for itself, so a skipped resize here loses nothing.
340
+ if (viewer != null && viewer.ready === true) {
306
341
  const displayOptions = getDisplayOptions(_config.theme);
307
342
  viewer.resizeCadView(
308
343
  displayOptions.cadWidth,
@@ -319,6 +354,11 @@ export function createPage({
319
354
  function handleMessage(message) {
320
355
  var data = message;
321
356
 
357
+ // Before anything reads the config: take the Python half's version
358
+ // out of it and check the contract, so `_core_version` never reaches
359
+ // applyConfig as an unknown key.
360
+ consumeCoreVersion(data?.config, send);
361
+
322
362
  if (data.type === "logo") {
323
363
  // The splash lives in the core, so a host asks for it by name and
324
364
  // sends only what it alone knows: its theme, its tree width and
@@ -399,6 +439,14 @@ export function createPage({
399
439
  // ever needs to re-render what it already has, that is `showViewer(
400
440
  // _meshData, _config)` guarded on `_meshData` being present.
401
441
  } else if (data.type === "ui") {
442
+ // Nothing on screen is a normal state now that show_clear exists,
443
+ // and most setters read the rendered scene and throw without one.
444
+ // Said rather than silent: in this ecosystem a dropped config is
445
+ // the hardest thing to debug.
446
+ if (viewer == null || viewer.ready !== true) {
447
+ debugLog("ui: no model on screen, config not applied");
448
+ return;
449
+ }
402
450
  if (_config["_splash"]) {
403
451
  return;
404
452
  }
package/src/version.js ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The JavaScript half's own version.
3
+ *
4
+ * The Python half sends its version with every model, and page.js compares
5
+ * the two here: major.minor is the contract and must match, the patch level
6
+ * is each half's own. Kept in step with js/package.json by `make bump-js` -
7
+ * a source constant because the packages ship as plain modules, so there is
8
+ * no build step that could inject it.
9
+ */
10
+
11
+ /*
12
+ Copyright 2026 Bernhard Walter
13
+
14
+ Licensed under the Apache License, Version 2.0 (the "License");
15
+ you may not use this file except in compliance with the License.
16
+ You may obtain a copy of the License at
17
+
18
+ http://www.apache.org/licenses/LICENSE-2.0
19
+
20
+ Unless required by applicable law or agreed to in writing, software
21
+ distributed under the License is distributed on an "AS IS" BASIS,
22
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23
+ See the License for the specific language governing permissions and
24
+ limitations under the License.
25
+ */
26
+
27
+ export const VERSION = "1.0.2";