@lightsparkdev/core 1.0.9 → 1.0.10

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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # @lightsparkdev/core
2
2
 
3
+ ## 1.0.10
4
+
5
+ ### Patch Changes
6
+
7
+ - aefe52c: Update tsup to latest
8
+ - 09dfcee: Prevent ts compile of test files for builds and update lint configuration
9
+
3
10
  ## 1.0.9
4
11
 
5
12
  ### Patch Changes
@@ -816,39 +816,38 @@ function sleep(ms) {
816
816
  function getDefaultMaxPollsError() {
817
817
  return new Error("pollUntil: Max polls reached");
818
818
  }
819
- function pollUntil(asyncFn, getValue, maxPolls = 60, pollIntervalMs = 500, ignoreErrors = false, getMaxPollsError = getDefaultMaxPollsError) {
820
- return new Promise((resolve, reject) => {
821
- let polls = 0;
822
- let stopPolling = false;
823
- (async function() {
824
- while (!stopPolling) {
825
- polls += 1;
826
- if (polls > maxPolls) {
827
- stopPolling = true;
828
- const maxPollsError = getMaxPollsError(maxPolls);
829
- reject(maxPollsError);
830
- break;
831
- }
832
- try {
833
- const asyncResult = await asyncFn();
834
- const result = getValue(asyncResult, {
835
- stopPolling: false,
836
- value: null
837
- });
838
- if (result.stopPolling) {
839
- stopPolling = true;
840
- resolve(result.value);
841
- }
842
- } catch (e) {
843
- if (!ignoreErrors || isFunction_default(ignoreErrors) && !ignoreErrors(e)) {
844
- stopPolling = true;
845
- reject(e);
846
- }
847
- }
848
- await sleep(pollIntervalMs);
819
+ async function pollUntil(asyncFn, getValue, maxPolls = 60, pollIntervalMs = 500, ignoreErrors = false, getMaxPollsError = getDefaultMaxPollsError) {
820
+ let polls = 0;
821
+ let stopPolling = false;
822
+ let result = {
823
+ stopPolling: false,
824
+ value: null
825
+ };
826
+ while (!stopPolling) {
827
+ polls += 1;
828
+ if (polls > maxPolls) {
829
+ stopPolling = true;
830
+ const maxPollsError = getMaxPollsError(maxPolls);
831
+ throw maxPollsError;
832
+ }
833
+ try {
834
+ const asyncResult = await asyncFn();
835
+ result = getValue(asyncResult, {
836
+ stopPolling: false,
837
+ value: null
838
+ });
839
+ if (result.stopPolling) {
840
+ stopPolling = true;
849
841
  }
850
- })();
851
- });
842
+ } catch (e) {
843
+ if (!ignoreErrors || isFunction_default(ignoreErrors) && !ignoreErrors(e)) {
844
+ stopPolling = true;
845
+ throw e;
846
+ }
847
+ }
848
+ await sleep(pollIntervalMs);
849
+ }
850
+ return result.value;
852
851
  }
853
852
 
854
853
  // src/utils/types.ts
package/dist/index.cjs CHANGED
@@ -109,14 +109,14 @@ var LightsparkAuthException_default = LightsparkAuthException;
109
109
 
110
110
  // src/auth/StubAuthProvider.ts
111
111
  var StubAuthProvider = class {
112
- async addAuthHeaders(headers) {
113
- return headers;
112
+ addAuthHeaders(headers) {
113
+ return Promise.resolve(headers);
114
114
  }
115
- async isAuthorized() {
116
- return false;
115
+ isAuthorized() {
116
+ return Promise.resolve(false);
117
117
  }
118
- async addWsConnectionParams(params) {
119
- return params;
118
+ addWsConnectionParams(params) {
119
+ return Promise.resolve(params);
120
120
  }
121
121
  };
122
122
 
@@ -267,7 +267,7 @@ var decrypt = async (header_json, ciphertext, password) => {
267
267
  if (header.v < 0 || header.v > 4) {
268
268
  throw new LightsparkException_default(
269
269
  "DecryptionError",
270
- "Unknown version ".concat(header.v)
270
+ `Unknown version ${header.v}`
271
271
  );
272
272
  }
273
273
  const cryptoImpl = await getCrypto();
@@ -1161,39 +1161,38 @@ function sleep(ms) {
1161
1161
  function getDefaultMaxPollsError() {
1162
1162
  return new Error("pollUntil: Max polls reached");
1163
1163
  }
1164
- function pollUntil(asyncFn, getValue, maxPolls = 60, pollIntervalMs = 500, ignoreErrors = false, getMaxPollsError = getDefaultMaxPollsError) {
1165
- return new Promise((resolve, reject) => {
1166
- let polls = 0;
1167
- let stopPolling = false;
1168
- (async function() {
1169
- while (!stopPolling) {
1170
- polls += 1;
1171
- if (polls > maxPolls) {
1172
- stopPolling = true;
1173
- const maxPollsError = getMaxPollsError(maxPolls);
1174
- reject(maxPollsError);
1175
- break;
1176
- }
1177
- try {
1178
- const asyncResult = await asyncFn();
1179
- const result = getValue(asyncResult, {
1180
- stopPolling: false,
1181
- value: null
1182
- });
1183
- if (result.stopPolling) {
1184
- stopPolling = true;
1185
- resolve(result.value);
1186
- }
1187
- } catch (e) {
1188
- if (!ignoreErrors || isFunction_default(ignoreErrors) && !ignoreErrors(e)) {
1189
- stopPolling = true;
1190
- reject(e);
1191
- }
1192
- }
1193
- await sleep(pollIntervalMs);
1164
+ async function pollUntil(asyncFn, getValue, maxPolls = 60, pollIntervalMs = 500, ignoreErrors = false, getMaxPollsError = getDefaultMaxPollsError) {
1165
+ let polls = 0;
1166
+ let stopPolling = false;
1167
+ let result = {
1168
+ stopPolling: false,
1169
+ value: null
1170
+ };
1171
+ while (!stopPolling) {
1172
+ polls += 1;
1173
+ if (polls > maxPolls) {
1174
+ stopPolling = true;
1175
+ const maxPollsError = getMaxPollsError(maxPolls);
1176
+ throw maxPollsError;
1177
+ }
1178
+ try {
1179
+ const asyncResult = await asyncFn();
1180
+ result = getValue(asyncResult, {
1181
+ stopPolling: false,
1182
+ value: null
1183
+ });
1184
+ if (result.stopPolling) {
1185
+ stopPolling = true;
1186
+ }
1187
+ } catch (e) {
1188
+ if (!ignoreErrors || isFunction_default(ignoreErrors) && !ignoreErrors(e)) {
1189
+ stopPolling = true;
1190
+ throw e;
1194
1191
  }
1195
- })();
1196
- });
1192
+ }
1193
+ await sleep(pollIntervalMs);
1194
+ }
1195
+ return result.value;
1197
1196
  }
1198
1197
 
1199
1198
  // src/utils/types.ts
@@ -1302,7 +1301,7 @@ var Logger = class {
1302
1301
  loggingEnabled = false;
1303
1302
  constructor(loggerContext, getLoggingEnabled) {
1304
1303
  this.context = loggerContext;
1305
- this.updateLoggingEnabled(getLoggingEnabled);
1304
+ void this.updateLoggingEnabled(getLoggingEnabled);
1306
1305
  }
1307
1306
  async updateLoggingEnabled(getLoggingEnabled) {
1308
1307
  if (getLoggingEnabled) {
@@ -1500,7 +1499,7 @@ var Requester = class {
1500
1499
  nonce,
1501
1500
  expires_at: expiration
1502
1501
  };
1503
- const key = await this.nodeKeyCache.getKey(signingNodeId);
1502
+ const key = this.nodeKeyCache.getKey(signingNodeId);
1504
1503
  if (!key) {
1505
1504
  throw new LightsparkSigningException_default(
1506
1505
  "Missing node of encrypted_signing_private_key"
@@ -0,0 +1,165 @@
1
+ import { Observable } from 'zen-observable-ts';
2
+ export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, DeepPartial, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode } from './utils/index.cjs';
3
+
4
+ type Headers = Record<string, string>;
5
+ type WsConnectionParams = Record<string, unknown>;
6
+ interface AuthProvider {
7
+ addAuthHeaders(headers: Headers): Promise<Headers>;
8
+ isAuthorized(): Promise<boolean>;
9
+ addWsConnectionParams(params: WsConnectionParams): Promise<WsConnectionParams>;
10
+ }
11
+
12
+ declare class LightsparkException extends Error {
13
+ code: string;
14
+ message: string;
15
+ extraInfo: Record<string, unknown> | undefined;
16
+ constructor(code: string, message: string, extraInfo?: Record<string, unknown>);
17
+ }
18
+
19
+ declare class LightsparkAuthException extends LightsparkException {
20
+ constructor(message: string, extraInfo?: Record<string, unknown>);
21
+ }
22
+
23
+ declare class StubAuthProvider implements AuthProvider {
24
+ addAuthHeaders(headers: Headers): Promise<Headers>;
25
+ isAuthorized(): Promise<boolean>;
26
+ addWsConnectionParams(params: WsConnectionParams): Promise<WsConnectionParams>;
27
+ }
28
+
29
+ declare const ConfigKeys: {
30
+ readonly LoggingEnabled: "lightspark-logging-enabled";
31
+ readonly ConsoleToolsEnabled: "lightspark-console-tools-enabled";
32
+ };
33
+ type ConfigKeys = (typeof ConfigKeys)[keyof typeof ConfigKeys];
34
+ declare const getLocalStorageConfigItem: (key: ConfigKeys) => boolean;
35
+
36
+ declare class LightsparkSigningException extends LightsparkException {
37
+ constructor(message: string, extraInfo?: Record<string, unknown>);
38
+ }
39
+
40
+ type GeneratedKeyPair = {
41
+ publicKey: CryptoKey | string;
42
+ privateKey: CryptoKey | string;
43
+ keyAlias?: string;
44
+ };
45
+ type CryptoInterface = {
46
+ decryptSecretWithNodePassword: (cipher: string, encryptedSecret: string, nodePassword: string) => Promise<ArrayBuffer | null>;
47
+ generateSigningKeyPair: () => Promise<GeneratedKeyPair>;
48
+ serializeSigningKey: (key: CryptoKey | string, format: "pkcs8" | "spki") => Promise<ArrayBuffer>;
49
+ getNonce: () => Promise<number>;
50
+ sign: (keyOrAlias: CryptoKey | string, data: Uint8Array) => Promise<ArrayBuffer>;
51
+ importPrivateSigningKey: (keyData: Uint8Array) => Promise<CryptoKey | string>;
52
+ };
53
+ declare function decryptSecretWithNodePassword(cipher: string, encryptedSecret: string, nodePassword: string): Promise<ArrayBuffer | null>;
54
+ declare const DefaultCrypto: {
55
+ decryptSecretWithNodePassword: typeof decryptSecretWithNodePassword;
56
+ generateSigningKeyPair: () => Promise<GeneratedKeyPair>;
57
+ serializeSigningKey: (key: CryptoKey | string, format: "pkcs8" | "spki") => Promise<ArrayBuffer>;
58
+ getNonce: () => Promise<number>;
59
+ sign: (keyOrAlias: CryptoKey | string, data: Uint8Array) => Promise<ArrayBuffer>;
60
+ importPrivateSigningKey: (keyData: Uint8Array) => Promise<CryptoKey | string>;
61
+ };
62
+
63
+ type OnlyKey = {
64
+ key: string;
65
+ alias?: never;
66
+ };
67
+ type OnlyAlias = {
68
+ key?: never;
69
+ alias: string;
70
+ };
71
+ type KeyOrAliasType = OnlyKey | OnlyAlias;
72
+ declare const KeyOrAlias: {
73
+ key: (key: string) => OnlyKey;
74
+ alias: (alias: string) => OnlyAlias;
75
+ };
76
+
77
+ interface Alias {
78
+ alias: string;
79
+ }
80
+ declare abstract class SigningKey {
81
+ readonly type: SigningKeyType;
82
+ constructor(type: SigningKeyType);
83
+ abstract sign(data: Uint8Array): Promise<ArrayBuffer>;
84
+ }
85
+ declare class RSASigningKey extends SigningKey {
86
+ private readonly privateKey;
87
+ private readonly cryptoImpl;
88
+ constructor(privateKey: CryptoKey | Alias, cryptoImpl: CryptoInterface);
89
+ sign(data: Uint8Array): Promise<ArrayBuffer>;
90
+ }
91
+ declare class Secp256k1SigningKey extends SigningKey {
92
+ private readonly privateKey;
93
+ constructor(privateKey: string);
94
+ sign(data: Uint8Array): Promise<Uint8Array>;
95
+ }
96
+
97
+ declare enum SigningKeyType {
98
+ RSASigningKey = "RSASigningKey",
99
+ Secp256k1SigningKey = "Secp256k1SigningKey"
100
+ }
101
+
102
+ declare class NodeKeyCache {
103
+ private readonly cryptoImpl;
104
+ private idToKey;
105
+ constructor(cryptoImpl?: CryptoInterface);
106
+ loadKey(id: string, keyOrAlias: KeyOrAliasType, signingKeyType: SigningKeyType): Promise<SigningKey | null>;
107
+ getKey(id: string): SigningKey | undefined;
108
+ hasKey(id: string): boolean;
109
+ private stripPemTags;
110
+ }
111
+
112
+ type GetLoggingEnabled = (() => Promise<boolean> | boolean) | undefined;
113
+ declare class Logger {
114
+ context: string;
115
+ loggingEnabled: boolean;
116
+ constructor(loggerContext: string, getLoggingEnabled?: GetLoggingEnabled);
117
+ updateLoggingEnabled(getLoggingEnabled: GetLoggingEnabled): Promise<void>;
118
+ info(message: string, ...rest: unknown[]): void;
119
+ }
120
+
121
+ type Query<T> = {
122
+ /** The string representation of the query payload for graphQL. **/
123
+ queryPayload: string;
124
+ /** The variables that will be passed to the query. **/
125
+ variables?: {
126
+ [key: string]: unknown;
127
+ };
128
+ /** The function that will be called to construct the object from the response. **/
129
+ constructObject: (rawData: any) => T;
130
+ /** The id of the node that will be used to sign the query. **/
131
+ signingNodeId?: string;
132
+ /** True if auth headers should be omitted for this query. **/
133
+ skipAuth?: boolean;
134
+ };
135
+
136
+ declare class Requester {
137
+ private readonly nodeKeyCache;
138
+ private readonly schemaEndpoint;
139
+ private readonly sdkUserAgent;
140
+ private readonly authProvider;
141
+ private readonly baseUrl;
142
+ private readonly cryptoImpl;
143
+ private readonly wsClient;
144
+ constructor(nodeKeyCache: NodeKeyCache, schemaEndpoint: string, sdkUserAgent: string, authProvider?: AuthProvider, baseUrl?: string, cryptoImpl?: CryptoInterface);
145
+ executeQuery<T>(query: Query<T>): Promise<T | null>;
146
+ subscribe<T>(queryPayload: string, variables?: {
147
+ [key: string]: unknown;
148
+ }): Observable<{
149
+ data: T;
150
+ }>;
151
+ makeRawRequest(queryPayload: string, variables?: {
152
+ [key: string]: unknown;
153
+ }, signingNodeId?: string | undefined, skipAuth?: boolean): Promise<any>;
154
+ private getSdkUserAgent;
155
+ private stripProtocol;
156
+ private addSigningDataIfNeeded;
157
+ }
158
+
159
+ declare enum ServerEnvironment {
160
+ PRODUCTION = "production",
161
+ DEV = "dev"
162
+ }
163
+ declare const apiDomainForEnvironment: (environment: ServerEnvironment) => string;
164
+
165
+ export { AuthProvider, ConfigKeys, CryptoInterface, DefaultCrypto, GeneratedKeyPair, KeyOrAlias, KeyOrAliasType, LightsparkAuthException, LightsparkException, LightsparkSigningException, Logger, NodeKeyCache, Query, RSASigningKey, Requester, Secp256k1SigningKey, ServerEnvironment, SigningKey, SigningKeyType, StubAuthProvider, apiDomainForEnvironment, getLocalStorageConfigItem };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { Observable } from 'zen-observable-ts';
2
- export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode } from './utils/index.js';
2
+ export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, DeepPartial, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode } from './utils/index.js';
3
3
 
4
4
  type Headers = Record<string, string>;
5
5
  type WsConnectionParams = Record<string, unknown>;
@@ -150,7 +150,7 @@ declare class Requester {
150
150
  }>;
151
151
  makeRawRequest(queryPayload: string, variables?: {
152
152
  [key: string]: unknown;
153
- }, signingNodeId?: string | undefined, skipAuth?: boolean): Promise<any | null>;
153
+ }, signingNodeId?: string | undefined, skipAuth?: boolean): Promise<any>;
154
154
  private getSdkUserAgent;
155
155
  private stripProtocol;
156
156
  private addSigningDataIfNeeded;
package/dist/index.js CHANGED
@@ -35,7 +35,7 @@ import {
35
35
  separateCurrencyStrParts,
36
36
  sleep,
37
37
  urlsafe_b64decode
38
- } from "./chunk-UU6SHVGX.js";
38
+ } from "./chunk-MAZP7ETK.js";
39
39
 
40
40
  // src/auth/LightsparkAuthException.ts
41
41
  var LightsparkAuthException = class extends LightsparkException_default {
@@ -47,14 +47,14 @@ var LightsparkAuthException_default = LightsparkAuthException;
47
47
 
48
48
  // src/auth/StubAuthProvider.ts
49
49
  var StubAuthProvider = class {
50
- async addAuthHeaders(headers) {
51
- return headers;
50
+ addAuthHeaders(headers) {
51
+ return Promise.resolve(headers);
52
52
  }
53
- async isAuthorized() {
54
- return false;
53
+ isAuthorized() {
54
+ return Promise.resolve(false);
55
55
  }
56
- async addWsConnectionParams(params) {
57
- return params;
56
+ addWsConnectionParams(params) {
57
+ return Promise.resolve(params);
58
58
  }
59
59
  };
60
60
 
@@ -162,7 +162,7 @@ var decrypt = async (header_json, ciphertext, password) => {
162
162
  if (header.v < 0 || header.v > 4) {
163
163
  throw new LightsparkException_default(
164
164
  "DecryptionError",
165
- "Unknown version ".concat(header.v)
165
+ `Unknown version ${header.v}`
166
166
  );
167
167
  }
168
168
  const cryptoImpl = await getCrypto();
@@ -394,7 +394,7 @@ var Logger = class {
394
394
  loggingEnabled = false;
395
395
  constructor(loggerContext, getLoggingEnabled) {
396
396
  this.context = loggerContext;
397
- this.updateLoggingEnabled(getLoggingEnabled);
397
+ void this.updateLoggingEnabled(getLoggingEnabled);
398
398
  }
399
399
  async updateLoggingEnabled(getLoggingEnabled) {
400
400
  if (getLoggingEnabled) {
@@ -592,7 +592,7 @@ var Requester = class {
592
592
  nonce,
593
593
  expires_at: expiration
594
594
  };
595
- const key = await this.nodeKeyCache.getKey(signingNodeId);
595
+ const key = this.nodeKeyCache.getKey(signingNodeId);
596
596
  if (!key) {
597
597
  throw new LightsparkSigningException_default(
598
598
  "Missing node of encrypted_signing_private_key"
@@ -886,39 +886,38 @@ function sleep(ms) {
886
886
  function getDefaultMaxPollsError() {
887
887
  return new Error("pollUntil: Max polls reached");
888
888
  }
889
- function pollUntil(asyncFn, getValue, maxPolls = 60, pollIntervalMs = 500, ignoreErrors = false, getMaxPollsError = getDefaultMaxPollsError) {
890
- return new Promise((resolve, reject) => {
891
- let polls = 0;
892
- let stopPolling = false;
893
- (async function() {
894
- while (!stopPolling) {
895
- polls += 1;
896
- if (polls > maxPolls) {
897
- stopPolling = true;
898
- const maxPollsError = getMaxPollsError(maxPolls);
899
- reject(maxPollsError);
900
- break;
901
- }
902
- try {
903
- const asyncResult = await asyncFn();
904
- const result = getValue(asyncResult, {
905
- stopPolling: false,
906
- value: null
907
- });
908
- if (result.stopPolling) {
909
- stopPolling = true;
910
- resolve(result.value);
911
- }
912
- } catch (e) {
913
- if (!ignoreErrors || isFunction_default(ignoreErrors) && !ignoreErrors(e)) {
914
- stopPolling = true;
915
- reject(e);
916
- }
917
- }
918
- await sleep(pollIntervalMs);
889
+ async function pollUntil(asyncFn, getValue, maxPolls = 60, pollIntervalMs = 500, ignoreErrors = false, getMaxPollsError = getDefaultMaxPollsError) {
890
+ let polls = 0;
891
+ let stopPolling = false;
892
+ let result = {
893
+ stopPolling: false,
894
+ value: null
895
+ };
896
+ while (!stopPolling) {
897
+ polls += 1;
898
+ if (polls > maxPolls) {
899
+ stopPolling = true;
900
+ const maxPollsError = getMaxPollsError(maxPolls);
901
+ throw maxPollsError;
902
+ }
903
+ try {
904
+ const asyncResult = await asyncFn();
905
+ result = getValue(asyncResult, {
906
+ stopPolling: false,
907
+ value: null
908
+ });
909
+ if (result.stopPolling) {
910
+ stopPolling = true;
919
911
  }
920
- })();
921
- });
912
+ } catch (e) {
913
+ if (!ignoreErrors || isFunction_default(ignoreErrors) && !ignoreErrors(e)) {
914
+ stopPolling = true;
915
+ throw e;
916
+ }
917
+ }
918
+ await sleep(pollIntervalMs);
919
+ }
920
+ return result.value;
922
921
  }
923
922
 
924
923
  // src/utils/types.ts
@@ -0,0 +1,223 @@
1
+ declare const b64decode: (encoded: string) => Uint8Array;
2
+ declare const urlsafe_b64decode: (encoded: string) => Uint8Array;
3
+ declare const b64encode: (data: ArrayBuffer) => string;
4
+
5
+ type SourceData = Uint8Array | string;
6
+ declare function createSha256Hash(data: SourceData): Promise<Uint8Array>;
7
+ declare function createSha256Hash(data: SourceData, asHex: true): Promise<string>;
8
+
9
+ declare const defaultCurrencyCode = "USD";
10
+ /** This enum identifies the unit of currency associated with a CurrencyAmount. **/
11
+ declare enum CurrencyUnit {
12
+ /**
13
+ * This is an enum value that represents values that could be added in the future.
14
+ * Clients should support unknown values as more of them could be added without notice.
15
+ */
16
+ FUTURE_VALUE = "FUTURE_VALUE",
17
+ /** Bitcoin is the cryptocurrency native to the Bitcoin network. It is used as the native medium for value transfer for the Lightning Network. **/
18
+ BITCOIN = "BITCOIN",
19
+ /** 0.00000001 (10e-8) Bitcoin or one hundred millionth of a Bitcoin. This is the unit most commonly used in Lightning transactions. **/
20
+ SATOSHI = "SATOSHI",
21
+ /** 0.001 Satoshi, or 10e-11 Bitcoin. We recommend using the Satoshi unit instead when possible. **/
22
+ MILLISATOSHI = "MILLISATOSHI",
23
+ /** United States Dollar. **/
24
+ USD = "USD",
25
+ /** 0.000000001 (10e-9) Bitcoin or a billionth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
26
+ NANOBITCOIN = "NANOBITCOIN",
27
+ /** 0.000001 (10e-6) Bitcoin or a millionth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
28
+ MICROBITCOIN = "MICROBITCOIN",
29
+ /** 0.001 (10e-3) Bitcoin or a thousandth of a Bitcoin. We recommend using the Satoshi unit instead when possible. **/
30
+ MILLIBITCOIN = "MILLIBITCOIN"
31
+ }
32
+ /** This object represents the value and unit for an amount of currency. **/
33
+ type CurrencyAmountType = {
34
+ /** The original numeric value for this CurrencyAmount. **/
35
+ originalValue: number;
36
+ /** The original unit of currency for this CurrencyAmount. **/
37
+ originalUnit: CurrencyUnit;
38
+ /** The unit of user's preferred currency. **/
39
+ preferredCurrencyUnit: CurrencyUnit;
40
+ /**
41
+ * The rounded numeric value for this CurrencyAmount in the very base level of user's preferred
42
+ * currency. For example, for USD, the value will be in cents.
43
+ **/
44
+ preferredCurrencyValueRounded: number;
45
+ /**
46
+ * The approximate float value for this CurrencyAmount in the very base level of user's preferred
47
+ * currency. For example, for USD, the value will be in cents.
48
+ **/
49
+ preferredCurrencyValueApprox: number;
50
+ };
51
+ declare function convertCurrencyAmountValue(fromUnit: CurrencyUnit, toUnit: CurrencyUnit, amount: number, centsPerBtc?: number): number;
52
+ declare const convertCurrencyAmount: (from: CurrencyAmountType, toUnit: CurrencyUnit) => CurrencyAmountType;
53
+ type CurrencyMap = {
54
+ sats: number;
55
+ msats: number;
56
+ btc: number;
57
+ [CurrencyUnit.BITCOIN]: number;
58
+ [CurrencyUnit.SATOSHI]: number;
59
+ [CurrencyUnit.MILLISATOSHI]: number;
60
+ [CurrencyUnit.MICROBITCOIN]: number;
61
+ [CurrencyUnit.MILLIBITCOIN]: number;
62
+ [CurrencyUnit.NANOBITCOIN]: number;
63
+ [CurrencyUnit.USD]: number;
64
+ [CurrencyUnit.FUTURE_VALUE]: number;
65
+ formatted: {
66
+ sats: string;
67
+ msats: string;
68
+ btc: string;
69
+ [CurrencyUnit.BITCOIN]: string;
70
+ [CurrencyUnit.SATOSHI]: string;
71
+ [CurrencyUnit.MILLISATOSHI]: string;
72
+ [CurrencyUnit.MILLIBITCOIN]: string;
73
+ [CurrencyUnit.MICROBITCOIN]: string;
74
+ [CurrencyUnit.NANOBITCOIN]: string;
75
+ [CurrencyUnit.USD]: string;
76
+ [CurrencyUnit.FUTURE_VALUE]: string;
77
+ };
78
+ isZero: boolean;
79
+ isLessThan: (other: CurrencyMap | CurrencyAmountObj | number) => boolean;
80
+ isGreaterThan: (other: CurrencyMap | CurrencyAmountObj | number) => boolean;
81
+ isEqualTo: (other: CurrencyMap | CurrencyAmountObj | number) => boolean;
82
+ type: "CurrencyMap";
83
+ };
84
+ type CurrencyAmountObj = {
85
+ value?: number | string | null;
86
+ unit?: CurrencyUnit;
87
+ __typename?: "CurrencyAmount";
88
+ };
89
+ type CurrencyAmountArg = CurrencyAmountObj | CurrencyAmountType | undefined | null;
90
+ declare function isCurrencyAmountObj(arg: unknown): arg is CurrencyAmountObj;
91
+ declare function isCurrencyAmount(arg: unknown): arg is CurrencyAmountType;
92
+ declare function mapCurrencyAmount(currencyAmountArg: CurrencyAmountArg, centsPerBtc?: number): CurrencyMap;
93
+ declare const isCurrencyMap: (currencyMap: unknown) => currencyMap is CurrencyMap;
94
+ declare const abbrCurrencyUnit: (unit: CurrencyUnit) => "USD" | "BTC" | "SAT" | "MSAT" | "Unsupported CurrencyUnit";
95
+ declare function formatCurrencyStr(amount: CurrencyAmountArg, maxFractionDigits?: number, compact?: boolean, showBtcSymbol?: boolean, options?: Intl.NumberFormatOptions): string;
96
+ declare function separateCurrencyStrParts(currencyStr: string): {
97
+ symbol: string;
98
+ amount: string;
99
+ };
100
+ declare function localeToCurrencySymbol(locale: string): string;
101
+
102
+ declare const isBrowser: boolean;
103
+ declare const isNode: boolean;
104
+ declare const isTest: boolean;
105
+
106
+ declare const isError: (e: unknown) => e is Error;
107
+ type ErrorWithMessage = {
108
+ message: string;
109
+ };
110
+ declare const isErrorWithMessage: (e: unknown) => e is ErrorWithMessage;
111
+ declare const getErrorMsg: (e: unknown) => string;
112
+ declare const isErrorMsg: (e: unknown, msg: string) => boolean;
113
+
114
+ declare const bytesToHex: (bytes: Uint8Array) => string;
115
+ declare const hexToBytes: (hex: string) => Uint8Array;
116
+
117
+ declare function getCurrentLocale(): string;
118
+
119
+ declare const countryCodesToCurrencyCodes: {
120
+ readonly AD: "EUR";
121
+ readonly AR: "ARS";
122
+ readonly AS: "USD";
123
+ readonly AT: "EUR";
124
+ readonly AU: "AUD";
125
+ readonly AX: "EUR";
126
+ readonly BE: "EUR";
127
+ readonly BL: "EUR";
128
+ readonly BQ: "USD";
129
+ readonly BR: "BRL";
130
+ readonly CA: "CAD";
131
+ readonly CO: "COP";
132
+ readonly CY: "EUR";
133
+ readonly DE: "EUR";
134
+ readonly EC: "USD";
135
+ readonly EE: "EUR";
136
+ readonly ES: "EUR";
137
+ readonly FI: "EUR";
138
+ readonly FM: "USD";
139
+ readonly FR: "EUR";
140
+ readonly GB: "GBP";
141
+ readonly GF: "EUR";
142
+ readonly GG: "GBP";
143
+ readonly GP: "EUR";
144
+ readonly GR: "EUR";
145
+ readonly GS: "GBP";
146
+ readonly GU: "USD";
147
+ readonly IE: "EUR";
148
+ readonly IM: "GBP";
149
+ readonly IN: "INR";
150
+ readonly IO: "USD";
151
+ readonly IT: "EUR";
152
+ readonly JE: "GBP";
153
+ readonly LT: "EUR";
154
+ readonly LU: "EUR";
155
+ readonly LV: "EUR";
156
+ readonly MC: "EUR";
157
+ readonly ME: "EUR";
158
+ readonly MF: "EUR";
159
+ readonly MH: "USD";
160
+ readonly MP: "USD";
161
+ readonly MQ: "EUR";
162
+ readonly MT: "EUR";
163
+ readonly MX: "MXN";
164
+ readonly NF: "AUD";
165
+ readonly NL: "EUR";
166
+ readonly NR: "AUD";
167
+ readonly PM: "EUR";
168
+ readonly PR: "USD";
169
+ readonly PT: "EUR";
170
+ readonly PW: "USD";
171
+ readonly RE: "EUR";
172
+ readonly SI: "EUR";
173
+ readonly SK: "EUR";
174
+ readonly SM: "EUR";
175
+ readonly TC: "USD";
176
+ readonly TF: "EUR";
177
+ readonly TL: "USD";
178
+ readonly TV: "AUD";
179
+ readonly UM: "USD";
180
+ readonly US: "USD";
181
+ readonly VA: "EUR";
182
+ readonly VG: "USD";
183
+ readonly VI: "USD";
184
+ readonly YT: "EUR";
185
+ };
186
+ type CurrencyLocales = keyof typeof countryCodesToCurrencyCodes;
187
+ type CurrencyCodes = (typeof countryCodesToCurrencyCodes)[CurrencyLocales];
188
+ declare function localeToCurrencyCode(locale: string): CurrencyCodes;
189
+
190
+ declare function clamp(val: number, min: number, max: number): number;
191
+ declare function linearInterpolate(value: number, fromRangeStart: number, fromRangeEnd: number, toRangeStart: number, toRangeEnd: number): number;
192
+ declare function round(num: number, decimalPlaces?: number): number;
193
+ declare function isNumber(value: unknown): value is number;
194
+
195
+ type GetValueResult<T> = {
196
+ stopPolling: boolean;
197
+ value: null | T;
198
+ };
199
+ declare function pollUntil<D extends () => Promise<unknown>, T>(asyncFn: D, getValue: (data: Awaited<ReturnType<D>>, response: {
200
+ stopPolling: boolean;
201
+ value: null | T;
202
+ }) => GetValueResult<T>, maxPolls?: number, pollIntervalMs?: number, ignoreErrors?: boolean | ((e: unknown) => boolean), getMaxPollsError?: (maxPolls: number) => Error): Promise<T>;
203
+
204
+ declare function sleep(ms: number): Promise<unknown>;
205
+
206
+ type Maybe<T> = T | null | undefined;
207
+ type ExpandRecursively<T> = T extends object ? T extends infer O ? {
208
+ [K in keyof O]: ExpandRecursively<O[K]>;
209
+ } : never : T;
210
+ type ById<T> = {
211
+ [id: string]: T;
212
+ };
213
+ type OmitTypename<T> = Omit<T, "__typename">;
214
+ declare const isType: <T extends string>(typename: T) => <N extends {
215
+ __typename: string;
216
+ }>(node: N | null | undefined) => node is Extract<N, {
217
+ __typename: T;
218
+ }>;
219
+ type DeepPartial<T> = T extends object ? {
220
+ [P in keyof T]?: DeepPartial<T[P]>;
221
+ } : T;
222
+
223
+ export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, DeepPartial, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode };
@@ -192,13 +192,14 @@ declare function linearInterpolate(value: number, fromRangeStart: number, fromRa
192
192
  declare function round(num: number, decimalPlaces?: number): number;
193
193
  declare function isNumber(value: unknown): value is number;
194
194
 
195
- declare function pollUntil<D extends () => Promise<unknown>, T>(asyncFn: D, getValue: (data: Awaited<ReturnType<D>>, response: {
195
+ type GetValueResult<T> = {
196
196
  stopPolling: boolean;
197
197
  value: null | T;
198
- }) => {
198
+ };
199
+ declare function pollUntil<D extends () => Promise<unknown>, T>(asyncFn: D, getValue: (data: Awaited<ReturnType<D>>, response: {
199
200
  stopPolling: boolean;
200
201
  value: null | T;
201
- }, maxPolls?: number, pollIntervalMs?: number, ignoreErrors?: boolean | ((e: unknown) => boolean), getMaxPollsError?: (maxPolls: number) => Error): Promise<T>;
202
+ }) => GetValueResult<T>, maxPolls?: number, pollIntervalMs?: number, ignoreErrors?: boolean | ((e: unknown) => boolean), getMaxPollsError?: (maxPolls: number) => Error): Promise<T>;
202
203
 
203
204
  declare function sleep(ms: number): Promise<unknown>;
204
205
 
@@ -215,5 +216,8 @@ declare const isType: <T extends string>(typename: T) => <N extends {
215
216
  }>(node: N | null | undefined) => node is Extract<N, {
216
217
  __typename: T;
217
218
  }>;
219
+ type DeepPartial<T> = T extends object ? {
220
+ [P in keyof T]?: DeepPartial<T[P]>;
221
+ } : T;
218
222
 
219
- export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode };
223
+ export { ById, CurrencyAmountArg, CurrencyAmountObj, CurrencyAmountType, CurrencyCodes, CurrencyLocales, CurrencyMap, CurrencyUnit, DeepPartial, ExpandRecursively, Maybe, OmitTypename, abbrCurrencyUnit, b64decode, b64encode, bytesToHex, clamp, convertCurrencyAmount, convertCurrencyAmountValue, countryCodesToCurrencyCodes, createSha256Hash, defaultCurrencyCode, formatCurrencyStr, getCurrentLocale, getErrorMsg, hexToBytes, isBrowser, isCurrencyAmount, isCurrencyAmountObj, isCurrencyMap, isError, isErrorMsg, isErrorWithMessage, isNode, isNumber, isTest, isType, linearInterpolate, localeToCurrencyCode, localeToCurrencySymbol, mapCurrencyAmount, pollUntil, round, separateCurrencyStrParts, sleep, urlsafe_b64decode };
@@ -34,7 +34,7 @@ import {
34
34
  separateCurrencyStrParts,
35
35
  sleep,
36
36
  urlsafe_b64decode
37
- } from "../chunk-UU6SHVGX.js";
37
+ } from "../chunk-MAZP7ETK.js";
38
38
  export {
39
39
  CurrencyUnit,
40
40
  abbrCurrencyUnit,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightsparkdev/core",
3
- "version": "1.0.9",
3
+ "version": "1.0.10",
4
4
  "description": "Lightspark JS SDK",
5
5
  "author": "Lightspark Inc.",
6
6
  "keywords": [
@@ -96,11 +96,11 @@
96
96
  "eslint": "^8.3.0",
97
97
  "eslint-watch": "^8.0.0",
98
98
  "jest": "^29.6.2",
99
- "prettier": "3.0.2",
100
- "prettier-plugin-organize-imports": "^3.2.2",
99
+ "prettier": "3.0.3",
100
+ "prettier-plugin-organize-imports": "^3.2.4",
101
101
  "ts-jest": "^29.1.1",
102
102
  "tsc-absolute": "^1.0.1",
103
- "tsup": "^6.7.0",
103
+ "tsup": "^7.2.0",
104
104
  "typescript": "^4.9.5"
105
105
  }
106
106
  }
package/src/Logger.ts CHANGED
@@ -9,7 +9,7 @@ export class Logger {
9
9
 
10
10
  constructor(loggerContext: string, getLoggingEnabled?: GetLoggingEnabled) {
11
11
  this.context = loggerContext;
12
- this.updateLoggingEnabled(getLoggingEnabled);
12
+ void this.updateLoggingEnabled(getLoggingEnabled);
13
13
  }
14
14
 
15
15
  async updateLoggingEnabled(getLoggingEnabled: GetLoggingEnabled) {
@@ -4,14 +4,13 @@ import type AuthProvider from "./AuthProvider.js";
4
4
  import { type Headers, type WsConnectionParams } from "./AuthProvider.js";
5
5
 
6
6
  export default class StubAuthProvider implements AuthProvider {
7
- async addAuthHeaders(headers: Headers) {
8
- return headers;
7
+ addAuthHeaders(headers: Headers) {
8
+ return Promise.resolve(headers);
9
9
  }
10
- async isAuthorized(): Promise<boolean> {
11
- return false;
10
+ isAuthorized(): Promise<boolean> {
11
+ return Promise.resolve(false);
12
12
  }
13
-
14
- async addWsConnectionParams(params: WsConnectionParams) {
15
- return params;
13
+ addWsConnectionParams(params: WsConnectionParams) {
14
+ return Promise.resolve(params);
16
15
  }
17
16
  }
@@ -117,6 +117,8 @@ const deriveKey = async (
117
117
  return [key, iv];
118
118
  };
119
119
 
120
+ type Header = { v: number; i: number; lsv?: number };
121
+
120
122
  const decrypt = async (
121
123
  header_json: string,
122
124
  ciphertext: string,
@@ -124,7 +126,7 @@ const decrypt = async (
124
126
  ): Promise<ArrayBuffer> => {
125
127
  let decoded = b64decode(ciphertext);
126
128
 
127
- let header;
129
+ let header: Header;
128
130
  if (header_json === "AES_256_CBC_PBKDF2_5000_SHA256") {
129
131
  header = {
130
132
  v: 0,
@@ -133,13 +135,13 @@ const decrypt = async (
133
135
  // Strip "Salted__" prefix
134
136
  decoded = decoded.slice(8);
135
137
  } else {
136
- header = JSON.parse(header_json);
138
+ header = JSON.parse(header_json) as Header;
137
139
  }
138
140
 
139
141
  if (header.v < 0 || header.v > 4) {
140
142
  throw new LightsparkException(
141
143
  "DecryptionError",
142
- "Unknown version ".concat(header.v),
144
+ `Unknown version ${header.v}`,
143
145
  );
144
146
  }
145
147
 
@@ -244,7 +246,7 @@ const sign = async (
244
246
  name: "RSA-PSS",
245
247
  saltLength: 32,
246
248
  },
247
- keyOrAlias as CryptoKey,
249
+ keyOrAlias,
248
250
  data,
249
251
  );
250
252
  };
@@ -0,0 +1,21 @@
1
+ import { describe, expect, test } from "@jest/globals";
2
+ import { b64encode, DefaultCrypto } from "../../index.js";
3
+
4
+ describe("Crypto tests", () => {
5
+ test("should generate a key", async () => {
6
+ const { privateKey, publicKey } =
7
+ await DefaultCrypto.generateSigningKeyPair();
8
+
9
+ const serializedKeypair = {
10
+ privateKey: b64encode(
11
+ await DefaultCrypto.serializeSigningKey(privateKey, "pkcs8"),
12
+ ),
13
+ publicKey: b64encode(
14
+ await DefaultCrypto.serializeSigningKey(publicKey, "spki"),
15
+ ),
16
+ };
17
+
18
+ expect(serializedKeypair.privateKey).not.toBeNull();
19
+ expect(serializedKeypair.publicKey).not.toBeNull();
20
+ }, 60_000);
21
+ });
@@ -26,6 +26,14 @@ export const LIGHTSPARK_BETA_HEADER_VALUE =
26
26
  "z2h0BBYxTA83cjW7fi8QwWtBPCzkQKiemcuhKY08LOo";
27
27
  dayjs.extend(utc);
28
28
 
29
+ type BodyData = {
30
+ query: string;
31
+ variables: { [key: string]: unknown };
32
+ operationName: string;
33
+ nonce?: number;
34
+ expires_at?: string;
35
+ };
36
+
29
37
  class Requester {
30
38
  private readonly wsClient: WsClient;
31
39
  constructor(
@@ -55,6 +63,7 @@ class Requester {
55
63
  }
56
64
 
57
65
  public async executeQuery<T>(query: Query<T>): Promise<T | null> {
66
+ /* eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- LIG-3400 */
58
67
  const data = await this.makeRawRequest(
59
68
  query.queryPayload,
60
69
  query.variables || {},
@@ -89,7 +98,7 @@ class Requester {
89
98
  }
90
99
  }
91
100
  const operation = operationMatch[2];
92
- const bodyData = {
101
+ const bodyData: BodyData = {
93
102
  query: queryPayload,
94
103
  variables,
95
104
  operationName: operation,
@@ -111,7 +120,7 @@ class Requester {
111
120
  signingNodeId: string | undefined = undefined,
112
121
  skipAuth: boolean = false,
113
122
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- LIG-3400 */
114
- ): Promise<any | null> {
123
+ ): Promise<any> {
115
124
  const operationNameRegex = /^\s*(query|mutation|subscription)\s+(\w+)/i;
116
125
  const operationMatch = queryPayload.match(operationNameRegex);
117
126
  if (!operationMatch || operationMatch.length < 3) {
@@ -131,7 +140,7 @@ class Requester {
131
140
  }
132
141
  }
133
142
  const operation = operationMatch[2];
134
- let bodyData = {
143
+ let bodyData: BodyData = {
135
144
  query: queryPayload,
136
145
  variables,
137
146
  operationName: operation,
@@ -179,7 +188,10 @@ class Requester {
179
188
  `Request ${operation} failed. ${response.statusText}`,
180
189
  );
181
190
  }
182
- const responseJson = await response.json();
191
+ const responseJson = (await response.json()) as {
192
+ data: unknown;
193
+ errors: unknown;
194
+ };
183
195
  const data = responseJson.data;
184
196
  if (!data) {
185
197
  throw new LightsparkException(
@@ -201,11 +213,11 @@ class Requester {
201
213
  }
202
214
 
203
215
  private async addSigningDataIfNeeded(
204
- queryPayload: { query: string; variables: unknown; operationName: string },
216
+ queryPayload: BodyData,
205
217
  headers: { [key: string]: string },
206
218
  signingNodeId: string | undefined,
207
219
  /* eslint-disable-next-line @typescript-eslint/no-explicit-any -- LIG-3400 */
208
- ): Promise<any> {
220
+ ): Promise<BodyData> {
209
221
  if (!signingNodeId) {
210
222
  return queryPayload;
211
223
  }
@@ -225,7 +237,7 @@ class Requester {
225
237
  expires_at: expiration,
226
238
  };
227
239
 
228
- const key = await this.nodeKeyCache.getKey(signingNodeId);
240
+ const key = this.nodeKeyCache.getKey(signingNodeId);
229
241
  if (!key) {
230
242
  throw new LightsparkSigningException(
231
243
  "Missing node of encrypted_signing_private_key",
@@ -5,50 +5,51 @@ function getDefaultMaxPollsError() {
5
5
  return new Error("pollUntil: Max polls reached");
6
6
  }
7
7
 
8
- export function pollUntil<D extends () => Promise<unknown>, T>(
8
+ type GetValueResult<T> = {
9
+ stopPolling: boolean;
10
+ value: null | T;
11
+ };
12
+
13
+ export async function pollUntil<D extends () => Promise<unknown>, T>(
9
14
  asyncFn: D,
10
15
  getValue: (
11
16
  data: Awaited<ReturnType<D>>,
12
17
  response: { stopPolling: boolean; value: null | T },
13
- ) => {
14
- stopPolling: boolean;
15
- value: null | T;
16
- },
18
+ ) => GetValueResult<T>,
17
19
  maxPolls = 60,
18
20
  pollIntervalMs = 500,
19
21
  ignoreErrors: boolean | ((e: unknown) => boolean) = false,
20
22
  getMaxPollsError: (maxPolls: number) => Error = getDefaultMaxPollsError,
21
23
  ): Promise<T> {
22
- return new Promise((resolve, reject) => {
23
- let polls = 0;
24
- let stopPolling = false;
25
- (async function () {
26
- while (!stopPolling) {
27
- polls += 1;
28
- if (polls > maxPolls) {
29
- stopPolling = true;
30
- const maxPollsError = getMaxPollsError(maxPolls);
31
- reject(maxPollsError);
32
- break;
33
- }
34
- try {
35
- const asyncResult = await asyncFn();
36
- const result = getValue(asyncResult as Awaited<ReturnType<D>>, {
37
- stopPolling: false,
38
- value: null,
39
- });
40
- if (result.stopPolling) {
41
- stopPolling = true;
42
- resolve(result.value as T);
43
- }
44
- } catch (e) {
45
- if (!ignoreErrors || (isFunction(ignoreErrors) && !ignoreErrors(e))) {
46
- stopPolling = true;
47
- reject(e);
48
- }
49
- }
50
- await sleep(pollIntervalMs);
24
+ let polls = 0;
25
+ let stopPolling = false;
26
+ let result: GetValueResult<T> = {
27
+ stopPolling: false,
28
+ value: null,
29
+ };
30
+ while (!stopPolling) {
31
+ polls += 1;
32
+ if (polls > maxPolls) {
33
+ stopPolling = true;
34
+ const maxPollsError = getMaxPollsError(maxPolls);
35
+ throw maxPollsError;
36
+ }
37
+ try {
38
+ const asyncResult = await asyncFn();
39
+ result = getValue(asyncResult as Awaited<ReturnType<D>>, {
40
+ stopPolling: false,
41
+ value: null,
42
+ });
43
+ if (result.stopPolling) {
44
+ stopPolling = true;
45
+ }
46
+ } catch (e) {
47
+ if (!ignoreErrors || (isFunction(ignoreErrors) && !ignoreErrors(e))) {
48
+ stopPolling = true;
49
+ throw e;
51
50
  }
52
- })();
53
- });
51
+ }
52
+ await sleep(pollIntervalMs);
53
+ }
54
+ return result.value as T;
54
55
  }
@@ -21,3 +21,9 @@ export const isType =
21
21
  ): node is Extract<N, { __typename: T }> => {
22
22
  return node?.__typename === typename;
23
23
  };
24
+
25
+ export type DeepPartial<T> = T extends object
26
+ ? {
27
+ [P in keyof T]?: DeepPartial<T[P]>;
28
+ }
29
+ : T;