@synapticon/motion-master-client 6.0.0-alpha.59 → 6.0.0-alpha.61

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.
@@ -137,6 +137,11 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
137
137
  * @example "local.motion-master.synapticon.com"
138
138
  */
139
139
  subject: string;
140
+ /**
141
+ * The certificate's subjectAltName DNS entries — the hostnames it is valid for, and what a browser actually checks (the CN is legacy and ignored). The bundled certificate covers both the loopback name and the `*.ip.…` wildcard used by off-loopback deployments, so one file serves either. Empty for a certificate with no SAN extension.
142
+ * @example ["local.motion-master.synapticon.com","*.ip.motion-master.synapticon.com"]
143
+ */
144
+ dnsNames?: string[];
140
145
  /**
141
146
  * Issuer common name (CN).
142
147
  * @example "R10"
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ export * from './generated/Api.js';
4
4
  export * from './constants.js';
5
5
  export * from './web-socket-connection.js';
6
6
  export * from './client.js';
7
+ export * from './lan.js';
7
8
  export * from './hex.js';
8
9
  export * from './sdo.js';
9
10
  export * from './somanet.js';
package/dist/index.js CHANGED
@@ -9,7 +9,9 @@ export * from './constants.js';
9
9
  export * from './web-socket-connection.js';
10
10
  export * from './client.js';
11
11
  // Pure, framework-agnostic helpers (no DOM/React): hex formatting, CoE SDO value
12
- // encode/decode, and SOMANET file-list parsing.
12
+ // encode/decode, SOMANET file-list parsing, and the LAN hostname mapping that lets a browser
13
+ // reach a server on another machine under a name the bundled certificate covers.
14
+ export * from './lan.js';
13
15
  export * from './hex.js';
14
16
  export * from './sdo.js';
15
17
  export * from './somanet.js';
package/dist/lan.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ export declare const LAN_DOMAIN = "ip.motion-master.synapticon.com";
2
+ export declare function isIpv4(value: string): boolean;
3
+ export declare function lanHostname(host: string): string;
4
+ export declare function lanAddress(host: string): string | null;
package/dist/lan.js ADDED
@@ -0,0 +1,59 @@
1
+ // Reaching a Motion Master that runs on another machine (an appliance on the workshop LAN, say)
2
+ // over TLS, from a page served at https://motion-master.synapticon.com.
3
+ //
4
+ // The obvious address — https://192.168.1.50:61447 — cannot work: no public CA will issue a
5
+ // certificate for a private IP, and a cross-origin fetch() offers no click-through for a
6
+ // self-signed one. The way out is a real, publicly-trusted name pointing at the private address.
7
+ // Names under `ip.motion-master.synapticon.com` write the address into their leftmost label, and
8
+ // the certificate every server ships carries the `*.ip.motion-master.synapticon.com` wildcard, so
9
+ // any such name validates with nothing to install.
10
+ //
11
+ // These names are resolved on the client machine by a hosts-file entry, not by public DNS — which
12
+ // is sufficient, because TLS checks a certificate against the name and never against how the name
13
+ // was resolved.
14
+ //
15
+ // The mapping is *offered* to the user, never applied behind their back: connecting straight to the
16
+ // IP address is a legitimate second path. It works once that origin has been opened in a tab and its
17
+ // certificate warning accepted, and it is the only path when the Console is being viewed from a
18
+ // phone or tablet — those cannot edit a hosts file, and it is the *browser's* machine that needs
19
+ // the entry, not the one running Motion Master. So these helpers convert on request; the caller
20
+ // decides.
21
+ // The subdomain whose leftmost label encodes an IPv4 address.
22
+ export const LAN_DOMAIN = 'ip.motion-master.synapticon.com';
23
+ // True when `value` is a dotted-quad IPv4 literal (each octet 0-255). Hostnames, IPv6 literals,
24
+ // and anything with a port or scheme attached are not.
25
+ export function isIpv4(value) {
26
+ const octets = value.trim().split('.');
27
+ if (octets.length !== 4) {
28
+ return false;
29
+ }
30
+ return octets.every((octet) => /^\d{1,3}$/.test(octet) && Number(octet) <= 255);
31
+ }
32
+ // Map a host to the name the bundled certificate covers: an IPv4 literal becomes its dashed form
33
+ // under LAN_DOMAIN (192.168.1.50 -> 192-168-1-50.ip.motion-master.synapticon.com); anything else
34
+ // is already a hostname and is returned trimmed but otherwise untouched — so a user who types
35
+ // `local.motion-master.synapticon.com`, or the dashed name itself, is left alone.
36
+ //
37
+ // Loopback is not special-cased: 127.0.0.1 maps to 127-0-0-1.ip.… which the same certificate
38
+ // covers. For a same-machine server the shorter `local.motion-master.synapticon.com` is still the
39
+ // better answer, since it is a public A record and so needs no hosts entry at all.
40
+ export function lanHostname(host) {
41
+ const trimmed = host.trim();
42
+ if (!isIpv4(trimmed)) {
43
+ return trimmed;
44
+ }
45
+ return `${trimmed.split('.').join('-')}.${LAN_DOMAIN}`;
46
+ }
47
+ // The inverse of lanHostname: recovers the address a LAN hostname encodes, or null if the host is
48
+ // not one of ours. Used to build the hosts-file line the user needs, since these names resolve
49
+ // nowhere until they add it.
50
+ export function lanAddress(host) {
51
+ const trimmed = host.trim().toLowerCase();
52
+ const suffix = `.${LAN_DOMAIN}`;
53
+ if (!trimmed.endsWith(suffix)) {
54
+ return null;
55
+ }
56
+ const label = trimmed.slice(0, -suffix.length);
57
+ const address = label.split('-').join('.');
58
+ return isIpv4(address) ? address : null;
59
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synapticon/motion-master-client",
3
- "version": "6.0.0-alpha.59",
3
+ "version": "6.0.0-alpha.61",
4
4
  "description": "Isomorphic TypeScript client for Motion Master: the generated HTTP API client, the WebSocket connection, and helpers.",
5
5
  "license": "MIT",
6
6
  "repository": {