seam 1.232.0 → 1.233.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 (2) hide show
  1. package/README.md +267 -4
  2. package/package.json +4 -3
package/README.md CHANGED
@@ -53,12 +53,19 @@ Instead, it builds on a core set of Seam modules:
53
53
  - [Advanced Usage](#advanced-usage)
54
54
  - [Additional Options](#additional-options)
55
55
  - [Setting the endpoint](#setting-the-endpoint)
56
+ - [Setting the request timeout](#setting-the-request-timeout)
56
57
  - [Configuring the Axios Client](#configuring-the-axios-client)
57
58
  - [Using the Axios Client](#using-the-axios-client)
58
59
  - [Overriding the Client](#overriding-the-client)
59
60
  - [Alternative endpoint path interface](#alternative-endpoint-path-interface)
60
61
  - [Inspecting the Request](#inspecting-the-request)
62
+ - [Serializing URL search params](#serializing-url-search-params)
61
63
  - [Command Line Interface](#command-line-interface)
64
+ - [Output](#output)
65
+ - [Pagination](#pagination-1)
66
+ - [JSON](#json)
67
+ - [Selecting an endpoint and a workspace](#selecting-an-endpoint-and-a-workspace)
68
+ - [Environment variables](#environment-variables)
62
69
  - [Receiving Webhooks](#receiving-webhooks)
63
70
  - [Development and Testing](#development-and-testing)
64
71
  - [Quickstart](#quickstart)
@@ -468,6 +475,7 @@ the constructor takes some advanced options that affect behavior.
468
475
  const seam = new Seam({
469
476
  apiKey: 'your-api-key',
470
477
  endpoint: 'https://example.com',
478
+ timeout: 30000,
471
479
  axiosOptions: {},
472
480
  axiosRetryOptions: {},
473
481
  })
@@ -479,6 +487,7 @@ these options may be passed in as the last argument.
479
487
  ```ts
480
488
  const seam = Seam.fromApiKey('some-api-key', {
481
489
  endpoint: 'https://example.com',
490
+ timeout: 30000,
482
491
  axiosOptions: {},
483
492
  axiosRetryOptions: {},
484
493
  })
@@ -492,12 +501,39 @@ This option corresponds to the Axios `baseURL` setting.
492
501
 
493
502
  Either pass the `endpoint` option, or set the `SEAM_ENDPOINT` environment variable.
494
503
 
504
+ #### Setting the request timeout
505
+
506
+ Requests time out after 30 seconds by default.
507
+ Pass the `timeout` option, in milliseconds, to override this:
508
+
509
+ ```ts
510
+ const seam = new Seam({
511
+ apiKey: 'your-api-key',
512
+ timeout: 60000,
513
+ })
514
+ ```
515
+
516
+ Set `timeout` to `0` to disable the timeout entirely.
517
+ A request that times out rejects with an Axios `ETIMEDOUT` error.
518
+ Timed-out idempotent requests are retried according to the retry options, with
519
+ the timeout reset for each attempt. Non-idempotent requests are not retried by
520
+ default.
521
+
495
522
  #### Configuring the Axios Client
496
523
 
497
524
  The Axios client and retry behavior may be configured with custom initiation options
498
525
  via [`axiosOptions`][axiosOptions] and [`axiosRetryOptions`][axiosRetryOptions].
499
526
  Options are deep merged with the default options.
500
527
 
528
+ By default, the SDK makes up to three attempts: the initial request and two
529
+ retries. Retries are limited to `GET`, `HEAD`, `OPTIONS`, `PUT`, and `DELETE`
530
+ requests that fail because of a transport error, timeout, HTTP 429 response, or
531
+ HTTP 5xx response. `POST` and `PATCH` requests are not retried.
532
+
533
+ Retries use exponential backoff with jitter: approximately 200–240 ms before
534
+ the first retry and 400–480 ms before the second. A longer `Retry-After` header
535
+ is honored. The request timeout is reset for each attempt.
536
+
501
537
  [axiosOptions]: https://axios-http.com/docs/config_defaults
502
538
  [axiosRetryOptions]: https://github.com/softonic/axios-retry
503
539
 
@@ -550,11 +586,69 @@ console.log(`${request.method} ${request.url}`, JSON.stringify(request.body))
550
586
  const devices = await request.execute()
551
587
  ```
552
588
 
589
+ #### Serializing URL search params
590
+
591
+ The Seam API parses URL search params as complex types.
592
+ If you call it with your own HTTP client, use `serializeUrlSearchParams`:
593
+
594
+ ```ts
595
+ import axios from 'axios'
596
+ import { serializeUrlSearchParams } from 'seam'
597
+
598
+ await axios.get('https://connect.getseam.com/devices/list', {
599
+ params: { device_ids: ['device1', 'device2'] },
600
+ paramsSerializer: serializeUrlSearchParams,
601
+ headers: { Authorization: 'Bearer your-api-key' },
602
+ })
603
+ ```
604
+
605
+ or `updateUrlSearchParams`:
606
+
607
+ ```ts
608
+ import { updateUrlSearchParams } from 'seam'
609
+
610
+ const searchParams = new URLSearchParams()
611
+ updateUrlSearchParams(searchParams, { device_ids: ['device1', 'device2'] })
612
+
613
+ Array.from(searchParams)
614
+ // => [['device_ids', 'device1'], ['device_ids', 'device2'], ['_strict', 'true']]
615
+
616
+ searchParams.toString()
617
+ // => 'device_ids=device1&device_ids=device2&_strict=true'
618
+ ```
619
+
620
+ The helpers wrap the [reference implementation].
621
+ The serialization defines the name and string value of each search param.
622
+ [`URLSearchParams`][URLSearchParams] holds those pairs and renders the query string:
623
+ The `_strict=true` parameter is added to any non-empty query so the Seam API uses
624
+ strict, schema-aware parsing.
625
+ A query with no serializable params remains empty.
626
+
627
+ A param set to `undefined` is omitted, while a param set to `null` is serialized
628
+ to an empty value, which the Seam API reads as null.
629
+ A param that cannot be represented raises an `UnserializableParamError`.
630
+ The Seam API parses these params with the corresponding [parser].
631
+
632
+ [URLSearchParams]: https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams
633
+ [reference implementation]: https://github.com/seamapi/url-search-params-serializer
634
+ [parser]: https://github.com/seamapi/url-search-params-parser
635
+
553
636
  ### Command Line Interface
554
637
 
555
- Every `seam` command is interactive and will prompt you for any missing
556
- required properties with helpful suggestions. To avoid automatic behavior,
557
- pass `-y`.
638
+ Every `seam` command makes its request as soon as every required property is
639
+ given. When something is missing, the CLI prompts you for it with helpful
640
+ suggestions.
641
+
642
+ Pass `--interactive` (or `-i`) to always be prompted to review and edit
643
+ properties before the request is made. The prompt is prefilled with whatever
644
+ you passed as arguments or piped in as JSON, and each property you open is
645
+ prefilled with the value it has, ready to edit rather than retype. This is the
646
+ way to add optional properties, or to check a request before making it.
647
+
648
+ For scripts and CI, pass `--non-interactive` (or `-y`) to never be prompted.
649
+ The command must then be complete: if the command itself is ambiguous, or any
650
+ required property is missing, the CLI exits with an error naming what is
651
+ missing instead of asking for it.
558
652
 
559
653
  To take a project from zero to a working Seam integration, run the
560
654
  [Seam Wizard] from the project's root:
@@ -581,7 +675,19 @@ seam connect-webviews create
581
675
  # List devices in your workspace
582
676
  seam devices list
583
677
 
584
- MY_DOOR=$(seam devices get --name "Front Door" --id-only)
678
+ # Review and edit filters before listing devices
679
+ seam devices list --interactive
680
+
681
+ # List devices, failing instead of prompting
682
+ seam devices list --non-interactive
683
+
684
+ # Fails with: Missing required parameter for /locks/unlock_door: --device-id
685
+ seam locks unlock-door --non-interactive
686
+
687
+ # Fails with: Unknown parameter for /devices/list: --limitt
688
+ seam devices list --limitt 5
689
+
690
+ MY_DOOR=$(seam devices get --name "Front Door" | jq -r '.device.device_id')
585
691
 
586
692
  # Unlock a lock
587
693
  seam locks unlock-door --device-id $MY_DOOR
@@ -593,6 +699,163 @@ seam access-codes create --code "1234" --name "My Code"
593
699
  seam access-codes list --device-id $MY_DOOR
594
700
  ```
595
701
 
702
+ ### Output
703
+
704
+ Only the response is written to stdout, so any command may be piped or
705
+ redirected. Prompts, progress, and other information are written to stderr.
706
+
707
+ The response is trimmed to the response key and pagination: no other top level
708
+ fields are reported.
709
+
710
+ ```bash
711
+ # The response, and nothing else, ends up in the file
712
+ seam devices list > devices.json
713
+
714
+ # Prompts and progress still show up in the terminal
715
+ seam devices list | jq '.devices[].device_id'
716
+ ```
717
+
718
+ ### Pagination
719
+
720
+ Every command that paginates accepts `--page-cursor` to select a page of
721
+ results, alongside `--limit` for the size of that page. Each response reports
722
+ its `pagination`, whose `next_page_cursor` is the cursor for the page after it.
723
+
724
+ ```bash
725
+ # The first page, and the cursor for the next one
726
+ seam devices list --limit 2 | jq '.pagination.next_page_cursor'
727
+
728
+ # The page after it
729
+ seam devices list --limit 2 --page-cursor "$CURSOR"
730
+ ```
731
+
732
+ A cursor is opaque: pass it back exactly as it was reported, and do not build
733
+ one yourself. Run `seam <command> --help` to see whether a command paginates.
734
+
735
+ ### JSON
736
+
737
+ Request params may be piped or redirected in as a JSON object, or passed
738
+ inline with `--raw`. Params given as arguments win over raw or stdin params.
739
+
740
+ An argument the command does not accept is an error, so a typo is reported
741
+ rather than sent. Params read from stdin are passed through as given, so
742
+ anything the API itself accepts may be sent that way.
743
+
744
+ ```bash
745
+ # Read params from a file
746
+ seam locks unlock-door < params.json
747
+
748
+ # Or from another program
749
+ echo '{"device_id": "'"$MY_DOOR"'"}' | seam locks unlock-door
750
+
751
+ # Pass request params inline as JSON
752
+ seam devices list --raw '{"search":"bar"}'
753
+
754
+ # --device-id wins over any device_id in params.json
755
+ seam devices list --limit 5 < params.json
756
+ ```
757
+
758
+ Pass `--json` to write the response as JSON. It is enabled automatically
759
+ whenever stdout is not a terminal, so piping and redirecting produce JSON
760
+ without passing anything. Pass `--no-json` to opt out and get the pretty
761
+ format instead.
762
+
763
+ ```bash
764
+ # Both write JSON
765
+ seam devices list --json
766
+ seam devices list | jq
767
+
768
+ # Pretty printed, even though it is piped
769
+ seam devices list --no-json | less
770
+ ```
771
+
772
+ Without a terminal to prompt on, the CLI behaves as though
773
+ `--non-interactive` was given: rather than waiting for an answer nobody can
774
+ give, it exits with an error naming what is missing.
775
+
776
+ ```bash
777
+ $ echo '{}' | seam locks unlock-door
778
+ Missing required parameter for /locks/unlock_door: --device-id
779
+ ```
780
+
781
+ An error exits non-zero. A request that fails reports its `error` on stdout,
782
+ so it can be inspected from a pipe; anything else is written to stderr only.
783
+
784
+ ### Selecting an endpoint and a workspace
785
+
786
+ Two settings say where commands go, and one command each stores them:
787
+
788
+ ```bash
789
+ # Every later command runs against this endpoint
790
+ seam select endpoint https://connect.getseam.com
791
+
792
+ # ...and this workspace
793
+ seam select workspace $MY_WORKSPACE
794
+ ```
795
+
796
+ Run either without a value to pick one interactively.
797
+
798
+ To send a single command somewhere else, pass `--endpoint` or
799
+ `--workspace-id` to that command. They override what is selected for that one
800
+ invocation and store nothing:
801
+
802
+ ```bash
803
+ # List devices in another workspace, without switching to it
804
+ seam devices list --workspace-id $OTHER_WORKSPACE
805
+
806
+ # Run one command against a local Seam Connect instance
807
+ seam devices list --endpoint http://localhost:3020
808
+
809
+ # Log in to another endpoint: the token is stored for that endpoint,
810
+ # and the selected one is left alone
811
+ seam login --endpoint http://localhost:3020 --token $LOCAL_KEY
812
+ ```
813
+
814
+ Because the two flags never store anything, they are refused on the commands
815
+ that do: `seam select endpoint --endpoint <url>` is an error, and the value
816
+ belongs after the command instead.
817
+
818
+ ### Environment variables
819
+
820
+ Everything `seam login`, `seam select workspace`, and `seam select endpoint`
821
+ store may be given in the environment instead:
822
+
823
+ - `SEAM_CLI_TOKEN`: a Personal Access Token or API Key,
824
+ - `SEAM_CLI_WORKSPACE_ID`: the workspace requests are made against,
825
+ - `SEAM_CLI_ENDPOINT`: the Seam API endpoint requests are made to.
826
+
827
+ Any of them, all of them, or none of them may be set. Each one wins over the
828
+ corresponding stored value and is in turn overridden by `--endpoint` or
829
+ `--workspace-id`, which makes them useful for CI or for working against
830
+ another workspace for a whole shell.
831
+
832
+ ```bash
833
+ # One command against another workspace
834
+ SEAM_CLI_WORKSPACE_ID=$OTHER_WORKSPACE seam devices list
835
+
836
+ # No login needed: authenticate from the environment
837
+ export SEAM_CLI_TOKEN=$SEAM_API_KEY
838
+ seam devices list
839
+
840
+ # Work against a local Seam Connect instance
841
+ SEAM_CLI_ENDPOINT=http://localhost:3020 seam devices list
842
+ ```
843
+
844
+ An API Key is scoped to a single workspace, so it needs no workspace id. A
845
+ Personal Access Token works across workspaces, so it needs one from
846
+ `--workspace-id`, `SEAM_CLI_WORKSPACE_ID`, or `seam select workspace`.
847
+
848
+ The command that would store an overridden value fails rather than storing
849
+ something the environment ignores: `seam login` and `seam logout` while
850
+ `SEAM_CLI_TOKEN` is set, `seam select workspace` while
851
+ `SEAM_CLI_WORKSPACE_ID` is set, and `seam select endpoint` while
852
+ `SEAM_CLI_ENDPOINT` is set. Unset the variable to use those commands.
853
+
854
+ ```bash
855
+ $ SEAM_CLI_TOKEN=$SEAM_API_KEY seam login
856
+ Cannot log in while SEAM_CLI_TOKEN is set: it overrides what would be stored. Unset SEAM_CLI_TOKEN to log in.
857
+ ```
858
+
596
859
  ### Receiving Webhooks
597
860
 
598
861
  The Seam API implements webhooks using [Svix](https://www.svix.com).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "seam",
3
- "version": "1.232.0",
3
+ "version": "1.233.0",
4
4
  "description": "JavaScript SDK for the Seam API written in TypeScript.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -73,9 +73,10 @@
73
73
  "version": "^11.0.0 || ^10.0.0"
74
74
  }
75
75
  },
76
+ "packageManager": "npm@11.19.0",
76
77
  "dependencies": {
77
- "@seamapi/cli": "0.24.1",
78
- "@seamapi/http": "2.3.1",
78
+ "@seamapi/cli": "0.28.0",
79
+ "@seamapi/http": "2.11.2",
79
80
  "@seamapi/webhook": "1.4.1"
80
81
  },
81
82
  "devDependencies": {