@signosoft/signpad-js 0.5.3 → 0.6.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.
package/README.md CHANGED
@@ -59,14 +59,13 @@ Without a valid lease, the component can still render, but driver initialization
59
59
  async function fetchLease() {
60
60
  try {
61
61
  const response = await fetch(
62
- "https://test.signosoft.com/api/v1/driver/leases",
62
+ "https://test.signosoft.com/api/v1/public/driver-leases/create",
63
63
  {
64
64
  method: "POST",
65
65
  headers: { "Content-Type": "application/json" },
66
66
  body: JSON.stringify({
67
- licenceKey: "YOUR-LICENSE-KEY",
67
+ token: "YOUR-LICENSE-TOKEN",
68
68
  validityHours: 24,
69
- port: 4204,
70
69
  }),
71
70
  },
72
71
  );
@@ -245,14 +244,13 @@ export class AppComponent implements AfterViewInit {
245
244
  public async fetchLease(): Promise<any> {
246
245
  try {
247
246
  const response = await fetch(
248
- "https://test.signosoft.com/api/v1/driver/leases",
247
+ "https://test.signosoft.com/api/v1/public/driver-leases/create",
249
248
  {
250
249
  method: "POST",
251
250
  headers: { "Content-Type": "application/json" },
252
251
  body: JSON.stringify({
253
- licenceKey: "YOUR-LICENSE-KEY",
252
+ token: "YOUR-LICENSE-TOKEN",
254
253
  validityHours: 24,
255
- port: 4204,
256
254
  }),
257
255
  },
258
256
  );
@@ -331,14 +329,13 @@ import type { SignpadConfig } from "@signosoft/signpad-js";
331
329
  async function fetchLease() {
332
330
  try {
333
331
  const response = await fetch(
334
- "https://test.signosoft.com/api/v1/driver/leases",
332
+ "https://test.signosoft.com/api/v1/public/driver-leases/create",
335
333
  {
336
334
  method: "POST",
337
335
  headers: { "Content-Type": "application/json" },
338
336
  body: JSON.stringify({
339
- licenceKey: "YOUR-LICENSE-KEY",
337
+ token: "YOUR-LICENSE-TOKEN",
340
338
  validityHours: 24,
341
- port: 4204,
342
339
  }),
343
340
  },
344
341
  );
@@ -439,13 +436,12 @@ const signpadConfig = ref<SignpadConfig>({ lease: undefined });
439
436
 
440
437
  const fetchLease = async () => {
441
438
  try {
442
- const response = await fetch("https://test.signosoft.com/api/v1/driver/leases", {
439
+ const response = await fetch("https://test.signosoft.com/api/v1/public/driver-leases/create", {
443
440
  method: "POST",
444
441
  headers: { "Content-Type": "application/json" },
445
442
  body: JSON.stringify({
446
- licenceKey: "YOUR-LICENSE-KEY",
443
+ token: "YOUR-LICENSE-TOKEN",
447
444
  validityHours: 24,
448
- port: 4204,
449
445
  }),
450
446
  });
451
447
 
@@ -526,14 +522,13 @@ pad.config = {
526
522
  const fetchLease = async () => {
527
523
  try {
528
524
  const response = await fetch(
529
- "https://test.signosoft.com/api/v1/driver/leases",
525
+ "https://test.signosoft.com/api/v1/public/driver-leases/create",
530
526
  {
531
527
  method: "POST",
532
528
  headers: { "Content-Type": "application/json" },
533
529
  body: JSON.stringify({
534
- licenceKey: "YOUR-LICENSE-KEY",
530
+ token: "YOUR-LICENSE-TOKEN",
535
531
  validityHours: 24,
536
- port: 4204,
537
532
  }),
538
533
  },
539
534
  );
@@ -676,6 +671,7 @@ The complete list of keys that can be translated is maintained in `src/i18n/en.j
676
671
  | `CONNECTION_ERROR` | Connection error. |
677
672
  | `ERROR_DISCONNECTION` | Error during disconnection. |
678
673
  | `ERROR_INSTANTIATING_DRIVER` | Error instantiating driver. |
674
+ | `INSUFFICIENT_TOKENS` | Not enough tokens to sign. Reconnecting… |
679
675
  | `INVALID_LICENSE_KEY` | Invalid license key. |
680
676
  | `READY_TO_CONNECT` | Ready to connect. |
681
677
  | `SIGNPAD_DETECTED` | Signpad detected. Click 'Connect Signpad' to begin. |
@@ -711,10 +707,28 @@ Standard event listeners triggered _after_ specific actions. Useful for observin
711
707
  | `onOk` | `event: CustomEvent<ISignatureConfirmationData>` | Dispatched when signature is confirmed. |
712
708
  | `onClear` | `event: CustomEvent<void>` | Dispatched when the canvas has been cleared. |
713
709
  | `onCancel` | `event: CustomEvent<void>` | Dispatched when the user aborts the session. |
714
- | `onError` | `event: CustomEvent<Error>` | Dispatched on critical failures (lease, driver, connection, etc.). |
710
+ | `onError` | `event: CustomEvent<ISignpadErrorDetail>` | Dispatched on critical failures (lease, driver, connection, billing, etc.). |
715
711
 
716
712
  > `actionHandlers` and `eventCallbacks` are separate hooks and can both be configured.
717
713
 
714
+ #### 🚨 `onError` payload (`ISignpadErrorDetail`)
715
+
716
+ ```typescript
717
+ {
718
+ category: SignpadErrorCategory; // BILLING_DENIED | NETWORK | OTHER
719
+ message: string; // error.message, for convenience
720
+ error: Error; // the original error
721
+ }
722
+ ```
723
+
724
+ `category` also drives automatic recovery:
725
+
726
+ - **`BILLING_DENIED`** — the lease has run out of signing credits/tokens. Signing automatically restarts a few seconds after the error is shown.
727
+ - **`OTHER`** — any other recoverable failure (e.g. a driver hiccup, a cancelled device picker). Signing automatically restarts the same way as `BILLING_DENIED`.
728
+ - **`NETWORK`** — a connectivity problem (lease fetch failed, device physically disconnected, origin validation failed). The error stays shown; signing does **not** auto-restart, since retrying on a timer can't fix a network or configuration problem — the user (or your app) must retry manually, e.g. via `connect()`.
729
+
730
+ > **Migration note (breaking payload shape change):** `event.detail` used to be the raw `Error`. It is now `ISignpadErrorDetail`; use `event.detail.error` for the original `Error` instance. `event.detail.message` still works unchanged.
731
+
718
732
  ---
719
733
 
720
734
  ### 💡 Example Implementation
@@ -923,7 +937,17 @@ The component progresses through a finite set of states, exposed via the `Signpa
923
937
  | `PROCESSING_CANCEL` | `"processing_cancel"` | Cancel action is being processed. |
924
938
  | `DISCONNECTING` | `"disconnecting"` | Disconnect in progress. |
925
939
  | `DISCONNECTED` | `"disconnected"` | Component is idle and disconnected. |
926
- | `ERROR` | `"error"` | An unrecoverable error occurred (see `onError` callback). |
940
+ | `ERROR` | `"error"` | An error occurred (see `onError` callback). Signing automatically restarts a few seconds later unless the error's `category` is `NETWORK`. |
941
+
942
+ ### 🚨 `SignpadErrorCategory`
943
+
944
+ Also importable from `@signosoft/signpad-js`, carried on the `onError` payload (see [`onError` payload](#-onerror-payload-isignpaderrordetail) above):
945
+
946
+ | Value | Value string | Auto-restarts signing? |
947
+ | :--------------- | :------------------ | :---------------------- |
948
+ | `BILLING_DENIED` | `"billing_denied"` | Yes |
949
+ | `NETWORK` | `"network"` | No |
950
+ | `OTHER` | `"other"` | Yes |
927
951
 
928
952
  ---
929
953
 
package/dist/index.d.ts CHANGED
@@ -241,6 +241,20 @@ declare class ConnectionManager {
241
241
  * @returns Resolves when the driver is initialized.
242
242
  */
243
243
  initWithLease(lease: any): Promise<void>;
244
+ /**
245
+ * Called by the driver when the lease has run out of signing credits.
246
+ * @param detail - Driver-provided description of the denial.
247
+ * @returns Always false — declines the driver's own retry; signpad-js's
248
+ * auto-restart (triggered by the ERROR transition below) handles recovery.
249
+ */
250
+ private handleBillingDenied;
251
+ /**
252
+ * Called by the driver when the billing check itself fails (e.g. the
253
+ * billing server is unreachable). Treated as a network error.
254
+ * @param detail - Driver-provided description of the failure.
255
+ * @returns Always false — see handleBillingDenied.
256
+ */
257
+ private handleBillingError;
244
258
  isFallback(deviceInfo: any | null, isDeviceConnected: boolean, includeDisconnected: boolean): boolean;
245
259
  /**
246
260
  * Normalizes device info to always include deviceName.
@@ -288,7 +302,7 @@ export declare interface IEventCallbacks {
288
302
  onOk?: (event: CustomEvent<ISignatureConfirmationData>) => void;
289
303
  onClear?: (event: CustomEvent<void>) => void;
290
304
  onCancel?: (event: CustomEvent<void>) => void;
291
- onError?: (event: CustomEvent<Error>) => void;
305
+ onError?: (event: CustomEvent<ISignpadErrorDetail>) => void;
292
306
  }
293
307
 
294
308
  export declare interface ILanguageOptions {
@@ -360,6 +374,12 @@ export declare interface ISignatureTabletMeta {
360
374
  [key: string]: any;
361
375
  }
362
376
 
377
+ export declare interface ISignpadErrorDetail {
378
+ category: SignpadErrorCategory;
379
+ message: string;
380
+ error: Error;
381
+ }
382
+
363
383
  export declare interface ITranslationSet {
364
384
  [key: string]: string;
365
385
  }
@@ -630,6 +650,19 @@ export declare class SignosoftSignpad extends LitElement {
630
650
  private shouldScheduleImmediateRetry;
631
651
  private scheduleAutoConnectRetry;
632
652
  private clearAutoConnectQueue;
653
+ /**
654
+ * Schedules signing to restart automatically after a BILLING_DENIED/OTHER
655
+ * error, so the flow recovers without requiring a manual reconnect.
656
+ * NETWORK errors never reach this — they stay shown until the user retries.
657
+ * @param delayMs - How long to keep the error visible before restarting.
658
+ */
659
+ private scheduleErrorAutoRestart;
660
+ /**
661
+ * Restarts the signing session after an auto-recoverable error, respecting
662
+ * the connect/disconnect reentrancy lock so it never races a concurrent
663
+ * manual connect/disconnect or hotplug transition.
664
+ */
665
+ private restartSigningAfterError;
633
666
  private delay;
634
667
  /**
635
668
  * Disconnects current session without transitioning through DISCONNECTED UI.
@@ -676,6 +709,12 @@ export declare interface SignpadConfig {
676
709
  eventCallbacks?: IEventCallbacks;
677
710
  }
678
711
 
712
+ export declare enum SignpadErrorCategory {
713
+ BILLING_DENIED = "billing_denied",
714
+ NETWORK = "network",
715
+ OTHER = "other"
716
+ }
717
+
679
718
  export declare enum SignpadEventType {
680
719
  SIGN_PEN = "sign-pen",
681
720
  SIGN_OK = "sign-ok",
@@ -702,6 +741,7 @@ export declare enum SignpadMessage {
702
741
  CONNECTION_ERROR = "CONNECTION_ERROR",
703
742
  ERROR_DISCONNECTION = "ERROR_DISCONNECTION",
704
743
  ERROR_INSTANTIATING_DRIVER = "ERROR_INSTANTIATING_DRIVER",
744
+ INSUFFICIENT_TOKENS = "INSUFFICIENT_TOKENS",
705
745
  INVALID_LICENSE_KEY = "INVALID_LICENSE_KEY",
706
746
  READY_TO_CONNECT = "READY_TO_CONNECT",
707
747
  SIGNPAD_DETECTED = "SIGNPAD_DETECTED",
@@ -800,7 +840,15 @@ declare class StateManager {
800
840
  * @param error - Optional error object if transitioning to an ERROR state.
801
841
  * @returns void
802
842
  */
803
- transitionTo(newState: SignpadState, messageKey?: string, error?: Error): void;
843
+ transitionTo(newState: SignpadState, messageKey?: string, error?: Error, category?: SignpadErrorCategory): void;
844
+ /**
845
+ * Heuristically classifies an error for auto-recovery decisions.
846
+ * Explicit categories (e.g. from billing hooks) should be passed to
847
+ * transitionTo directly rather than relying on this fallback.
848
+ * @param error - The error to classify.
849
+ * @returns The inferred error category.
850
+ */
851
+ private classifyError;
804
852
  /**
805
853
  * Updates the internal drawing flag. Triggers a UI update if the value changes.
806
854
  * @param started - Boolean indicating if the user has started drawing.