priceos 0.0.27 → 0.0.30
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.cjs +150 -20
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +5 -4
- package/dist/index.d.ts +5 -4
- package/dist/index.js +150 -20
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -37,6 +37,141 @@ module.exports = __toCommonJS(index_exports);
|
|
|
37
37
|
|
|
38
38
|
// src/client.ts
|
|
39
39
|
var import_openapi_fetch = __toESM(require("openapi-fetch"), 1);
|
|
40
|
+
var RATE_LIMIT_STATUS = 429;
|
|
41
|
+
var MAX_RETRIES = 4;
|
|
42
|
+
var BASE_DELAY_MS = 250;
|
|
43
|
+
var BACKOFF_MULTIPLIER = 2;
|
|
44
|
+
var JITTER_MS = 250;
|
|
45
|
+
var RETRY_DELAY_CAP_MS = 5e3;
|
|
46
|
+
var REQUEST_TIMEOUT_MS = 2e4;
|
|
47
|
+
var LOG_LEVELS = {
|
|
48
|
+
none: 0,
|
|
49
|
+
error: 1,
|
|
50
|
+
warning: 2,
|
|
51
|
+
info: 3,
|
|
52
|
+
debug: 4
|
|
53
|
+
};
|
|
54
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
55
|
+
var getRetryDelayMs = (retryCount) => {
|
|
56
|
+
const backoff = BASE_DELAY_MS * Math.pow(BACKOFF_MULTIPLIER, retryCount - 1);
|
|
57
|
+
const jitter = Math.random() * JITTER_MS;
|
|
58
|
+
return Math.min(RETRY_DELAY_CAP_MS, backoff + jitter);
|
|
59
|
+
};
|
|
60
|
+
var createLogger = (logLevel) => {
|
|
61
|
+
const shouldLog = (level) => logLevel !== "none" && LOG_LEVELS[level] <= LOG_LEVELS[logLevel];
|
|
62
|
+
const write = (level, message, details) => {
|
|
63
|
+
if (!shouldLog(level)) return;
|
|
64
|
+
const prefix = `[PriceOS] ${level.toUpperCase()}: ${message}`;
|
|
65
|
+
const payload = details && Object.keys(details).length > 0 ? details : void 0;
|
|
66
|
+
switch (level) {
|
|
67
|
+
case "error":
|
|
68
|
+
payload ? console.error(prefix, payload) : console.error(prefix);
|
|
69
|
+
return;
|
|
70
|
+
case "warning":
|
|
71
|
+
payload ? console.warn(prefix, payload) : console.warn(prefix);
|
|
72
|
+
return;
|
|
73
|
+
case "info":
|
|
74
|
+
payload ? console.info(prefix, payload) : console.info(prefix);
|
|
75
|
+
return;
|
|
76
|
+
case "debug":
|
|
77
|
+
payload ? console.debug(prefix, payload) : console.debug(prefix);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
error: (message, details) => write("error", message, details),
|
|
83
|
+
warning: (message, details) => write("warning", message, details),
|
|
84
|
+
info: (message, details) => write("info", message, details),
|
|
85
|
+
debug: (message, details) => write("debug", message, details)
|
|
86
|
+
};
|
|
87
|
+
};
|
|
88
|
+
var getUpstreamSignal = (input, init) => {
|
|
89
|
+
if (init?.signal) return init.signal;
|
|
90
|
+
if (typeof Request !== "undefined" && input instanceof Request) return input.signal;
|
|
91
|
+
return void 0;
|
|
92
|
+
};
|
|
93
|
+
var getRequestDetails = (input, init) => {
|
|
94
|
+
const method = init?.method ?? (typeof Request !== "undefined" && input instanceof Request ? input.method : "GET");
|
|
95
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
96
|
+
return { method, url };
|
|
97
|
+
};
|
|
98
|
+
var getErrorMessage = (error) => {
|
|
99
|
+
const maybeError = error;
|
|
100
|
+
if (maybeError && typeof maybeError.error === "string") return maybeError.error;
|
|
101
|
+
return "Request failed";
|
|
102
|
+
};
|
|
103
|
+
var throwRequestError = (log, error, response, context) => {
|
|
104
|
+
log.error("Request failed", { context, status: response?.status, error });
|
|
105
|
+
throw new PriceOSError(getErrorMessage(error), { status: response?.status, details: error });
|
|
106
|
+
};
|
|
107
|
+
var createRetryingFetch = (baseFetch, log) => {
|
|
108
|
+
return async (input, init) => {
|
|
109
|
+
const { method, url } = getRequestDetails(input, init);
|
|
110
|
+
let attempt = 0;
|
|
111
|
+
while (true) {
|
|
112
|
+
log.debug("Request attempt", { method, url, attempt: attempt + 1, maxRetries: MAX_RETRIES });
|
|
113
|
+
const controller = new AbortController();
|
|
114
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
115
|
+
const upstreamSignal = getUpstreamSignal(input, init);
|
|
116
|
+
let removeAbortListener = null;
|
|
117
|
+
if (upstreamSignal) {
|
|
118
|
+
if (upstreamSignal.aborted) {
|
|
119
|
+
controller.abort();
|
|
120
|
+
} else {
|
|
121
|
+
const onAbort = () => controller.abort();
|
|
122
|
+
upstreamSignal.addEventListener("abort", onAbort);
|
|
123
|
+
removeAbortListener = () => upstreamSignal.removeEventListener("abort", onAbort);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
try {
|
|
127
|
+
const response = await baseFetch(input, { ...init, signal: controller.signal });
|
|
128
|
+
if (response.status !== RATE_LIMIT_STATUS) return response;
|
|
129
|
+
const retryAfter = response.headers.get("retry-after") ?? void 0;
|
|
130
|
+
log.warning("Rate limit hit (429)", {
|
|
131
|
+
method,
|
|
132
|
+
url,
|
|
133
|
+
attempt: attempt + 1,
|
|
134
|
+
maxRetries: MAX_RETRIES,
|
|
135
|
+
retryAfter
|
|
136
|
+
});
|
|
137
|
+
if (attempt >= MAX_RETRIES) {
|
|
138
|
+
log.error("Rate limit retries exhausted", { method, url, attempts: attempt + 1 });
|
|
139
|
+
return response;
|
|
140
|
+
}
|
|
141
|
+
const delayMs = getRetryDelayMs(attempt + 1);
|
|
142
|
+
log.info("Waiting to retry after rate limit", {
|
|
143
|
+
method,
|
|
144
|
+
url,
|
|
145
|
+
delayMs,
|
|
146
|
+
nextAttempt: attempt + 2,
|
|
147
|
+
maxRetries: MAX_RETRIES
|
|
148
|
+
});
|
|
149
|
+
await sleep(delayMs);
|
|
150
|
+
attempt += 1;
|
|
151
|
+
} catch (error) {
|
|
152
|
+
if (controller.signal.aborted) {
|
|
153
|
+
const abortedByCaller = upstreamSignal?.aborted ?? false;
|
|
154
|
+
if (abortedByCaller) {
|
|
155
|
+
log.warning("Request aborted by caller", { method, url, attempt: attempt + 1 });
|
|
156
|
+
} else {
|
|
157
|
+
log.error("Request timed out", {
|
|
158
|
+
method,
|
|
159
|
+
url,
|
|
160
|
+
attempt: attempt + 1,
|
|
161
|
+
timeoutMs: REQUEST_TIMEOUT_MS
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
log.error("Request failed", { method, url, attempt: attempt + 1, error });
|
|
166
|
+
}
|
|
167
|
+
throw error;
|
|
168
|
+
} finally {
|
|
169
|
+
clearTimeout(timeoutId);
|
|
170
|
+
removeAbortListener?.();
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
};
|
|
40
175
|
var PriceOSError = class extends Error {
|
|
41
176
|
status;
|
|
42
177
|
details;
|
|
@@ -50,18 +185,21 @@ var PriceOSError = class extends Error {
|
|
|
50
185
|
var PriceOS = class {
|
|
51
186
|
client;
|
|
52
187
|
header;
|
|
188
|
+
log;
|
|
53
189
|
customers;
|
|
54
190
|
features;
|
|
55
191
|
usage;
|
|
56
192
|
constructor(apiKey, opts = {}) {
|
|
57
|
-
const
|
|
193
|
+
const logLevel = opts.logLevel ?? "none";
|
|
194
|
+
this.log = createLogger(logLevel);
|
|
195
|
+
const baseUrl = "https://api.priceos.com";
|
|
58
196
|
this.header = { "x-api-key": apiKey };
|
|
197
|
+
const fetchWithRetry = createRetryingFetch(fetch, this.log);
|
|
59
198
|
this.client = (0, import_openapi_fetch.default)({
|
|
60
199
|
baseUrl,
|
|
61
|
-
fetch:
|
|
200
|
+
fetch: fetchWithRetry,
|
|
62
201
|
headers: {
|
|
63
|
-
"x-api-key": apiKey
|
|
64
|
-
...opts.userAgent ? { "user-agent": opts.userAgent } : {}
|
|
202
|
+
"x-api-key": apiKey
|
|
65
203
|
}
|
|
66
204
|
});
|
|
67
205
|
this.customers = {
|
|
@@ -69,8 +207,7 @@ var PriceOS = class {
|
|
|
69
207
|
const { data, error, response } = await this.client.GET("/v1/customer", {
|
|
70
208
|
params: { query: { customerId }, header: this.header }
|
|
71
209
|
});
|
|
72
|
-
if (error)
|
|
73
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
210
|
+
if (error) throwRequestError(this.log, error, response, "GET /v1/customer");
|
|
74
211
|
return data ?? null;
|
|
75
212
|
},
|
|
76
213
|
identify: async (input) => {
|
|
@@ -78,8 +215,7 @@ var PriceOS = class {
|
|
|
78
215
|
params: { header: this.header },
|
|
79
216
|
body: input
|
|
80
217
|
});
|
|
81
|
-
if (error)
|
|
82
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
218
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/customer/identify");
|
|
83
219
|
return data ?? null;
|
|
84
220
|
},
|
|
85
221
|
create: async (input) => {
|
|
@@ -87,8 +223,7 @@ var PriceOS = class {
|
|
|
87
223
|
params: { header: this.header },
|
|
88
224
|
body: input
|
|
89
225
|
});
|
|
90
|
-
if (error)
|
|
91
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
226
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/customer");
|
|
92
227
|
return data;
|
|
93
228
|
},
|
|
94
229
|
update: async (input) => {
|
|
@@ -96,16 +231,14 @@ var PriceOS = class {
|
|
|
96
231
|
params: { header: this.header },
|
|
97
232
|
body: input
|
|
98
233
|
});
|
|
99
|
-
if (error)
|
|
100
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
234
|
+
if (error) throwRequestError(this.log, error, response, "PUT /v1/customer");
|
|
101
235
|
return data;
|
|
102
236
|
},
|
|
103
237
|
delete: async (customerId) => {
|
|
104
238
|
const { data, error, response } = await this.client.DELETE("/v1/customer", {
|
|
105
239
|
params: { query: { customerId }, header: this.header }
|
|
106
240
|
});
|
|
107
|
-
if (error)
|
|
108
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
241
|
+
if (error) throwRequestError(this.log, error, response, "DELETE /v1/customer");
|
|
109
242
|
return data;
|
|
110
243
|
}
|
|
111
244
|
};
|
|
@@ -114,8 +247,7 @@ var PriceOS = class {
|
|
|
114
247
|
const { data, error, response } = await this.client.GET("/v1/feature-access", {
|
|
115
248
|
params: { query: { customerId }, header: this.header }
|
|
116
249
|
});
|
|
117
|
-
if (error)
|
|
118
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
250
|
+
if (error) throwRequestError(this.log, error, response, "GET /v1/feature-access");
|
|
119
251
|
return data;
|
|
120
252
|
}
|
|
121
253
|
};
|
|
@@ -125,8 +257,7 @@ var PriceOS = class {
|
|
|
125
257
|
params: { header: this.header },
|
|
126
258
|
body: input
|
|
127
259
|
});
|
|
128
|
-
if (error)
|
|
129
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
260
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/usage");
|
|
130
261
|
return data;
|
|
131
262
|
},
|
|
132
263
|
listEvents: async (input) => {
|
|
@@ -134,8 +265,7 @@ var PriceOS = class {
|
|
|
134
265
|
params: { header: this.header },
|
|
135
266
|
body: input
|
|
136
267
|
});
|
|
137
|
-
if (error)
|
|
138
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
268
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/usage/events");
|
|
139
269
|
return data;
|
|
140
270
|
}
|
|
141
271
|
};
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["export { PriceOS, PriceOSError } from \"./client\";\nexport type {\n PriceOSClientOptions,\n PriceOSCustomersClient,\n PriceOSFeaturesClient,\n PriceOSHttpClient,\n PriceOSUsageClient,\n} from \"./client\";\nexport type {\n CreateCustomerRequest,\n CreateCustomerResponse,\n DeleteCustomerRequest,\n DeleteCustomerResponse,\n GetCustomerResponse,\n GetFeatureAccessResponse,\n IdentifyCustomerBody,\n IdentifyCustomerResponse,\n LimitFeatureKeyFromAccessMap,\n ListUsageEventsBody,\n ListUsageEventsResponse,\n TrackUsageBody,\n TrackUsageResponse,\n UpdateCustomerBody,\n UpdateCustomerResponse,\n} from \"./types\";\n","import createClient from \"openapi-fetch\";\nimport type { Client } from \"openapi-fetch\";\nimport type { paths } from \"./gen/openapi\";\nimport {\n CreateCustomerRequest,\n CreateCustomerResponse,\n DeleteCustomerResponse,\n GetCustomerResponse,\n GetFeatureAccessResponse,\n IdentifyCustomerBody,\n IdentifyCustomerResponse,\n LimitFeatureKeyFromAccessMap,\n ListUsageEventsBody,\n ListUsageEventsResponse,\n TrackUsageBody,\n TrackUsageResponse,\n UpdateCustomerBody,\n UpdateCustomerResponse,\n} from \"./types\";\n\n// --- Public options ---\nexport type PriceOSClientOptions = {\n baseUrl?: string;\n fetch?: typeof fetch;\n userAgent?: string;\n};\n\nexport type PriceOSCustomersClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n get(customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null>;\n identify(input: IdentifyCustomerBody): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null>;\n create(input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>>;\n update(input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>>;\n delete(customerId: string): Promise<DeleteCustomerResponse>;\n};\n\nexport type PriceOSFeaturesClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n getAccess(customerId: string): Promise<TFeatureAccessMap>;\n};\n\nexport type PriceOSUsageClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n track(\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse>;\n listEvents(\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse>;\n};\n\n// --- Public SDK surface type ---\nexport type PriceOSHttpClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n};\n\nexport class PriceOSError extends Error {\n status?: number;\n details?: unknown;\n\n constructor(message: string, opts?: { status?: number; details?: unknown }) {\n super(message);\n this.name = \"PriceOSError\";\n this.status = opts?.status;\n this.details = opts?.details;\n }\n}\n\nexport class PriceOS<TFeatureAccessMap = GetFeatureAccessResponse>\n implements PriceOSHttpClient<TFeatureAccessMap>\n{\n private client: Client<paths>;\n private header: { \"x-api-key\": string };\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n\n constructor(apiKey: string, opts: PriceOSClientOptions = {}) {\n const baseUrl = opts.baseUrl ?? \"https://api.priceos.com\";\n this.header = { \"x-api-key\": apiKey };\n this.client = createClient<paths>({\n baseUrl,\n fetch: opts.fetch,\n headers: {\n \"x-api-key\": apiKey,\n ...(opts.userAgent ? { \"user-agent\": opts.userAgent } : {}),\n },\n });\n\n this.customers = {\n get: async (customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.GET(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return (data ?? null) as GetCustomerResponse<TFeatureAccessMap> | null;\n },\n identify: async (\n input: IdentifyCustomerBody\n ): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer/identify\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return (data ?? null) as IdentifyCustomerResponse<TFeatureAccessMap> | null;\n },\n create: async (input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as CreateCustomerResponse<TFeatureAccessMap>;\n },\n update: async (input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.PUT(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as UpdateCustomerResponse<TFeatureAccessMap>;\n },\n delete: async (customerId: string): Promise<DeleteCustomerResponse> => {\n const { data, error, response } = await this.client.DELETE(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as DeleteCustomerResponse;\n },\n };\n\n this.features = {\n getAccess: async (customerId: string): Promise<TFeatureAccessMap> => {\n const { data, error, response } = await this.client.GET(\"/v1/feature-access\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as TFeatureAccessMap;\n },\n };\n\n this.usage = {\n track: async (\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data!;\n },\n listEvents: async (\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage/events\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data!;\n },\n };\n }\n}\n"],"mappings":"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","names":["createClient"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/client.ts"],"sourcesContent":["export { PriceOS, PriceOSError } from \"./client\";\nexport type {\n PriceOSClientOptions,\n PriceOSLogLevel,\n PriceOSCustomersClient,\n PriceOSFeaturesClient,\n PriceOSHttpClient,\n PriceOSUsageClient,\n} from \"./client\";\nexport type {\n CreateCustomerRequest,\n CreateCustomerResponse,\n DeleteCustomerRequest,\n DeleteCustomerResponse,\n GetCustomerResponse,\n GetFeatureAccessResponse,\n IdentifyCustomerBody,\n IdentifyCustomerResponse,\n LimitFeatureKeyFromAccessMap,\n ListUsageEventsBody,\n ListUsageEventsResponse,\n UsageEvent,\n TrackUsageBody,\n TrackUsageResponse,\n UpdateCustomerBody,\n UpdateCustomerResponse,\n} from \"./types\";\n","import createClient from \"openapi-fetch\";\nimport type { Client } from \"openapi-fetch\";\nimport type { paths } from \"./gen/openapi\";\nimport {\n CreateCustomerRequest,\n CreateCustomerResponse,\n DeleteCustomerResponse,\n GetCustomerResponse,\n GetFeatureAccessResponse,\n IdentifyCustomerBody,\n IdentifyCustomerResponse,\n LimitFeatureKeyFromAccessMap,\n ListUsageEventsBody,\n ListUsageEventsResponse,\n TrackUsageBody,\n TrackUsageResponse,\n UpdateCustomerBody,\n UpdateCustomerResponse,\n} from \"./types\";\n\nexport type PriceOSLogLevel = \"none\" | \"error\" | \"warning\" | \"info\" | \"debug\";\n\n// --- Public options ---\nexport type PriceOSClientOptions = {\n logLevel?: PriceOSLogLevel;\n};\n\nconst RATE_LIMIT_STATUS = 429;\nconst MAX_RETRIES = 4;\nconst BASE_DELAY_MS = 250;\nconst BACKOFF_MULTIPLIER = 2;\nconst JITTER_MS = 250;\nconst RETRY_DELAY_CAP_MS = 5_000;\nconst REQUEST_TIMEOUT_MS = 20_000;\n\nconst LOG_LEVELS: Record<PriceOSLogLevel, number> = {\n none: 0,\n error: 1,\n warning: 2,\n info: 3,\n debug: 4,\n};\n\ntype Logger = {\n error: (message: string, details?: Record<string, unknown>) => void;\n warning: (message: string, details?: Record<string, unknown>) => void;\n info: (message: string, details?: Record<string, unknown>) => void;\n debug: (message: string, details?: Record<string, unknown>) => void;\n};\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst getRetryDelayMs = (retryCount: number): number => {\n const backoff = BASE_DELAY_MS * Math.pow(BACKOFF_MULTIPLIER, retryCount - 1);\n const jitter = Math.random() * JITTER_MS;\n return Math.min(RETRY_DELAY_CAP_MS, backoff + jitter);\n};\n\nconst createLogger = (logLevel: PriceOSLogLevel): Logger => {\n const shouldLog = (level: PriceOSLogLevel): boolean =>\n logLevel !== \"none\" && LOG_LEVELS[level] <= LOG_LEVELS[logLevel];\n\n const write = (\n level: PriceOSLogLevel,\n message: string,\n details?: Record<string, unknown>\n ): void => {\n if (!shouldLog(level)) return;\n const prefix = `[PriceOS] ${level.toUpperCase()}: ${message}`;\n const payload = details && Object.keys(details).length > 0 ? details : undefined;\n\n switch (level) {\n case \"error\":\n payload ? console.error(prefix, payload) : console.error(prefix);\n return;\n case \"warning\":\n payload ? console.warn(prefix, payload) : console.warn(prefix);\n return;\n case \"info\":\n payload ? console.info(prefix, payload) : console.info(prefix);\n return;\n case \"debug\":\n payload ? console.debug(prefix, payload) : console.debug(prefix);\n return;\n }\n };\n\n return {\n error: (message, details) => write(\"error\", message, details),\n warning: (message, details) => write(\"warning\", message, details),\n info: (message, details) => write(\"info\", message, details),\n debug: (message, details) => write(\"debug\", message, details),\n };\n};\n\nconst getUpstreamSignal = (input: RequestInfo | URL, init?: RequestInit): AbortSignal | undefined => {\n if (init?.signal) return init.signal;\n if (typeof Request !== \"undefined\" && input instanceof Request) return input.signal;\n return undefined;\n};\n\nconst getRequestDetails = (\n input: RequestInfo | URL,\n init?: RequestInit\n): { method: string; url: string } => {\n const method =\n init?.method ??\n (typeof Request !== \"undefined\" && input instanceof Request ? input.method : \"GET\");\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n return { method, url };\n};\n\nconst getErrorMessage = (error: unknown): string => {\n const maybeError = error as { error?: unknown } | null;\n if (maybeError && typeof maybeError.error === \"string\") return maybeError.error;\n return \"Request failed\";\n};\n\nconst throwRequestError = (\n log: Logger,\n error: unknown,\n response: Response | undefined,\n context: string\n): never => {\n log.error(\"Request failed\", { context, status: response?.status, error });\n throw new PriceOSError(getErrorMessage(error), { status: response?.status, details: error });\n};\n\nconst createRetryingFetch = (baseFetch: typeof fetch, log: Logger): typeof fetch => {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const { method, url } = getRequestDetails(input, init);\n let attempt = 0;\n while (true) {\n log.debug(\"Request attempt\", { method, url, attempt: attempt + 1, maxRetries: MAX_RETRIES });\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n const upstreamSignal = getUpstreamSignal(input, init);\n let removeAbortListener: (() => void) | null = null;\n\n if (upstreamSignal) {\n if (upstreamSignal.aborted) {\n controller.abort();\n } else {\n const onAbort = () => controller.abort();\n upstreamSignal.addEventListener(\"abort\", onAbort);\n removeAbortListener = () => upstreamSignal.removeEventListener(\"abort\", onAbort);\n }\n }\n\n try {\n const response = await baseFetch(input, { ...init, signal: controller.signal });\n if (response.status !== RATE_LIMIT_STATUS) return response;\n\n const retryAfter = response.headers.get(\"retry-after\") ?? undefined;\n log.warning(\"Rate limit hit (429)\", {\n method,\n url,\n attempt: attempt + 1,\n maxRetries: MAX_RETRIES,\n retryAfter,\n });\n\n if (attempt >= MAX_RETRIES) {\n log.error(\"Rate limit retries exhausted\", { method, url, attempts: attempt + 1 });\n return response;\n }\n\n const delayMs = getRetryDelayMs(attempt + 1);\n log.info(\"Waiting to retry after rate limit\", {\n method,\n url,\n delayMs,\n nextAttempt: attempt + 2,\n maxRetries: MAX_RETRIES,\n });\n await sleep(delayMs);\n attempt += 1;\n } catch (error) {\n if (controller.signal.aborted) {\n const abortedByCaller = upstreamSignal?.aborted ?? false;\n if (abortedByCaller) {\n log.warning(\"Request aborted by caller\", { method, url, attempt: attempt + 1 });\n } else {\n log.error(\"Request timed out\", {\n method,\n url,\n attempt: attempt + 1,\n timeoutMs: REQUEST_TIMEOUT_MS,\n });\n }\n } else {\n log.error(\"Request failed\", { method, url, attempt: attempt + 1, error });\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n removeAbortListener?.();\n }\n }\n };\n};\n\nexport type PriceOSCustomersClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n get(customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null>;\n identify(input: IdentifyCustomerBody): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null>;\n create(input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>>;\n update(input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>>;\n delete(customerId: string): Promise<DeleteCustomerResponse>;\n};\n\nexport type PriceOSFeaturesClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n getAccess(customerId: string): Promise<TFeatureAccessMap>;\n};\n\nexport type PriceOSUsageClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n track(\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse>;\n listEvents(\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse>;\n};\n\n// --- Public SDK surface type ---\nexport type PriceOSHttpClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n};\n\nexport class PriceOSError extends Error {\n status?: number;\n details?: unknown;\n\n constructor(message: string, opts?: { status?: number; details?: unknown }) {\n super(message);\n this.name = \"PriceOSError\";\n this.status = opts?.status;\n this.details = opts?.details;\n }\n}\n\nexport class PriceOS<TFeatureAccessMap = GetFeatureAccessResponse>\n implements PriceOSHttpClient<TFeatureAccessMap>\n{\n private client: Client<paths>;\n private header: { \"x-api-key\": string };\n private log: Logger;\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n\n constructor(apiKey: string, opts: PriceOSClientOptions = {}) {\n const logLevel = opts.logLevel ?? \"none\";\n this.log = createLogger(logLevel);\n const baseUrl = \"https://api.priceos.com\";\n this.header = { \"x-api-key\": apiKey };\n const fetchWithRetry = createRetryingFetch(fetch, this.log);\n this.client = createClient<paths>({\n baseUrl,\n fetch: fetchWithRetry,\n headers: {\n \"x-api-key\": apiKey,\n },\n });\n\n this.customers = {\n get: async (customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.GET(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error) throwRequestError(this.log, error, response, \"GET /v1/customer\");\n return (data ?? null) as GetCustomerResponse<TFeatureAccessMap> | null;\n },\n identify: async (\n input: IdentifyCustomerBody\n ): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer/identify\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/customer/identify\");\n return (data ?? null) as IdentifyCustomerResponse<TFeatureAccessMap> | null;\n },\n create: async (input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/customer\");\n return data! as CreateCustomerResponse<TFeatureAccessMap>;\n },\n update: async (input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.PUT(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"PUT /v1/customer\");\n return data! as UpdateCustomerResponse<TFeatureAccessMap>;\n },\n delete: async (customerId: string): Promise<DeleteCustomerResponse> => {\n const { data, error, response } = await this.client.DELETE(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error) throwRequestError(this.log, error, response, \"DELETE /v1/customer\");\n return data! as DeleteCustomerResponse;\n },\n };\n\n this.features = {\n getAccess: async (customerId: string): Promise<TFeatureAccessMap> => {\n const { data, error, response } = await this.client.GET(\"/v1/feature-access\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error) throwRequestError(this.log, error, response, \"GET /v1/feature-access\");\n return data! as TFeatureAccessMap;\n },\n };\n\n this.usage = {\n track: async (\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/usage\");\n return data!;\n },\n listEvents: async (\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage/events\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/usage/events\");\n return data!;\n },\n };\n }\n}\n"],"mappings":"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","names":["createClient"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1306,11 +1306,11 @@ type ListUsageEventsBody<TFeatureKey extends string = ListUsageEventsBodyBase["f
|
|
|
1306
1306
|
featureKey: TFeatureKey;
|
|
1307
1307
|
};
|
|
1308
1308
|
type ListUsageEventsResponse = paths["/v1/usage/events"]["post"]["responses"][200]["content"]["application/json"];
|
|
1309
|
+
type UsageEvent = ListUsageEventsResponse["usageEvents"][number];
|
|
1309
1310
|
|
|
1311
|
+
type PriceOSLogLevel = "none" | "error" | "warning" | "info" | "debug";
|
|
1310
1312
|
type PriceOSClientOptions = {
|
|
1311
|
-
|
|
1312
|
-
fetch?: typeof fetch;
|
|
1313
|
-
userAgent?: string;
|
|
1313
|
+
logLevel?: PriceOSLogLevel;
|
|
1314
1314
|
};
|
|
1315
1315
|
type PriceOSCustomersClient<TFeatureAccessMap = GetFeatureAccessResponse> = {
|
|
1316
1316
|
get(customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null>;
|
|
@@ -1342,10 +1342,11 @@ declare class PriceOSError extends Error {
|
|
|
1342
1342
|
declare class PriceOS<TFeatureAccessMap = GetFeatureAccessResponse> implements PriceOSHttpClient<TFeatureAccessMap> {
|
|
1343
1343
|
private client;
|
|
1344
1344
|
private header;
|
|
1345
|
+
private log;
|
|
1345
1346
|
customers: PriceOSCustomersClient<TFeatureAccessMap>;
|
|
1346
1347
|
features: PriceOSFeaturesClient<TFeatureAccessMap>;
|
|
1347
1348
|
usage: PriceOSUsageClient<TFeatureAccessMap>;
|
|
1348
1349
|
constructor(apiKey: string, opts?: PriceOSClientOptions);
|
|
1349
1350
|
}
|
|
1350
1351
|
|
|
1351
|
-
export { type CreateCustomerRequest, type CreateCustomerResponse, type DeleteCustomerRequest, type DeleteCustomerResponse, type GetCustomerResponse, type GetFeatureAccessResponse, type IdentifyCustomerBody, type IdentifyCustomerResponse, type LimitFeatureKeyFromAccessMap, type ListUsageEventsBody, type ListUsageEventsResponse, PriceOS, type PriceOSClientOptions, type PriceOSCustomersClient, PriceOSError, type PriceOSFeaturesClient, type PriceOSHttpClient, type PriceOSUsageClient, type TrackUsageBody, type TrackUsageResponse, type UpdateCustomerBody, type UpdateCustomerResponse };
|
|
1352
|
+
export { type CreateCustomerRequest, type CreateCustomerResponse, type DeleteCustomerRequest, type DeleteCustomerResponse, type GetCustomerResponse, type GetFeatureAccessResponse, type IdentifyCustomerBody, type IdentifyCustomerResponse, type LimitFeatureKeyFromAccessMap, type ListUsageEventsBody, type ListUsageEventsResponse, PriceOS, type PriceOSClientOptions, type PriceOSCustomersClient, PriceOSError, type PriceOSFeaturesClient, type PriceOSHttpClient, type PriceOSLogLevel, type PriceOSUsageClient, type TrackUsageBody, type TrackUsageResponse, type UpdateCustomerBody, type UpdateCustomerResponse, type UsageEvent };
|
package/dist/index.d.ts
CHANGED
|
@@ -1306,11 +1306,11 @@ type ListUsageEventsBody<TFeatureKey extends string = ListUsageEventsBodyBase["f
|
|
|
1306
1306
|
featureKey: TFeatureKey;
|
|
1307
1307
|
};
|
|
1308
1308
|
type ListUsageEventsResponse = paths["/v1/usage/events"]["post"]["responses"][200]["content"]["application/json"];
|
|
1309
|
+
type UsageEvent = ListUsageEventsResponse["usageEvents"][number];
|
|
1309
1310
|
|
|
1311
|
+
type PriceOSLogLevel = "none" | "error" | "warning" | "info" | "debug";
|
|
1310
1312
|
type PriceOSClientOptions = {
|
|
1311
|
-
|
|
1312
|
-
fetch?: typeof fetch;
|
|
1313
|
-
userAgent?: string;
|
|
1313
|
+
logLevel?: PriceOSLogLevel;
|
|
1314
1314
|
};
|
|
1315
1315
|
type PriceOSCustomersClient<TFeatureAccessMap = GetFeatureAccessResponse> = {
|
|
1316
1316
|
get(customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null>;
|
|
@@ -1342,10 +1342,11 @@ declare class PriceOSError extends Error {
|
|
|
1342
1342
|
declare class PriceOS<TFeatureAccessMap = GetFeatureAccessResponse> implements PriceOSHttpClient<TFeatureAccessMap> {
|
|
1343
1343
|
private client;
|
|
1344
1344
|
private header;
|
|
1345
|
+
private log;
|
|
1345
1346
|
customers: PriceOSCustomersClient<TFeatureAccessMap>;
|
|
1346
1347
|
features: PriceOSFeaturesClient<TFeatureAccessMap>;
|
|
1347
1348
|
usage: PriceOSUsageClient<TFeatureAccessMap>;
|
|
1348
1349
|
constructor(apiKey: string, opts?: PriceOSClientOptions);
|
|
1349
1350
|
}
|
|
1350
1351
|
|
|
1351
|
-
export { type CreateCustomerRequest, type CreateCustomerResponse, type DeleteCustomerRequest, type DeleteCustomerResponse, type GetCustomerResponse, type GetFeatureAccessResponse, type IdentifyCustomerBody, type IdentifyCustomerResponse, type LimitFeatureKeyFromAccessMap, type ListUsageEventsBody, type ListUsageEventsResponse, PriceOS, type PriceOSClientOptions, type PriceOSCustomersClient, PriceOSError, type PriceOSFeaturesClient, type PriceOSHttpClient, type PriceOSUsageClient, type TrackUsageBody, type TrackUsageResponse, type UpdateCustomerBody, type UpdateCustomerResponse };
|
|
1352
|
+
export { type CreateCustomerRequest, type CreateCustomerResponse, type DeleteCustomerRequest, type DeleteCustomerResponse, type GetCustomerResponse, type GetFeatureAccessResponse, type IdentifyCustomerBody, type IdentifyCustomerResponse, type LimitFeatureKeyFromAccessMap, type ListUsageEventsBody, type ListUsageEventsResponse, PriceOS, type PriceOSClientOptions, type PriceOSCustomersClient, PriceOSError, type PriceOSFeaturesClient, type PriceOSHttpClient, type PriceOSLogLevel, type PriceOSUsageClient, type TrackUsageBody, type TrackUsageResponse, type UpdateCustomerBody, type UpdateCustomerResponse, type UsageEvent };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,140 @@
|
|
|
1
1
|
// src/client.ts
|
|
2
2
|
import createClient from "openapi-fetch";
|
|
3
|
+
var RATE_LIMIT_STATUS = 429;
|
|
4
|
+
var MAX_RETRIES = 4;
|
|
5
|
+
var BASE_DELAY_MS = 250;
|
|
6
|
+
var BACKOFF_MULTIPLIER = 2;
|
|
7
|
+
var JITTER_MS = 250;
|
|
8
|
+
var RETRY_DELAY_CAP_MS = 5e3;
|
|
9
|
+
var REQUEST_TIMEOUT_MS = 2e4;
|
|
10
|
+
var LOG_LEVELS = {
|
|
11
|
+
none: 0,
|
|
12
|
+
error: 1,
|
|
13
|
+
warning: 2,
|
|
14
|
+
info: 3,
|
|
15
|
+
debug: 4
|
|
16
|
+
};
|
|
17
|
+
var sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
18
|
+
var getRetryDelayMs = (retryCount) => {
|
|
19
|
+
const backoff = BASE_DELAY_MS * Math.pow(BACKOFF_MULTIPLIER, retryCount - 1);
|
|
20
|
+
const jitter = Math.random() * JITTER_MS;
|
|
21
|
+
return Math.min(RETRY_DELAY_CAP_MS, backoff + jitter);
|
|
22
|
+
};
|
|
23
|
+
var createLogger = (logLevel) => {
|
|
24
|
+
const shouldLog = (level) => logLevel !== "none" && LOG_LEVELS[level] <= LOG_LEVELS[logLevel];
|
|
25
|
+
const write = (level, message, details) => {
|
|
26
|
+
if (!shouldLog(level)) return;
|
|
27
|
+
const prefix = `[PriceOS] ${level.toUpperCase()}: ${message}`;
|
|
28
|
+
const payload = details && Object.keys(details).length > 0 ? details : void 0;
|
|
29
|
+
switch (level) {
|
|
30
|
+
case "error":
|
|
31
|
+
payload ? console.error(prefix, payload) : console.error(prefix);
|
|
32
|
+
return;
|
|
33
|
+
case "warning":
|
|
34
|
+
payload ? console.warn(prefix, payload) : console.warn(prefix);
|
|
35
|
+
return;
|
|
36
|
+
case "info":
|
|
37
|
+
payload ? console.info(prefix, payload) : console.info(prefix);
|
|
38
|
+
return;
|
|
39
|
+
case "debug":
|
|
40
|
+
payload ? console.debug(prefix, payload) : console.debug(prefix);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
return {
|
|
45
|
+
error: (message, details) => write("error", message, details),
|
|
46
|
+
warning: (message, details) => write("warning", message, details),
|
|
47
|
+
info: (message, details) => write("info", message, details),
|
|
48
|
+
debug: (message, details) => write("debug", message, details)
|
|
49
|
+
};
|
|
50
|
+
};
|
|
51
|
+
var getUpstreamSignal = (input, init) => {
|
|
52
|
+
if (init?.signal) return init.signal;
|
|
53
|
+
if (typeof Request !== "undefined" && input instanceof Request) return input.signal;
|
|
54
|
+
return void 0;
|
|
55
|
+
};
|
|
56
|
+
var getRequestDetails = (input, init) => {
|
|
57
|
+
const method = init?.method ?? (typeof Request !== "undefined" && input instanceof Request ? input.method : "GET");
|
|
58
|
+
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
59
|
+
return { method, url };
|
|
60
|
+
};
|
|
61
|
+
var getErrorMessage = (error) => {
|
|
62
|
+
const maybeError = error;
|
|
63
|
+
if (maybeError && typeof maybeError.error === "string") return maybeError.error;
|
|
64
|
+
return "Request failed";
|
|
65
|
+
};
|
|
66
|
+
var throwRequestError = (log, error, response, context) => {
|
|
67
|
+
log.error("Request failed", { context, status: response?.status, error });
|
|
68
|
+
throw new PriceOSError(getErrorMessage(error), { status: response?.status, details: error });
|
|
69
|
+
};
|
|
70
|
+
var createRetryingFetch = (baseFetch, log) => {
|
|
71
|
+
return async (input, init) => {
|
|
72
|
+
const { method, url } = getRequestDetails(input, init);
|
|
73
|
+
let attempt = 0;
|
|
74
|
+
while (true) {
|
|
75
|
+
log.debug("Request attempt", { method, url, attempt: attempt + 1, maxRetries: MAX_RETRIES });
|
|
76
|
+
const controller = new AbortController();
|
|
77
|
+
const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);
|
|
78
|
+
const upstreamSignal = getUpstreamSignal(input, init);
|
|
79
|
+
let removeAbortListener = null;
|
|
80
|
+
if (upstreamSignal) {
|
|
81
|
+
if (upstreamSignal.aborted) {
|
|
82
|
+
controller.abort();
|
|
83
|
+
} else {
|
|
84
|
+
const onAbort = () => controller.abort();
|
|
85
|
+
upstreamSignal.addEventListener("abort", onAbort);
|
|
86
|
+
removeAbortListener = () => upstreamSignal.removeEventListener("abort", onAbort);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const response = await baseFetch(input, { ...init, signal: controller.signal });
|
|
91
|
+
if (response.status !== RATE_LIMIT_STATUS) return response;
|
|
92
|
+
const retryAfter = response.headers.get("retry-after") ?? void 0;
|
|
93
|
+
log.warning("Rate limit hit (429)", {
|
|
94
|
+
method,
|
|
95
|
+
url,
|
|
96
|
+
attempt: attempt + 1,
|
|
97
|
+
maxRetries: MAX_RETRIES,
|
|
98
|
+
retryAfter
|
|
99
|
+
});
|
|
100
|
+
if (attempt >= MAX_RETRIES) {
|
|
101
|
+
log.error("Rate limit retries exhausted", { method, url, attempts: attempt + 1 });
|
|
102
|
+
return response;
|
|
103
|
+
}
|
|
104
|
+
const delayMs = getRetryDelayMs(attempt + 1);
|
|
105
|
+
log.info("Waiting to retry after rate limit", {
|
|
106
|
+
method,
|
|
107
|
+
url,
|
|
108
|
+
delayMs,
|
|
109
|
+
nextAttempt: attempt + 2,
|
|
110
|
+
maxRetries: MAX_RETRIES
|
|
111
|
+
});
|
|
112
|
+
await sleep(delayMs);
|
|
113
|
+
attempt += 1;
|
|
114
|
+
} catch (error) {
|
|
115
|
+
if (controller.signal.aborted) {
|
|
116
|
+
const abortedByCaller = upstreamSignal?.aborted ?? false;
|
|
117
|
+
if (abortedByCaller) {
|
|
118
|
+
log.warning("Request aborted by caller", { method, url, attempt: attempt + 1 });
|
|
119
|
+
} else {
|
|
120
|
+
log.error("Request timed out", {
|
|
121
|
+
method,
|
|
122
|
+
url,
|
|
123
|
+
attempt: attempt + 1,
|
|
124
|
+
timeoutMs: REQUEST_TIMEOUT_MS
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
} else {
|
|
128
|
+
log.error("Request failed", { method, url, attempt: attempt + 1, error });
|
|
129
|
+
}
|
|
130
|
+
throw error;
|
|
131
|
+
} finally {
|
|
132
|
+
clearTimeout(timeoutId);
|
|
133
|
+
removeAbortListener?.();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
};
|
|
3
138
|
var PriceOSError = class extends Error {
|
|
4
139
|
status;
|
|
5
140
|
details;
|
|
@@ -13,18 +148,21 @@ var PriceOSError = class extends Error {
|
|
|
13
148
|
var PriceOS = class {
|
|
14
149
|
client;
|
|
15
150
|
header;
|
|
151
|
+
log;
|
|
16
152
|
customers;
|
|
17
153
|
features;
|
|
18
154
|
usage;
|
|
19
155
|
constructor(apiKey, opts = {}) {
|
|
20
|
-
const
|
|
156
|
+
const logLevel = opts.logLevel ?? "none";
|
|
157
|
+
this.log = createLogger(logLevel);
|
|
158
|
+
const baseUrl = "https://api.priceos.com";
|
|
21
159
|
this.header = { "x-api-key": apiKey };
|
|
160
|
+
const fetchWithRetry = createRetryingFetch(fetch, this.log);
|
|
22
161
|
this.client = createClient({
|
|
23
162
|
baseUrl,
|
|
24
|
-
fetch:
|
|
163
|
+
fetch: fetchWithRetry,
|
|
25
164
|
headers: {
|
|
26
|
-
"x-api-key": apiKey
|
|
27
|
-
...opts.userAgent ? { "user-agent": opts.userAgent } : {}
|
|
165
|
+
"x-api-key": apiKey
|
|
28
166
|
}
|
|
29
167
|
});
|
|
30
168
|
this.customers = {
|
|
@@ -32,8 +170,7 @@ var PriceOS = class {
|
|
|
32
170
|
const { data, error, response } = await this.client.GET("/v1/customer", {
|
|
33
171
|
params: { query: { customerId }, header: this.header }
|
|
34
172
|
});
|
|
35
|
-
if (error)
|
|
36
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
173
|
+
if (error) throwRequestError(this.log, error, response, "GET /v1/customer");
|
|
37
174
|
return data ?? null;
|
|
38
175
|
},
|
|
39
176
|
identify: async (input) => {
|
|
@@ -41,8 +178,7 @@ var PriceOS = class {
|
|
|
41
178
|
params: { header: this.header },
|
|
42
179
|
body: input
|
|
43
180
|
});
|
|
44
|
-
if (error)
|
|
45
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
181
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/customer/identify");
|
|
46
182
|
return data ?? null;
|
|
47
183
|
},
|
|
48
184
|
create: async (input) => {
|
|
@@ -50,8 +186,7 @@ var PriceOS = class {
|
|
|
50
186
|
params: { header: this.header },
|
|
51
187
|
body: input
|
|
52
188
|
});
|
|
53
|
-
if (error)
|
|
54
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
189
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/customer");
|
|
55
190
|
return data;
|
|
56
191
|
},
|
|
57
192
|
update: async (input) => {
|
|
@@ -59,16 +194,14 @@ var PriceOS = class {
|
|
|
59
194
|
params: { header: this.header },
|
|
60
195
|
body: input
|
|
61
196
|
});
|
|
62
|
-
if (error)
|
|
63
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
197
|
+
if (error) throwRequestError(this.log, error, response, "PUT /v1/customer");
|
|
64
198
|
return data;
|
|
65
199
|
},
|
|
66
200
|
delete: async (customerId) => {
|
|
67
201
|
const { data, error, response } = await this.client.DELETE("/v1/customer", {
|
|
68
202
|
params: { query: { customerId }, header: this.header }
|
|
69
203
|
});
|
|
70
|
-
if (error)
|
|
71
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
204
|
+
if (error) throwRequestError(this.log, error, response, "DELETE /v1/customer");
|
|
72
205
|
return data;
|
|
73
206
|
}
|
|
74
207
|
};
|
|
@@ -77,8 +210,7 @@ var PriceOS = class {
|
|
|
77
210
|
const { data, error, response } = await this.client.GET("/v1/feature-access", {
|
|
78
211
|
params: { query: { customerId }, header: this.header }
|
|
79
212
|
});
|
|
80
|
-
if (error)
|
|
81
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
213
|
+
if (error) throwRequestError(this.log, error, response, "GET /v1/feature-access");
|
|
82
214
|
return data;
|
|
83
215
|
}
|
|
84
216
|
};
|
|
@@ -88,8 +220,7 @@ var PriceOS = class {
|
|
|
88
220
|
params: { header: this.header },
|
|
89
221
|
body: input
|
|
90
222
|
});
|
|
91
|
-
if (error)
|
|
92
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
223
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/usage");
|
|
93
224
|
return data;
|
|
94
225
|
},
|
|
95
226
|
listEvents: async (input) => {
|
|
@@ -97,8 +228,7 @@ var PriceOS = class {
|
|
|
97
228
|
params: { header: this.header },
|
|
98
229
|
body: input
|
|
99
230
|
});
|
|
100
|
-
if (error)
|
|
101
|
-
throw new PriceOSError(error.error ?? "Request failed", { status: response?.status, details: error });
|
|
231
|
+
if (error) throwRequestError(this.log, error, response, "POST /v1/usage/events");
|
|
102
232
|
return data;
|
|
103
233
|
}
|
|
104
234
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import createClient from \"openapi-fetch\";\nimport type { Client } from \"openapi-fetch\";\nimport type { paths } from \"./gen/openapi\";\nimport {\n CreateCustomerRequest,\n CreateCustomerResponse,\n DeleteCustomerResponse,\n GetCustomerResponse,\n GetFeatureAccessResponse,\n IdentifyCustomerBody,\n IdentifyCustomerResponse,\n LimitFeatureKeyFromAccessMap,\n ListUsageEventsBody,\n ListUsageEventsResponse,\n TrackUsageBody,\n TrackUsageResponse,\n UpdateCustomerBody,\n UpdateCustomerResponse,\n} from \"./types\";\n\n// --- Public options ---\nexport type PriceOSClientOptions = {\n baseUrl?: string;\n fetch?: typeof fetch;\n userAgent?: string;\n};\n\nexport type PriceOSCustomersClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n get(customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null>;\n identify(input: IdentifyCustomerBody): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null>;\n create(input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>>;\n update(input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>>;\n delete(customerId: string): Promise<DeleteCustomerResponse>;\n};\n\nexport type PriceOSFeaturesClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n getAccess(customerId: string): Promise<TFeatureAccessMap>;\n};\n\nexport type PriceOSUsageClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n track(\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse>;\n listEvents(\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse>;\n};\n\n// --- Public SDK surface type ---\nexport type PriceOSHttpClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n};\n\nexport class PriceOSError extends Error {\n status?: number;\n details?: unknown;\n\n constructor(message: string, opts?: { status?: number; details?: unknown }) {\n super(message);\n this.name = \"PriceOSError\";\n this.status = opts?.status;\n this.details = opts?.details;\n }\n}\n\nexport class PriceOS<TFeatureAccessMap = GetFeatureAccessResponse>\n implements PriceOSHttpClient<TFeatureAccessMap>\n{\n private client: Client<paths>;\n private header: { \"x-api-key\": string };\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n\n constructor(apiKey: string, opts: PriceOSClientOptions = {}) {\n const baseUrl = opts.baseUrl ?? \"https://api.priceos.com\";\n this.header = { \"x-api-key\": apiKey };\n this.client = createClient<paths>({\n baseUrl,\n fetch: opts.fetch,\n headers: {\n \"x-api-key\": apiKey,\n ...(opts.userAgent ? { \"user-agent\": opts.userAgent } : {}),\n },\n });\n\n this.customers = {\n get: async (customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.GET(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return (data ?? null) as GetCustomerResponse<TFeatureAccessMap> | null;\n },\n identify: async (\n input: IdentifyCustomerBody\n ): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer/identify\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return (data ?? null) as IdentifyCustomerResponse<TFeatureAccessMap> | null;\n },\n create: async (input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as CreateCustomerResponse<TFeatureAccessMap>;\n },\n update: async (input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.PUT(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as UpdateCustomerResponse<TFeatureAccessMap>;\n },\n delete: async (customerId: string): Promise<DeleteCustomerResponse> => {\n const { data, error, response } = await this.client.DELETE(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as DeleteCustomerResponse;\n },\n };\n\n this.features = {\n getAccess: async (customerId: string): Promise<TFeatureAccessMap> => {\n const { data, error, response } = await this.client.GET(\"/v1/feature-access\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data! as TFeatureAccessMap;\n },\n };\n\n this.usage = {\n track: async (\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data!;\n },\n listEvents: async (\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage/events\", {\n params: { header: this.header },\n body: input,\n });\n if (error)\n throw new PriceOSError(error.error ?? \"Request failed\", { status: response?.status, details: error });\n return data!;\n },\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client.ts"],"sourcesContent":["import createClient from \"openapi-fetch\";\nimport type { Client } from \"openapi-fetch\";\nimport type { paths } from \"./gen/openapi\";\nimport {\n CreateCustomerRequest,\n CreateCustomerResponse,\n DeleteCustomerResponse,\n GetCustomerResponse,\n GetFeatureAccessResponse,\n IdentifyCustomerBody,\n IdentifyCustomerResponse,\n LimitFeatureKeyFromAccessMap,\n ListUsageEventsBody,\n ListUsageEventsResponse,\n TrackUsageBody,\n TrackUsageResponse,\n UpdateCustomerBody,\n UpdateCustomerResponse,\n} from \"./types\";\n\nexport type PriceOSLogLevel = \"none\" | \"error\" | \"warning\" | \"info\" | \"debug\";\n\n// --- Public options ---\nexport type PriceOSClientOptions = {\n logLevel?: PriceOSLogLevel;\n};\n\nconst RATE_LIMIT_STATUS = 429;\nconst MAX_RETRIES = 4;\nconst BASE_DELAY_MS = 250;\nconst BACKOFF_MULTIPLIER = 2;\nconst JITTER_MS = 250;\nconst RETRY_DELAY_CAP_MS = 5_000;\nconst REQUEST_TIMEOUT_MS = 20_000;\n\nconst LOG_LEVELS: Record<PriceOSLogLevel, number> = {\n none: 0,\n error: 1,\n warning: 2,\n info: 3,\n debug: 4,\n};\n\ntype Logger = {\n error: (message: string, details?: Record<string, unknown>) => void;\n warning: (message: string, details?: Record<string, unknown>) => void;\n info: (message: string, details?: Record<string, unknown>) => void;\n debug: (message: string, details?: Record<string, unknown>) => void;\n};\n\nconst sleep = (ms: number): Promise<void> => new Promise((resolve) => setTimeout(resolve, ms));\n\nconst getRetryDelayMs = (retryCount: number): number => {\n const backoff = BASE_DELAY_MS * Math.pow(BACKOFF_MULTIPLIER, retryCount - 1);\n const jitter = Math.random() * JITTER_MS;\n return Math.min(RETRY_DELAY_CAP_MS, backoff + jitter);\n};\n\nconst createLogger = (logLevel: PriceOSLogLevel): Logger => {\n const shouldLog = (level: PriceOSLogLevel): boolean =>\n logLevel !== \"none\" && LOG_LEVELS[level] <= LOG_LEVELS[logLevel];\n\n const write = (\n level: PriceOSLogLevel,\n message: string,\n details?: Record<string, unknown>\n ): void => {\n if (!shouldLog(level)) return;\n const prefix = `[PriceOS] ${level.toUpperCase()}: ${message}`;\n const payload = details && Object.keys(details).length > 0 ? details : undefined;\n\n switch (level) {\n case \"error\":\n payload ? console.error(prefix, payload) : console.error(prefix);\n return;\n case \"warning\":\n payload ? console.warn(prefix, payload) : console.warn(prefix);\n return;\n case \"info\":\n payload ? console.info(prefix, payload) : console.info(prefix);\n return;\n case \"debug\":\n payload ? console.debug(prefix, payload) : console.debug(prefix);\n return;\n }\n };\n\n return {\n error: (message, details) => write(\"error\", message, details),\n warning: (message, details) => write(\"warning\", message, details),\n info: (message, details) => write(\"info\", message, details),\n debug: (message, details) => write(\"debug\", message, details),\n };\n};\n\nconst getUpstreamSignal = (input: RequestInfo | URL, init?: RequestInit): AbortSignal | undefined => {\n if (init?.signal) return init.signal;\n if (typeof Request !== \"undefined\" && input instanceof Request) return input.signal;\n return undefined;\n};\n\nconst getRequestDetails = (\n input: RequestInfo | URL,\n init?: RequestInit\n): { method: string; url: string } => {\n const method =\n init?.method ??\n (typeof Request !== \"undefined\" && input instanceof Request ? input.method : \"GET\");\n const url =\n typeof input === \"string\"\n ? input\n : input instanceof URL\n ? input.toString()\n : input.url;\n return { method, url };\n};\n\nconst getErrorMessage = (error: unknown): string => {\n const maybeError = error as { error?: unknown } | null;\n if (maybeError && typeof maybeError.error === \"string\") return maybeError.error;\n return \"Request failed\";\n};\n\nconst throwRequestError = (\n log: Logger,\n error: unknown,\n response: Response | undefined,\n context: string\n): never => {\n log.error(\"Request failed\", { context, status: response?.status, error });\n throw new PriceOSError(getErrorMessage(error), { status: response?.status, details: error });\n};\n\nconst createRetryingFetch = (baseFetch: typeof fetch, log: Logger): typeof fetch => {\n return async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n const { method, url } = getRequestDetails(input, init);\n let attempt = 0;\n while (true) {\n log.debug(\"Request attempt\", { method, url, attempt: attempt + 1, maxRetries: MAX_RETRIES });\n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), REQUEST_TIMEOUT_MS);\n const upstreamSignal = getUpstreamSignal(input, init);\n let removeAbortListener: (() => void) | null = null;\n\n if (upstreamSignal) {\n if (upstreamSignal.aborted) {\n controller.abort();\n } else {\n const onAbort = () => controller.abort();\n upstreamSignal.addEventListener(\"abort\", onAbort);\n removeAbortListener = () => upstreamSignal.removeEventListener(\"abort\", onAbort);\n }\n }\n\n try {\n const response = await baseFetch(input, { ...init, signal: controller.signal });\n if (response.status !== RATE_LIMIT_STATUS) return response;\n\n const retryAfter = response.headers.get(\"retry-after\") ?? undefined;\n log.warning(\"Rate limit hit (429)\", {\n method,\n url,\n attempt: attempt + 1,\n maxRetries: MAX_RETRIES,\n retryAfter,\n });\n\n if (attempt >= MAX_RETRIES) {\n log.error(\"Rate limit retries exhausted\", { method, url, attempts: attempt + 1 });\n return response;\n }\n\n const delayMs = getRetryDelayMs(attempt + 1);\n log.info(\"Waiting to retry after rate limit\", {\n method,\n url,\n delayMs,\n nextAttempt: attempt + 2,\n maxRetries: MAX_RETRIES,\n });\n await sleep(delayMs);\n attempt += 1;\n } catch (error) {\n if (controller.signal.aborted) {\n const abortedByCaller = upstreamSignal?.aborted ?? false;\n if (abortedByCaller) {\n log.warning(\"Request aborted by caller\", { method, url, attempt: attempt + 1 });\n } else {\n log.error(\"Request timed out\", {\n method,\n url,\n attempt: attempt + 1,\n timeoutMs: REQUEST_TIMEOUT_MS,\n });\n }\n } else {\n log.error(\"Request failed\", { method, url, attempt: attempt + 1, error });\n }\n throw error;\n } finally {\n clearTimeout(timeoutId);\n removeAbortListener?.();\n }\n }\n };\n};\n\nexport type PriceOSCustomersClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n get(customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null>;\n identify(input: IdentifyCustomerBody): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null>;\n create(input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>>;\n update(input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>>;\n delete(customerId: string): Promise<DeleteCustomerResponse>;\n};\n\nexport type PriceOSFeaturesClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n getAccess(customerId: string): Promise<TFeatureAccessMap>;\n};\n\nexport type PriceOSUsageClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n track(\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse>;\n listEvents(\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse>;\n};\n\n// --- Public SDK surface type ---\nexport type PriceOSHttpClient<TFeatureAccessMap = GetFeatureAccessResponse> = {\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n};\n\nexport class PriceOSError extends Error {\n status?: number;\n details?: unknown;\n\n constructor(message: string, opts?: { status?: number; details?: unknown }) {\n super(message);\n this.name = \"PriceOSError\";\n this.status = opts?.status;\n this.details = opts?.details;\n }\n}\n\nexport class PriceOS<TFeatureAccessMap = GetFeatureAccessResponse>\n implements PriceOSHttpClient<TFeatureAccessMap>\n{\n private client: Client<paths>;\n private header: { \"x-api-key\": string };\n private log: Logger;\n customers: PriceOSCustomersClient<TFeatureAccessMap>;\n features: PriceOSFeaturesClient<TFeatureAccessMap>;\n usage: PriceOSUsageClient<TFeatureAccessMap>;\n\n constructor(apiKey: string, opts: PriceOSClientOptions = {}) {\n const logLevel = opts.logLevel ?? \"none\";\n this.log = createLogger(logLevel);\n const baseUrl = \"https://api.priceos.com\";\n this.header = { \"x-api-key\": apiKey };\n const fetchWithRetry = createRetryingFetch(fetch, this.log);\n this.client = createClient<paths>({\n baseUrl,\n fetch: fetchWithRetry,\n headers: {\n \"x-api-key\": apiKey,\n },\n });\n\n this.customers = {\n get: async (customerId: string): Promise<GetCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.GET(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error) throwRequestError(this.log, error, response, \"GET /v1/customer\");\n return (data ?? null) as GetCustomerResponse<TFeatureAccessMap> | null;\n },\n identify: async (\n input: IdentifyCustomerBody\n ): Promise<IdentifyCustomerResponse<TFeatureAccessMap> | null> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer/identify\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/customer/identify\");\n return (data ?? null) as IdentifyCustomerResponse<TFeatureAccessMap> | null;\n },\n create: async (input: CreateCustomerRequest): Promise<CreateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.POST(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/customer\");\n return data! as CreateCustomerResponse<TFeatureAccessMap>;\n },\n update: async (input: UpdateCustomerBody): Promise<UpdateCustomerResponse<TFeatureAccessMap>> => {\n const { data, error, response } = await this.client.PUT(\"/v1/customer\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"PUT /v1/customer\");\n return data! as UpdateCustomerResponse<TFeatureAccessMap>;\n },\n delete: async (customerId: string): Promise<DeleteCustomerResponse> => {\n const { data, error, response } = await this.client.DELETE(\"/v1/customer\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error) throwRequestError(this.log, error, response, \"DELETE /v1/customer\");\n return data! as DeleteCustomerResponse;\n },\n };\n\n this.features = {\n getAccess: async (customerId: string): Promise<TFeatureAccessMap> => {\n const { data, error, response } = await this.client.GET(\"/v1/feature-access\", {\n params: { query: { customerId }, header: this.header },\n });\n if (error) throwRequestError(this.log, error, response, \"GET /v1/feature-access\");\n return data! as TFeatureAccessMap;\n },\n };\n\n this.usage = {\n track: async (\n input: TrackUsageBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<TrackUsageResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/usage\");\n return data!;\n },\n listEvents: async (\n input: ListUsageEventsBody<LimitFeatureKeyFromAccessMap<TFeatureAccessMap>>\n ): Promise<ListUsageEventsResponse> => {\n const { data, error, response } = await this.client.POST(\"/v1/usage/events\", {\n params: { header: this.header },\n body: input,\n });\n if (error) throwRequestError(this.log, error, response, \"POST /v1/usage/events\");\n return data!;\n },\n };\n }\n}\n"],"mappings":"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","names":[]}
|