@simantic/cloud-sim 0.2.0 → 0.3.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Simantic, Inc.
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
@@ -9,7 +9,7 @@ after.
9
9
  The package is ESM with no dependencies, built on `fetch`, so it runs on
10
10
  Node 18 and later, in browsers, and on Deno, Bun and edge runtimes. Its
11
11
  wire types are generated from the server's OpenAPI document
12
- (`openapi/v1.json` in the cloud-sim repo), so they change only when the
12
+ (https://cloud.simantic.com/v1/openapi.json), so they change only when the
13
13
  contract does.
14
14
 
15
15
  ## Install
@@ -18,10 +18,8 @@ contract does.
18
18
  npm install @simantic/cloud-sim
19
19
  ```
20
20
 
21
- The package is private to the `simantic` npm organization for now: installing
22
- it needs an npm token of an org member (`npm login`, or `NPM_TOKEN` on CI and
23
- Vercel, which writes the `.npmrc` itself). The API it calls is open to any
24
- simantic account; its contract is at https://cloud.simantic.com/v1/openapi.json.
21
+ The API it calls is open to any simantic account; its contract is at
22
+ https://cloud.simantic.com/v1/openapi.json.
25
23
 
26
24
  ## Quick start
27
25
 
@@ -71,6 +69,7 @@ const run = await sim.runs.create({ mcu: 'STM32F072RB', firmware: input.files![0
71
69
  new CloudSim({
72
70
  apiKey, // an smtc_ API key or a dashboard session token, or a function giving one
73
71
  version, // Cloud-Sim-Version, such as '1.0'; the server's newest stable without it
72
+ client, // your app or tool, such as 'my-tool/1.2', named on the runs it makes
74
73
  baseUrl, // default https://cloud.simantic.com
75
74
  fetch, // default the global fetch
76
75
  onUnauthorized, // called once on a 401, before the request is sent again
@@ -85,6 +84,14 @@ release, so results do not change under you when the server's default
85
84
  moves on. A call that makes runs or reads a catalog can name another
86
85
  version for itself (`version`), so one client can serve a version picker.
87
86
 
87
+ Every run the client makes names it in `Cloud-Sim-Client`, and keeps
88
+ that as its `client`: `cloud-sim-ts/<version>` (the SDK's version, also
89
+ exported as `SDK_VERSION`), after `client` when it is given, so a run made
90
+ by `my-tool` reads `my-tool/1.2 cloud-sim-ts/0.3.1`. `client` is
91
+ `product/version` tokens separated by single spaces, in printable ASCII;
92
+ the constructor throws a `TypeError` for anything else. Only creates
93
+ carry the header.
94
+
88
95
  Every call takes an optional `signal`. Aborting it ends the call, its
89
96
  retries and the waits between them, and the call throws the signal's
90
97
  reason.
@@ -318,4 +325,5 @@ answers with is checked against the schemas in `openapi/v1.json`.
318
325
 
319
326
  ## License
320
327
 
321
- Proprietary (`UNLICENSED`), as the API itself is.
328
+ MIT, in `LICENSE`. The license is for this package; the Cloud Sim API
329
+ it calls is a Simantic service, used with a Simantic API key.
package/dist/client.d.ts CHANGED
@@ -15,6 +15,14 @@ export interface CloudSimOptions {
15
15
  * stable version, which can change under a long-lived client.
16
16
  */
17
17
  version?: string;
18
+ /**
19
+ * The app or tool built on the SDK, as `product/version` (several
20
+ * separated by spaces), such as `my-tool/1.2`. A run it makes keeps it,
21
+ * followed by the SDK's own `cloud-sim-ts/<version>`, as its `client`
22
+ * (`Cloud-Sim-Client`); without it, the run names the SDK alone. Printable
23
+ * ASCII; the constructor throws a TypeError for anything else.
24
+ */
25
+ client?: string;
18
26
  /** Default `https://cloud.simantic.com`. */
19
27
  baseUrl?: string;
20
28
  /** Default the global fetch. */
@@ -545,6 +545,14 @@ export interface components {
545
545
  * @description When its owner asked to cancel it, while it is being stopped.
546
546
  */
547
547
  cancel_requested_at: string | null;
548
+ /**
549
+ * @description The client it was made with, as the `Cloud-Sim-Client` header of the
550
+ * request that made it named it: `cloud-sim-cli/0.1.0`, say, or
551
+ * `cloud-sim-mcp/0.2.1 cloud-sim-ts/0.2.1` for one client built on
552
+ * another. Null when that request named none, and for a run submitted
553
+ * through the legacy /jobs API.
554
+ */
555
+ client: string | null;
548
556
  /** Format: date-time */
549
557
  created_at: string;
550
558
  engine: null | components["schemas"]["RunEngine"];
@@ -872,6 +880,8 @@ export interface operations {
872
880
  "Cloud-Sim-Version"?: string | null;
873
881
  /** @description Up to 255 printable ASCII characters: the same request again with it gets the same run. */
874
882
  "Idempotency-Key"?: string | null;
883
+ /** @description The client making the run, as `product/version` tokens separated by spaces (`cloud-sim-mcp/0.2.1 cloud-sim-ts/0.2.1`): the run keeps it as `client`. Up to 200 printable ASCII characters; any other value is left out, not refused. */
884
+ "Cloud-Sim-Client"?: string | null;
875
885
  };
876
886
  path?: never;
877
887
  cookie?: never;
package/dist/http.d.ts CHANGED
@@ -13,6 +13,7 @@ export interface RetryInfo {
13
13
  export interface TransportOptions {
14
14
  apiKey: ApiKey;
15
15
  version?: string;
16
+ client?: string;
16
17
  baseUrl?: string;
17
18
  fetch?: typeof fetch;
18
19
  onUnauthorized?: () => Promise<void> | void;
@@ -48,6 +49,8 @@ export interface Call {
48
49
  }
49
50
  export declare class Transport {
50
51
  readonly version: string | undefined;
52
+ /** `Cloud-Sim-Client`, as a create sends it. */
53
+ readonly client: string;
51
54
  readonly baseUrl: string;
52
55
  /** How many times a transient failure is tried again. */
53
56
  readonly maxRetries: number;
package/dist/http.js CHANGED
@@ -2,6 +2,7 @@
2
2
  // version header, a time limit on the answer, retries of what is safe to
3
3
  // retry, and the server's error body turned into a CloudSimError.
4
4
  import { CloudSimError, generalCode } from './errors.js';
5
+ import { SDK_VERSION } from './version.js';
5
6
  export const DEFAULT_BASE_URL = 'https://cloud.simantic.com';
6
7
  const DEFAULT_MAX_RETRIES = 3;
7
8
  // The CLI's and the dashboard's own limit: a submit can take a while, as the
@@ -14,8 +15,14 @@ const MAX_BACKOFF_MS = 8_000;
14
15
  // A Retry-After longer than this is not waited out: a call that would sit
15
16
  // for minutes is the caller's to decide on, so it fails with the error.
16
17
  const MAX_RETRY_AFTER_MS = 60_000;
18
+ // The SDK as `Cloud-Sim-Client` names it, after any client built on it.
19
+ const SDK_CLIENT = `cloud-sim-ts/${SDK_VERSION}`;
20
+ // The longest `Cloud-Sim-Client` the server keeps; it drops a longer one.
21
+ const MAX_CLIENT_LENGTH = 200;
17
22
  export class Transport {
18
23
  version;
24
+ /** `Cloud-Sim-Client`, as a create sends it. */
25
+ client;
19
26
  baseUrl;
20
27
  /** How many times a transient failure is tried again. */
21
28
  maxRetries;
@@ -27,6 +34,7 @@ export class Transport {
27
34
  constructor(options) {
28
35
  this.apiKey = options.apiKey;
29
36
  this.version = options.version;
37
+ this.client = clientHeader(options.client);
30
38
  this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/+$/, '');
31
39
  // Called as a plain function: a browser's fetch throws "Illegal
32
40
  // invocation" when called as a method of anything but the window.
@@ -289,3 +297,21 @@ export function sleep(ms, signal) {
289
297
  export function isRecord(v) {
290
298
  return typeof v === 'object' && v !== null && !Array.isArray(v);
291
299
  }
300
+ /**
301
+ * `Cloud-Sim-Client` for a client built on the SDK as `client` (none for the
302
+ * SDK used as it is): its products, then the SDK's. Checked here rather than
303
+ * left to the server, which keeps only 1-200 printable ASCII characters and
304
+ * otherwise drops it, and to fetch, which refuses other characters in a
305
+ * header only when a request is sent.
306
+ */
307
+ function clientHeader(client) {
308
+ const named = client?.trim();
309
+ if (!named)
310
+ return SDK_CLIENT;
311
+ const header = `${named} ${SDK_CLIENT}`;
312
+ if (!/^[\x21-\x7e]+( [\x21-\x7e]+)*$/.test(named) || header.length > MAX_CLIENT_LENGTH) {
313
+ throw new TypeError(`client must be printable ASCII products separated by single spaces, such as "my-tool/1.2", ` +
314
+ `of at most ${MAX_CLIENT_LENGTH - SDK_CLIENT.length - 1} characters: got ${JSON.stringify(client)}`);
315
+ }
316
+ return header;
317
+ }
package/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export { CloudSim, type CloudSimOptions } from './client.js';
2
+ export { SDK_VERSION } from './version.js';
2
3
  export { CloudSimError, type CloudSimErrorInit, CompareError, isTransient, } from './errors.js';
3
4
  export type { ApiKey, RetryInfo } from './http.js';
4
5
  export { type FollowEvent, type FollowOptions, type FollowTransport, type Offsets, type StreamName, POLL_INTERVAL_MS, } from './follow.js';
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  // fetch does: Node 18 and later, browsers, Deno, Bun, edge runtimes.
4
4
  // Anything that needs Node lives in '@simantic/cloud-sim/node'.
5
5
  export { CloudSim } from './client.js';
6
+ export { SDK_VERSION } from './version.js';
6
7
  export { CloudSimError, CompareError, isTransient, } from './errors.js';
7
8
  export { POLL_INTERVAL_MS, } from './follow.js';
8
9
  export { compareResults } from './compare.js';
package/dist/runs.js CHANGED
@@ -169,7 +169,7 @@ export class Runs {
169
169
  const call = {
170
170
  method: 'POST',
171
171
  path: '/v1/runs',
172
- headers: { 'Idempotency-Key': key },
172
+ headers: { 'Idempotency-Key': key, 'Cloud-Sim-Client': this.http.client },
173
173
  version: params.version,
174
174
  signal: params.signal,
175
175
  timeoutMs: params.timeoutMs,
@@ -0,0 +1 @@
1
+ export declare const SDK_VERSION = "0.3.1";
@@ -0,0 +1,4 @@
1
+ // The SDK's own version, as a run's `Cloud-Sim-Client` names it
2
+ // (`cloud-sim-ts/<version>`). A test keeps it equal to package.json's, so a
3
+ // release that bumps one bumps the other.
4
+ export const SDK_VERSION = '0.3.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@simantic/cloud-sim",
3
- "version": "0.2.0",
3
+ "version": "0.3.1",
4
4
  "description": "TypeScript client for the Cloud Sim API: run MCU firmware in the cloud, follow its output live, and compare simulation engines.",
5
5
  "type": "module",
6
6
  "exports": {
@@ -23,13 +23,8 @@
23
23
  "engines": {
24
24
  "node": ">=18"
25
25
  },
26
- "license": "UNLICENSED",
27
- "repository": {
28
- "type": "git",
29
- "url": "git+https://github.com/simantic-dev/cloud-sim.git",
30
- "directory": "sdk/typescript"
31
- },
32
- "homepage": "https://github.com/simantic-dev/cloud-sim/tree/main/sdk/typescript#readme",
26
+ "license": "MIT",
27
+ "homepage": "https://simantic.com/cloud-sim",
33
28
  "keywords": [
34
29
  "simantic",
35
30
  "cloud-sim",
@@ -52,8 +47,5 @@
52
47
  "openapi-typescript": "^7.13.0",
53
48
  "typescript": "~5.9.3",
54
49
  "vitest": "^4.1.11"
55
- },
56
- "publishConfig": {
57
- "access": "restricted"
58
50
  }
59
51
  }