@peers-app/peers-sdk 0.15.4 → 0.15.5

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/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  export * from "./context";
2
2
  export * from "./data";
3
- export { WorkflowLogs, getLogger, workflowLogSchema, type IWorkflowLog, } from "./data/workflow-logs";
4
3
  export * as data from "./data";
5
4
  export * from "./data/orm";
6
5
  export * as orm from "./data/orm";
6
+ export { getLogger, type IWorkflowLog, WorkflowLogs, workflowLogSchema, } from "./data/workflow-logs";
7
7
  export * from "./device/binary-peer-connection-v2";
8
8
  export * from "./device/connection";
9
9
  export * from "./device/device";
package/dist/index.js CHANGED
@@ -14,17 +14,17 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.tools = exports.orm = exports.data = exports.workflowLogSchema = exports.getLogger = exports.WorkflowLogs = void 0;
17
+ exports.tools = exports.workflowLogSchema = exports.WorkflowLogs = exports.getLogger = exports.orm = exports.data = void 0;
18
18
  __exportStar(require("./context"), exports);
19
19
  __exportStar(require("./data"), exports);
20
+ exports.data = require("./data");
21
+ __exportStar(require("./data/orm"), exports);
22
+ exports.orm = require("./data/orm");
20
23
  // Root `.d.ts` lists these explicitly so IDEs see them (not only via `export *`).
21
24
  var workflow_logs_1 = require("./data/workflow-logs");
22
- Object.defineProperty(exports, "WorkflowLogs", { enumerable: true, get: function () { return workflow_logs_1.WorkflowLogs; } });
23
25
  Object.defineProperty(exports, "getLogger", { enumerable: true, get: function () { return workflow_logs_1.getLogger; } });
26
+ Object.defineProperty(exports, "WorkflowLogs", { enumerable: true, get: function () { return workflow_logs_1.WorkflowLogs; } });
24
27
  Object.defineProperty(exports, "workflowLogSchema", { enumerable: true, get: function () { return workflow_logs_1.workflowLogSchema; } });
25
- exports.data = require("./data");
26
- __exportStar(require("./data/orm"), exports);
27
- exports.orm = require("./data/orm");
28
28
  __exportStar(require("./device/binary-peer-connection-v2"), exports);
29
29
  __exportStar(require("./device/connection"), exports);
30
30
  __exportStar(require("./device/device"), exports);
package/dist/keys.d.ts CHANGED
@@ -1,52 +1,103 @@
1
+ /** Replaces tweetnacl’s default PRNG (required on some runtimes, e.g. tests or constrained environments). */
1
2
  export declare function setPRNG(fn: (x: Uint8Array, n: number) => void): void;
3
+ /** SHA-256 of UTF-8 `str`, returned as base64url (no padding). */
2
4
  export declare function hashValue(str: string): string;
5
+ /** SHA-256 of raw bytes, returned as base64url (no padding). */
3
6
  export declare function hashBytes(buffer: Uint8Array): string;
7
+ /** Deterministic JSON string via `fast-json-stable-stringify` (key order stable). */
4
8
  export declare function stableStringify(obj: any): string;
9
+ /** {@link hashValue} of the stable JSON for `obj` (for content-addressing object payloads). */
5
10
  export declare function hashObject(obj: {
6
11
  [key: string]: any;
7
12
  }): string;
13
+ /** Base64 with URL-safe alphabet and no `=` padding (used throughout keys and wire formats). */
8
14
  export declare function encodeBase64(data: Uint8Array): string;
15
+ /**
16
+ * Inverse of {@link encodeBase64}; accepts standard or URL-safe base64 and repads as needed.
17
+ * @throws TypeError if `data` is not a string
18
+ */
9
19
  export declare function decodeBase64(data: string): Uint8Array;
20
+ /** Random token as base64url string (`size` raw bytes, default 32). */
10
21
  export declare function newToken(size?: number): string;
22
+ /** Ed25519 signing key and derived X25519 box public key, both base64url. */
11
23
  export interface IPublicKeys {
12
24
  publicKey: string;
13
25
  publicBoxKey: string;
14
26
  }
27
+ /** {@link IPublicKeys} plus Ed25519 secret key material (64-byte encoding as stored by this module). */
15
28
  export interface IPublicPrivateKeys extends IPublicKeys {
16
29
  secretKey: string;
17
30
  }
31
+ /** Detached Ed25519 signature over JSON-serialized `contents` with signer’s public key. */
18
32
  export interface ISignedObject<T> {
19
33
  contents: T;
20
34
  signature: string;
21
35
  publicKey: string;
22
36
  }
37
+ /** NaCl box ciphertext + nonce + sender box public key (all base64url). */
23
38
  export interface IDataBox {
24
39
  contents: string;
25
40
  nonce: string;
26
41
  fromPublicKey: string;
27
42
  }
43
+ /** Generates a new Ed25519 keypair and derived X25519 box keys; all keys are base64url. */
28
44
  export declare function newKeys(): IPublicPrivateKeys;
45
+ /** Re-derives public and box keys from an Ed25519 `secretKey` (same encoding as {@link newKeys}). */
29
46
  export declare function hydrateKeys(secretKey: string): IPublicPrivateKeys;
47
+ /** Signs a UTF-8 message with Ed25519; returns base64url signed message (NaCl `sign` combined format). */
30
48
  export declare function signMessageWithSecretKey(msg: string, secretKey: string): string;
49
+ /**
50
+ * Verifies and strips an Ed25519 signed message; returns the original UTF-8 string.
51
+ * @throws If verification fails
52
+ */
31
53
  export declare function openMessageWithPublicKey(msg: string, publicKey: string): string;
54
+ /**
55
+ * Detached sign over stable JSON: `undefined` / `null` are encoded with sentinel fields for round-trip.
56
+ * @returns Payload with original `contents`, `signature`, and signer's Ed25519 public key (32-byte slice, base64url)
57
+ */
32
58
  export declare function signObjectWithSecretKey<T>(obj: T, secretKey: string): ISignedObject<T>;
59
+ /**
60
+ * Verifies a detached signature and returns `contents` after undoing the undefined/null sentinels.
61
+ * @throws If the signature is invalid
62
+ */
33
63
  export declare function openSignedObject<T>(signedObj: ISignedObject<T>): T;
64
+ /**
65
+ * X25519 box encrypts `data` (msgpack via {@link txEncode}) to `toPublicBoxKey` from keys derived from `mySecretKey`.
66
+ * @param toPublicBoxKey Recipient’s X25519 public key (base64url)
67
+ */
34
68
  export declare function boxDataWithKeys(data: any, toPublicBoxKey: string, mySecretKey: string): IDataBox;
69
+ /** Narrowing guard: value looks like an {@link IDataBox} envelope. */
35
70
  export declare function isBoxedData(data: any): boolean;
71
+ /**
72
+ * Decrypts a box from {@link boxDataWithKeys} using the recipient’s Ed25519 secret (same format as {@link newKeys}).
73
+ * @throws If decryption or authentication fails
74
+ */
36
75
  export declare function openBoxWithSecretKey(box: IDataBox, mySecretKey: string): any;
76
+ /** JSON-serializes `data` then NaCl `secretbox` with a random nonce; returns base64 payload `~` base64 nonce. */
37
77
  export declare function encryptData<T>(data: T, secretKey: string): string;
78
+ /** Inverse of {@link encryptData}. Returns `null` if secretbox open fails. */
38
79
  export declare function decryptData<T>(encryptedData: string, secretKey: string): T | null;
80
+ /** Object plus a `signature` field in the `publicKey:detachedSig` form produced by this module. */
39
81
  export type IObjectWithSignature<T> = T & {
40
82
  signature: string;
41
83
  };
42
84
  type IMaybeSignature = {
43
85
  signature?: string;
44
86
  };
87
+ /**
88
+ * Strips any existing `signature`, signs a shallow copy of `obj`, and sets `signature` to `publicKey:detachedSig`.
89
+ * @returns Same shape as `obj` with string `signature` suitable for {@link verifyObjectSignature}
90
+ */
45
91
  export declare function addSignatureToObject<T extends Record<string, any>>(obj: T, secretKey: string): IObjectWithSignature<T>;
46
92
  /**
47
- * Will throw if the signature is invalid
93
+ * Ensures `signature` matches the rest of the object via {@link openSignedObject}.
94
+ * @throws If there is no signature or verification fails
48
95
  */
49
96
  export declare function verifyObjectSignature<T extends IMaybeSignature>(objectWithSignature: T): void;
97
+ /** True if {@link verifyObjectSignature} would succeed. */
50
98
  export declare function isObjectSignatureValid<T extends IMaybeSignature>(objectWithSignature: T): boolean;
99
+ /**
100
+ * Parses the Ed25519 public key prefix from a `publicKey:signature` field, or `undefined` if malformed.
101
+ */
51
102
  export declare function getPublicKeyFromObjectSignature<T extends IMaybeSignature>(objectWithSignature: T): string | undefined;
52
103
  export {};
package/dist/keys.js CHANGED
@@ -33,9 +33,11 @@ const tx_encoding_1 = require("./device/tx-encoding");
33
33
  const serial_json_1 = require("./serial-json");
34
34
  globalThis.Buffer = buffer_1.Buffer; // shim for browsers/RN
35
35
  const _stableStringify = require("fast-json-stable-stringify");
36
+ /** Replaces tweetnacl’s default PRNG (required on some runtimes, e.g. tests or constrained environments). */
36
37
  function setPRNG(fn) {
37
38
  nacl.setPRNG(fn);
38
39
  }
40
+ /** SHA-256 of UTF-8 `str`, returned as base64url (no padding). */
39
41
  function hashValue(str) {
40
42
  // const full = nacl.hash(decodeUTF8(str));
41
43
  // const half = full.slice(0, 32);
@@ -43,23 +45,31 @@ function hashValue(str) {
43
45
  const hash = (0, sha2_1.sha256)(new TextEncoder().encode(str));
44
46
  return encodeBase64(hash);
45
47
  }
48
+ /** SHA-256 of raw bytes, returned as base64url (no padding). */
46
49
  function hashBytes(buffer) {
47
50
  const hash = (0, sha2_1.sha256)(buffer);
48
51
  return encodeBase64(hash);
49
52
  }
53
+ /** Deterministic JSON string via `fast-json-stable-stringify` (key order stable). */
50
54
  function stableStringify(obj) {
51
55
  return _stableStringify(obj);
52
56
  }
57
+ /** {@link hashValue} of the stable JSON for `obj` (for content-addressing object payloads). */
53
58
  function hashObject(obj) {
54
59
  const stableJson = stableStringify(obj);
55
60
  const hash = hashValue(stableJson);
56
61
  return hash;
57
62
  }
63
+ /** Base64 with URL-safe alphabet and no `=` padding (used throughout keys and wire formats). */
58
64
  function encodeBase64(data) {
59
65
  // return Buffer.from(data).toString("base64url"); // no padding by default
60
66
  const str = utils.encodeBase64(data);
61
67
  return str.replace(/\+/g, "-").replace(/\//g, "_").replace(/=/g, "");
62
68
  }
69
+ /**
70
+ * Inverse of {@link encodeBase64}; accepts standard or URL-safe base64 and repads as needed.
71
+ * @throws TypeError if `data` is not a string
72
+ */
63
73
  function decodeBase64(data) {
64
74
  if (typeof data !== "string") {
65
75
  throw new TypeError(`decodeBase64 expected a string but received ${typeof data}`);
@@ -70,9 +80,11 @@ function decodeBase64(data) {
70
80
  }
71
81
  return utils.decodeBase64(data);
72
82
  }
83
+ /** Random token as base64url string (`size` raw bytes, default 32). */
73
84
  function newToken(size = 32) {
74
85
  return encodeBase64(nacl.randomBytes(size));
75
86
  }
87
+ /** Generates a new Ed25519 keypair and derived X25519 box keys; all keys are base64url. */
76
88
  function newKeys() {
77
89
  const sign = nacl.sign.keyPair(); // Ed25519
78
90
  const curveSecret = ed2curve.convertSecretKey(sign.secretKey); // 32 bytes
@@ -83,6 +95,7 @@ function newKeys() {
83
95
  publicBoxKey: encodeBase64(box.publicKey),
84
96
  };
85
97
  }
98
+ /** Re-derives public and box keys from an Ed25519 `secretKey` (same encoding as {@link newKeys}). */
86
99
  function hydrateKeys(secretKey) {
87
100
  const sk64 = decodeBase64(secretKey); // Ed25519 64-byte secretKey
88
101
  const curveSecret = ed2curve.convertSecretKey(sk64);
@@ -93,12 +106,17 @@ function hydrateKeys(secretKey) {
93
106
  publicBoxKey: encodeBase64(box.publicKey),
94
107
  };
95
108
  }
109
+ /** Signs a UTF-8 message with Ed25519; returns base64url signed message (NaCl `sign` combined format). */
96
110
  function signMessageWithSecretKey(msg, secretKey) {
97
111
  const _secretKey = decodeBase64(secretKey);
98
112
  const msgDecoded = (0, tweetnacl_util_1.decodeUTF8)(msg);
99
113
  const msgSigned = nacl.sign(msgDecoded, _secretKey);
100
114
  return encodeBase64(msgSigned);
101
115
  }
116
+ /**
117
+ * Verifies and strips an Ed25519 signed message; returns the original UTF-8 string.
118
+ * @throws If verification fails
119
+ */
102
120
  function openMessageWithPublicKey(msg, publicKey) {
103
121
  const _publicKey = decodeBase64(publicKey);
104
122
  const msgDecoded = decodeBase64(msg);
@@ -108,6 +126,10 @@ function openMessageWithPublicKey(msg, publicKey) {
108
126
  }
109
127
  return (0, tweetnacl_util_1.encodeUTF8)(msgOpened);
110
128
  }
129
+ /**
130
+ * Detached sign over stable JSON: `undefined` / `null` are encoded with sentinel fields for round-trip.
131
+ * @returns Payload with original `contents`, `signature`, and signer's Ed25519 public key (32-byte slice, base64url)
132
+ */
111
133
  function signObjectWithSecretKey(obj, secretKey) {
112
134
  const _secretKey = decodeBase64(secretKey);
113
135
  if (obj === undefined) {
@@ -125,6 +147,10 @@ function signObjectWithSecretKey(obj, secretKey) {
125
147
  publicKey: encodeBase64(_secretKey.slice(32)),
126
148
  };
127
149
  }
150
+ /**
151
+ * Verifies a detached signature and returns `contents` after undoing the undefined/null sentinels.
152
+ * @throws If the signature is invalid
153
+ */
128
154
  function openSignedObject(signedObj) {
129
155
  const _publicKey = decodeBase64(signedObj.publicKey);
130
156
  const objStr = (0, serial_json_1.toJSONString)(signedObj.contents);
@@ -145,6 +171,10 @@ function openSignedObject(signedObj) {
145
171
  }
146
172
  return signedObj.contents;
147
173
  }
174
+ /**
175
+ * X25519 box encrypts `data` (msgpack via {@link txEncode}) to `toPublicBoxKey` from keys derived from `mySecretKey`.
176
+ * @param toPublicBoxKey Recipient’s X25519 public key (base64url)
177
+ */
148
178
  function boxDataWithKeys(data, toPublicBoxKey, mySecretKey) {
149
179
  const _secretKey = decodeBase64(mySecretKey);
150
180
  const curveSecret = ed2curve.convertSecretKey(_secretKey);
@@ -159,12 +189,17 @@ function boxDataWithKeys(data, toPublicBoxKey, mySecretKey) {
159
189
  fromPublicKey: encodeBase64(boxKeyPair.publicKey),
160
190
  };
161
191
  }
192
+ /** Narrowing guard: value looks like an {@link IDataBox} envelope. */
162
193
  function isBoxedData(data) {
163
194
  return (typeof data === "object" &&
164
195
  typeof data.contents === "string" &&
165
196
  typeof data.nonce === "string" &&
166
197
  typeof data.fromPublicKey === "string");
167
198
  }
199
+ /**
200
+ * Decrypts a box from {@link boxDataWithKeys} using the recipient’s Ed25519 secret (same format as {@link newKeys}).
201
+ * @throws If decryption or authentication fails
202
+ */
168
203
  function openBoxWithSecretKey(box, mySecretKey) {
169
204
  const _secretKey = decodeBase64(mySecretKey);
170
205
  const curveSecret = ed2curve.convertSecretKey(_secretKey);
@@ -196,14 +231,20 @@ function decryptString(data, secretKey) {
196
231
  }
197
232
  return (0, tweetnacl_util_1.encodeUTF8)(decryptedData);
198
233
  }
234
+ /** JSON-serializes `data` then NaCl `secretbox` with a random nonce; returns base64 payload `~` base64 nonce. */
199
235
  function encryptData(data, secretKey) {
200
236
  const _data = (0, serial_json_1.toJSONString)(data);
201
237
  return encryptString(_data, secretKey);
202
238
  }
239
+ /** Inverse of {@link encryptData}. Returns `null` if secretbox open fails. */
203
240
  function decryptData(encryptedData, secretKey) {
204
241
  const _data = decryptString(encryptedData, secretKey);
205
242
  return (0, serial_json_1.fromJSONString)(_data);
206
243
  }
244
+ /**
245
+ * Strips any existing `signature`, signs a shallow copy of `obj`, and sets `signature` to `publicKey:detachedSig`.
246
+ * @returns Same shape as `obj` with string `signature` suitable for {@link verifyObjectSignature}
247
+ */
207
248
  function addSignatureToObject(obj, secretKey) {
208
249
  obj = { ...obj };
209
250
  delete obj.signature;
@@ -212,7 +253,8 @@ function addSignatureToObject(obj, secretKey) {
212
253
  return { ...obj, signature: objSignature };
213
254
  }
214
255
  /**
215
- * Will throw if the signature is invalid
256
+ * Ensures `signature` matches the rest of the object via {@link openSignedObject}.
257
+ * @throws If there is no signature or verification fails
216
258
  */
217
259
  function verifyObjectSignature(objectWithSignature) {
218
260
  if (!objectWithSignature.signature) {
@@ -228,6 +270,7 @@ function verifyObjectSignature(objectWithSignature) {
228
270
  };
229
271
  openSignedObject(signedObject); // will throw if invalid
230
272
  }
273
+ /** True if {@link verifyObjectSignature} would succeed. */
231
274
  function isObjectSignatureValid(objectWithSignature) {
232
275
  try {
233
276
  verifyObjectSignature(objectWithSignature);
@@ -237,6 +280,9 @@ function isObjectSignatureValid(objectWithSignature) {
237
280
  }
238
281
  return true;
239
282
  }
283
+ /**
284
+ * Parses the Ed25519 public key prefix from a `publicKey:signature` field, or `undefined` if malformed.
285
+ */
240
286
  function getPublicKeyFromObjectSignature(objectWithSignature) {
241
287
  const parts = objectWithSignature.signature?.split(":");
242
288
  if (!parts || parts.length !== 2) {
@@ -1,5 +1,16 @@
1
+ /** True for plain object literals (excludes array, Date, and null). */
1
2
  export declare function isObject(x: any): x is Record<string, any>;
3
+ /**
4
+ * Clones a value into a JSON-serializable tree: Dates, Buffers, cycles, `undefined`, `NaN`, RegExp, etc. use sentinel strings.
5
+ * Shared references are preserved with `__duplicate_ref_*` and `__this_ref` markers for {@link fromJSON}.
6
+ */
2
7
  export declare function toJSON(obj: any): any;
8
+ /**
9
+ * Reverses {@link toJSON}: restores special values, shared references, and keys escaped with `__DOLLAR_`.
10
+ * @param _externalReferences Reserved for future use (function revival, etc.)
11
+ */
3
12
  export declare function fromJSON(obj: any, _externalReferences?: any): any;
13
+ /** `JSON.stringify` of {@link toJSON} (stable, extended types). */
4
14
  export declare function toJSONString(obj: any): string;
15
+ /** `JSON.parse` then {@link fromJSON}. */
5
16
  export declare function fromJSONString(str: string): any;
@@ -6,9 +6,14 @@ exports.fromJSON = fromJSON;
6
6
  exports.toJSONString = toJSONString;
7
7
  exports.fromJSONString = fromJSONString;
8
8
  const _ = require("lodash");
9
+ /** True for plain object literals (excludes array, Date, and null). */
9
10
  function isObject(x) {
10
11
  return _.isObject(x) && !_.isArray(x) && !_.isDate(x) && x !== null;
11
12
  }
13
+ /**
14
+ * Clones a value into a JSON-serializable tree: Dates, Buffers, cycles, `undefined`, `NaN`, RegExp, etc. use sentinel strings.
15
+ * Shared references are preserved with `__duplicate_ref_*` and `__this_ref` markers for {@link fromJSON}.
16
+ */
12
17
  function toJSON(obj) {
13
18
  if (!_.isObject(obj)) {
14
19
  return obj;
@@ -95,6 +100,10 @@ function toJSON(obj) {
95
100
  obj = recurse(obj);
96
101
  return obj;
97
102
  }
103
+ /**
104
+ * Reverses {@link toJSON}: restores special values, shared references, and keys escaped with `__DOLLAR_`.
105
+ * @param _externalReferences Reserved for future use (function revival, etc.)
106
+ */
98
107
  function fromJSON(obj, _externalReferences) {
99
108
  var dup_refs = {};
100
109
  function recurse(obj) {
@@ -185,9 +194,11 @@ function fromJSON(obj, _externalReferences) {
185
194
  obj = recurse(obj);
186
195
  return obj;
187
196
  }
197
+ /** `JSON.stringify` of {@link toJSON} (stable, extended types). */
188
198
  function toJSONString(obj) {
189
199
  return JSON.stringify(toJSON(obj));
190
200
  }
201
+ /** `JSON.parse` then {@link fromJSON}. */
191
202
  function fromJSONString(str) {
192
203
  return fromJSON(JSON.parse(str));
193
204
  }
package/dist/utils.d.ts CHANGED
@@ -1,29 +1,76 @@
1
1
  import type { ITableMetaData } from "./data/orm";
2
2
  import { type IDeviceConnection } from "./types/peer-device";
3
+ /** Builds a random string of base-36 characters with unbiased distribution (tweetnacl-backed). */
3
4
  export declare function cryptoRandomString(length: number): string;
5
+ /**
6
+ * Creates a new 25-character peer id: base-36 time prefix (10 chars) + random suffix (15 chars).
7
+ * Sort order correlates with creation time. Use {@link isid} to validate user-provided values.
8
+ */
4
9
  export declare function newid(): string;
10
+ /** Lexicographic lower bound for valid peer ids (epoch). */
5
11
  export declare const MIN_ID: string;
12
+ /** Lexicographic upper bound for valid peer ids (far future). */
6
13
  export declare const MAX_ID: string;
14
+ /**
15
+ * Returns whether `id` is a 25-char base-36 string whose embedded time is not in the future (5 min skew allowed).
16
+ * @param id Candidate id (coerced to string)
17
+ */
7
18
  export declare function isid(id: any): boolean;
19
+ /** Returns the `Date.now()`-compatible millisecond time encoded in the first 10 base-36 characters of a peer id. */
8
20
  export declare function idTime(id: string): number;
21
+ /** Interprets a peer id’s time prefix as a `Date` (see {@link idTime}). */
9
22
  export declare function idDate(id: string): Date;
10
23
  /**
11
- * This returns the random number as two parts to prevent loss of precision when converting to large numbers
24
+ * Returns the 15-character random suffix of a peer id as two base-36 integers so large values stay exact in JS.
25
+ * @param id A 25-character peer id from {@link newid}
12
26
  */
13
27
  export declare function idRandNums(id: string): [number, number];
28
+ /** Fast non-cryptographic 32-bit string hash (sign-insensitive) for display keys and bucketing. */
14
29
  export declare function simpleHash(str: string): number;
30
+ /** Like TypeScript’s `Partial` for specific keys: required keys in `K` become optional. */
15
31
  export type Optional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
32
+ /** `simpleHash` of JSON-stable stringification of an object. */
16
33
  export declare function simpleObjectHash(obj: any): number;
34
+ /** Resolves after `ms` milliseconds (0 yields a microtask-yield on most runtimes). */
17
35
  export declare function sleep(ms?: number): Promise<void>;
36
+ /** Turns `fooBar` into `Foo Bar` for labels (also replaces `_` with space). */
18
37
  export declare function camelCaseToSpaces(s?: string): string;
38
+ /** Like {@link camelCaseToSpaces} but lowercased and joined with hyphens (kebab-case). */
19
39
  export declare function camelCaseToHyphens(s?: string): string;
40
+ /** USD currency formatter with two fraction digits. */
20
41
  export declare const moneyFormatter: Intl.NumberFormat;
42
+ /**
43
+ * Formats a number as USD. Uses {@link moneyFormatter} when `precision` is 2; otherwise builds a custom `Intl` formatter.
44
+ * @param value Amount in major currency units
45
+ * @param precision Decimal places (default 2)
46
+ */
21
47
  export declare function formatMoney(value: number, precision?: number): string;
48
+ /**
49
+ * Caches the in-flight `Promise` per serialized argument tuple. Re-invoking with the same args returns the same promise.
50
+ * When `cacheTtl` is set, the cache entry is removed after that many ms after completion.
51
+ */
22
52
  export declare function memoizePromise<F extends (...args: any[]) => Promise<any>>(fn: F, opts?: {
23
53
  cacheTtl?: number;
24
54
  }): F;
55
+ /**
56
+ * Debounces per distinct argument list: each unique `JSON.stringify(args)` gets its own debounced function (lodash debounce).
57
+ * @param wait Debounce wait in ms (default 300)
58
+ * @throws If the internal map is missing an entry (should not happen)
59
+ */
25
60
  export declare function debounceByArgs<F extends (...args: any[]) => any>(fn: F, wait?: number): F;
61
+ /**
62
+ * Monotonic-ish high-resolution time when `performance` exists; otherwise `Date.now()`.
63
+ * Uses `timeOrigin + now()` in browsers; suitable for relative timing, not wall-clock.
64
+ */
26
65
  export declare function getTimestamp(): number;
66
+ /**
67
+ * Runs `fn` with adaptive timeout from {@link IDeviceConnection.latencyMs}, retrying on error or until the op finishes.
68
+ * Updates `connection` latency and error rate from outcomes.
69
+ * @param opts.timeout Clamped timeout; defaults to {@link PeerDeviceConsts} min/max
70
+ * @param opts.retriesOnError Max error retries
71
+ * @param opts.retriesOnTimeout Max “timed out” races before giving up
72
+ * @throws Last error, timeout exhaustion, or if the connection is closed
73
+ */
27
74
  export declare function retryOnErrorOrTimeout<T>({ fn, connection, opts, }: {
28
75
  fn: () => Promise<T>;
29
76
  connection: IDeviceConnection;
@@ -34,6 +81,7 @@ export declare function retryOnErrorOrTimeout<T>({ fn, connection, opts, }: {
34
81
  };
35
82
  }): Promise<T>;
36
83
  /**
37
- * Table name is "name_id" if `id` is present, otherwise just "name"
84
+ * Physical table name: `"name_id"` when `tableId` is set, else `name`.
85
+ * @param metaData Table metadata from the ORM layer
38
86
  */
39
87
  export declare function getFullTableName(metaData: ITableMetaData): string;
package/dist/utils.js CHANGED
@@ -22,6 +22,7 @@ const _ = require("lodash");
22
22
  const nacl = require("tweetnacl");
23
23
  const peer_device_1 = require("./types/peer-device");
24
24
  const stableStringify = require("fast-json-stable-stringify");
25
+ /** Builds a random string of base-36 characters with unbiased distribution (tweetnacl-backed). */
25
26
  function cryptoRandomString(length) {
26
27
  let s = "";
27
28
  let r = nacl.randomBytes(length + 6);
@@ -42,6 +43,10 @@ function cryptoRandomString(length) {
42
43
  }
43
44
  return s.substring(0, length);
44
45
  }
46
+ /**
47
+ * Creates a new 25-character peer id: base-36 time prefix (10 chars) + random suffix (15 chars).
48
+ * Sort order correlates with creation time. Use {@link isid} to validate user-provided values.
49
+ */
45
50
  function newid() {
46
51
  // modeled after mongo ids, timestamp + counter + random but we're going to skip counter and have bigger random
47
52
  // people can switch to using a counter + random later if they want (or do something else with the random part).
@@ -64,8 +69,14 @@ function newid() {
64
69
  const time = Date.now().toString(36).padStart(10, "0"); // e.g: "00kq6xh45f", length == 10
65
70
  return time + cryptoRandomString(15);
66
71
  }
72
+ /** Lexicographic lower bound for valid peer ids (epoch). */
67
73
  exports.MIN_ID = "0".repeat(25); // 1970
74
+ /** Lexicographic upper bound for valid peer ids (far future). */
68
75
  exports.MAX_ID = `f55n5nmuua${"z".repeat(15)}`; // 50k years from now
76
+ /**
77
+ * Returns whether `id` is a 25-char base-36 string whose embedded time is not in the future (5 min skew allowed).
78
+ * @param id Candidate id (coerced to string)
79
+ */
69
80
  function isid(id) {
70
81
  id = String(id);
71
82
  const idMatch = Boolean(/^[0-9a-z]{25}$/i.exec(id));
@@ -76,21 +87,25 @@ function isid(id) {
76
87
  }
77
88
  return false;
78
89
  }
90
+ /** Returns the `Date.now()`-compatible millisecond time encoded in the first 10 base-36 characters of a peer id. */
79
91
  function idTime(id) {
80
92
  const time36 = id.substr(0, 10);
81
93
  return Number.parseInt(time36, 36);
82
94
  }
95
+ /** Interprets a peer id’s time prefix as a `Date` (see {@link idTime}). */
83
96
  function idDate(id) {
84
97
  return new Date(idTime(id));
85
98
  }
86
99
  /**
87
- * This returns the random number as two parts to prevent loss of precision when converting to large numbers
100
+ * Returns the 15-character random suffix of a peer id as two base-36 integers so large values stay exact in JS.
101
+ * @param id A 25-character peer id from {@link newid}
88
102
  */
89
103
  function idRandNums(id) {
90
104
  const numPart1 = id.substr(10, 8);
91
105
  const numPart2 = id.substr(18, 7);
92
106
  return [Number.parseInt(numPart1, 36), Number.parseInt(numPart2, 36)];
93
107
  }
108
+ /** Fast non-cryptographic 32-bit string hash (sign-insensitive) for display keys and bucketing. */
94
109
  function simpleHash(str) {
95
110
  let hash = 0;
96
111
  for (let i = 0; i < str.length; i++) {
@@ -100,12 +115,15 @@ function simpleHash(str) {
100
115
  }
101
116
  return Math.abs(hash);
102
117
  }
118
+ /** `simpleHash` of JSON-stable stringification of an object. */
103
119
  function simpleObjectHash(obj) {
104
120
  return simpleHash(stableStringify(obj));
105
121
  }
122
+ /** Resolves after `ms` milliseconds (0 yields a microtask-yield on most runtimes). */
106
123
  function sleep(ms = 0) {
107
124
  return new Promise((resolve) => setTimeout(resolve, ms));
108
125
  }
126
+ /** Turns `fooBar` into `Foo Bar` for labels (also replaces `_` with space). */
109
127
  function camelCaseToSpaces(s = "") {
110
128
  s = s.replace(/([a-z])([A-Z])/g, "$1 $2");
111
129
  // s = s.replace(/(GL)([A-Z])/g, '$1 $2'); // anything like GLAccounts, GLBatches, etc.
@@ -113,16 +131,23 @@ function camelCaseToSpaces(s = "") {
113
131
  s = s[0]?.toUpperCase() + s.substr(1);
114
132
  return s;
115
133
  }
134
+ /** Like {@link camelCaseToSpaces} but lowercased and joined with hyphens (kebab-case). */
116
135
  function camelCaseToHyphens(s = "") {
117
136
  s = camelCaseToSpaces(s);
118
137
  return s.split(" ").join("-").toLowerCase();
119
138
  }
139
+ /** USD currency formatter with two fraction digits. */
120
140
  exports.moneyFormatter = new Intl.NumberFormat("en-US", {
121
141
  style: "currency",
122
142
  currency: "USD",
123
143
  minimumFractionDigits: 2,
124
144
  maximumFractionDigits: 2,
125
145
  });
146
+ /**
147
+ * Formats a number as USD. Uses {@link moneyFormatter} when `precision` is 2; otherwise builds a custom `Intl` formatter.
148
+ * @param value Amount in major currency units
149
+ * @param precision Decimal places (default 2)
150
+ */
126
151
  function formatMoney(value, precision = 2) {
127
152
  if (precision === 2) {
128
153
  return exports.moneyFormatter.format(value);
@@ -135,6 +160,10 @@ function formatMoney(value, precision = 2) {
135
160
  });
136
161
  return _moneyFormatter.format(value);
137
162
  }
163
+ /**
164
+ * Caches the in-flight `Promise` per serialized argument tuple. Re-invoking with the same args returns the same promise.
165
+ * When `cacheTtl` is set, the cache entry is removed after that many ms after completion.
166
+ */
138
167
  function memoizePromise(fn, opts) {
139
168
  const cache = new Map();
140
169
  const memoized = (...args) => {
@@ -156,6 +185,11 @@ function memoizePromise(fn, opts) {
156
185
  };
157
186
  return memoized;
158
187
  }
188
+ /**
189
+ * Debounces per distinct argument list: each unique `JSON.stringify(args)` gets its own debounced function (lodash debounce).
190
+ * @param wait Debounce wait in ms (default 300)
191
+ * @throws If the internal map is missing an entry (should not happen)
192
+ */
159
193
  function debounceByArgs(fn, wait = 300) {
160
194
  const debouncedFunctions = new Map();
161
195
  const debounced = (...args) => {
@@ -172,6 +206,10 @@ function debounceByArgs(fn, wait = 300) {
172
206
  };
173
207
  return debounced;
174
208
  }
209
+ /**
210
+ * Monotonic-ish high-resolution time when `performance` exists; otherwise `Date.now()`.
211
+ * Uses `timeOrigin + now()` in browsers; suitable for relative timing, not wall-clock.
212
+ */
175
213
  function getTimestamp() {
176
214
  // check if in node.js environment
177
215
  if (typeof performance === "undefined" || !performance.timeOrigin) {
@@ -180,6 +218,14 @@ function getTimestamp() {
180
218
  }
181
219
  return performance.timeOrigin + performance.now();
182
220
  }
221
+ /**
222
+ * Runs `fn` with adaptive timeout from {@link IDeviceConnection.latencyMs}, retrying on error or until the op finishes.
223
+ * Updates `connection` latency and error rate from outcomes.
224
+ * @param opts.timeout Clamped timeout; defaults to {@link PeerDeviceConsts} min/max
225
+ * @param opts.retriesOnError Max error retries
226
+ * @param opts.retriesOnTimeout Max “timed out” races before giving up
227
+ * @throws Last error, timeout exhaustion, or if the connection is closed
228
+ */
183
229
  async function retryOnErrorOrTimeout({ fn, connection, opts = {}, }) {
184
230
  const timeoutMin = opts.timeout ?? peer_device_1.PeerDeviceConsts.TIMEOUT_MIN;
185
231
  const timeoutMax = opts.timeout ?? peer_device_1.PeerDeviceConsts.TIMEOUT_MAX;
@@ -244,7 +290,8 @@ async function retryOnErrorOrTimeout({ fn, connection, opts = {}, }) {
244
290
  }
245
291
  }
246
292
  /**
247
- * Table name is "name_id" if `id` is present, otherwise just "name"
293
+ * Physical table name: `"name_id"` when `tableId` is set, else `name`.
294
+ * @param metaData Table metadata from the ORM layer
248
295
  */
249
296
  function getFullTableName(metaData) {
250
297
  return [metaData.name, metaData.tableId].filter((v) => v && v.length > 0).join("_");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peers-app/peers-sdk",
3
- "version": "0.15.4",
3
+ "version": "0.15.5",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+https://github.com/peers-app/peers-sdk.git"