@syscli/oneclickdz 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +298 -0
- package/dist/index.cjs +934 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +730 -0
- package/dist/index.d.ts +730 -0
- package/dist/index.js +890 -0
- package/dist/index.js.map +1 -0
- package/package.json +67 -0
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,730 @@
|
|
|
1
|
+
type HttpMethod = "GET" | "POST" | "PUT" | "PATCH" | "DELETE";
|
|
2
|
+
/** A fetch implementation compatible with the platform global. */
|
|
3
|
+
type FetchLike = typeof globalThis.fetch;
|
|
4
|
+
interface RetryConfig {
|
|
5
|
+
/** Total attempts including the first. 1 disables retrying. */
|
|
6
|
+
attempts: number;
|
|
7
|
+
/** Wait the Retry-After header when the API sends one. */
|
|
8
|
+
respectRetryAfter: boolean;
|
|
9
|
+
}
|
|
10
|
+
/** Page numbers and totals the API returns on list endpoints. */
|
|
11
|
+
interface Pagination {
|
|
12
|
+
page: number;
|
|
13
|
+
pageSize: number;
|
|
14
|
+
totalPages: number;
|
|
15
|
+
totalResults: number;
|
|
16
|
+
}
|
|
17
|
+
interface ResponseMeta {
|
|
18
|
+
timestamp?: string;
|
|
19
|
+
pagination?: Pagination;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The success envelope every endpoint returns. `data` is the endpoint payload;
|
|
24
|
+
* a few endpoints (the gift-card catalog, for one) hang extra counts off the top
|
|
25
|
+
* level, so unknown keys are preserved.
|
|
26
|
+
*/
|
|
27
|
+
interface Envelope<T> {
|
|
28
|
+
success: true;
|
|
29
|
+
data: T;
|
|
30
|
+
meta?: ResponseMeta;
|
|
31
|
+
requestId?: string;
|
|
32
|
+
[key: string]: unknown;
|
|
33
|
+
}
|
|
34
|
+
type QueryValue = string | number | boolean | null | undefined;
|
|
35
|
+
type QueryParams = Record<string, QueryValue>;
|
|
36
|
+
interface HttpClientConfig {
|
|
37
|
+
/** The API access token, sent as the X-Access-Token header. */
|
|
38
|
+
key: string;
|
|
39
|
+
/** Trailing slash is optional; it is added if missing. */
|
|
40
|
+
baseUrl: string;
|
|
41
|
+
fetch: FetchLike;
|
|
42
|
+
timeoutMs: number;
|
|
43
|
+
retry: RetryConfig;
|
|
44
|
+
}
|
|
45
|
+
interface RequestOptions {
|
|
46
|
+
query?: QueryParams;
|
|
47
|
+
/** Serialized as JSON. Its presence is what adds the Content-Type header. */
|
|
48
|
+
body?: unknown;
|
|
49
|
+
/** Caller cancellation, merged with the per-request timeout. */
|
|
50
|
+
signal?: AbortSignal;
|
|
51
|
+
}
|
|
52
|
+
declare class HttpClient {
|
|
53
|
+
private readonly config;
|
|
54
|
+
constructor(config: HttpClientConfig);
|
|
55
|
+
/**
|
|
56
|
+
* Send a request and return the unwrapped envelope.
|
|
57
|
+
*
|
|
58
|
+
* Retry policy is deliberately narrow. A 429 is always safe to retry, since
|
|
59
|
+
* the request was rejected before processing. A 5xx or a dropped connection is
|
|
60
|
+
* retried only for GET: a send that timed out may still have gone through, and
|
|
61
|
+
* a blind retry could charge the account twice. Use a `ref` for safe resends.
|
|
62
|
+
*/
|
|
63
|
+
request<T>(method: HttpMethod, path: string, options?: RequestOptions): Promise<Envelope<T>>;
|
|
64
|
+
private retryable;
|
|
65
|
+
/** Wait the API's Retry-After when offered, otherwise an exponential backoff. */
|
|
66
|
+
private backoffMs;
|
|
67
|
+
private send;
|
|
68
|
+
/** Confirm the body is a success envelope before handing it back. */
|
|
69
|
+
private toEnvelope;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* One page of a list, plus a `next()` that fetches the page after it. `next()`
|
|
74
|
+
* resolves to undefined once there is nothing more, so a `while (page)` loop ends
|
|
75
|
+
* cleanly.
|
|
76
|
+
*/
|
|
77
|
+
interface Page<T> extends Pagination {
|
|
78
|
+
items: T[];
|
|
79
|
+
/** True while a further page exists. */
|
|
80
|
+
hasMore: boolean;
|
|
81
|
+
/** The next page, or undefined when this is the last one. */
|
|
82
|
+
next(): Promise<Page<T> | undefined>;
|
|
83
|
+
}
|
|
84
|
+
declare abstract class Resource {
|
|
85
|
+
protected readonly http: HttpClient;
|
|
86
|
+
constructor(http: HttpClient);
|
|
87
|
+
/** GET a path and return its `data` payload. */
|
|
88
|
+
protected getData<T>(path: string, query?: QueryParams, signal?: AbortSignal): Promise<T>;
|
|
89
|
+
/** POST a body and return the `data` payload. */
|
|
90
|
+
protected postData<T>(path: string, body: unknown, signal?: AbortSignal): Promise<T>;
|
|
91
|
+
/**
|
|
92
|
+
* Fetch one page of a list. `extract` pulls the items and the pagination block
|
|
93
|
+
* out of whatever shape the endpoint nests them in; it gets the whole envelope
|
|
94
|
+
* because some endpoints keep pagination in `data` and others in `meta`.
|
|
95
|
+
* `next()` reissues the same request with the page number bumped.
|
|
96
|
+
*/
|
|
97
|
+
protected fetchPage<T>(path: string, query: QueryParams, extract: (env: Envelope<unknown>) => {
|
|
98
|
+
items: T[];
|
|
99
|
+
pagination: Pagination;
|
|
100
|
+
}): Promise<Page<T>>;
|
|
101
|
+
/** Walk every item across every page, starting from a first-page promise. */
|
|
102
|
+
protected iterate<T>(first: Promise<Page<T>>): AsyncGenerator<T>;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Where a mobile or internet top-up sits in its lifecycle. PENDING and HANDLING
|
|
107
|
+
* are in-flight; the rest are final. QUEUED only appears for internet orders.
|
|
108
|
+
* UNKNOWN_ERROR means the outcome is undecided and can still settle within 24h,
|
|
109
|
+
* which is why a top-up should not be treated as failed the moment it shows up.
|
|
110
|
+
*/
|
|
111
|
+
type TopupStatus = "PENDING" | "HANDLING" | "QUEUED" | "FULFILLED" | "REFUNDED" | "UNKNOWN_ERROR";
|
|
112
|
+
/** A gift-card order's lifecycle. PARTIALLY_FILLED means some cards came through. */
|
|
113
|
+
type GiftOrderStatus = "HANDLING" | "FULFILLED" | "PARTIALLY_FILLED" | "REFUNDED";
|
|
114
|
+
/** A Navio payment link's lifecycle. */
|
|
115
|
+
type PaymentStatus = "PENDING" | "CONFIRMED" | "FAILED";
|
|
116
|
+
/** The top-up statuses at which polling stops. */
|
|
117
|
+
declare const TOPUP_TERMINAL: readonly TopupStatus[];
|
|
118
|
+
/** The gift-card order statuses at which polling stops. */
|
|
119
|
+
declare const GIFT_TERMINAL: readonly GiftOrderStatus[];
|
|
120
|
+
/** The payment statuses at which polling stops. */
|
|
121
|
+
declare const PAYMENT_TERMINAL: readonly PaymentStatus[];
|
|
122
|
+
type KeyType = "SANDBOX" | "PRODUCTION";
|
|
123
|
+
type KeyScope = "READ-WRITE" | "READ-ONLY";
|
|
124
|
+
interface ApiKeyInfo {
|
|
125
|
+
key: string;
|
|
126
|
+
isEnabled: boolean;
|
|
127
|
+
type: KeyType;
|
|
128
|
+
/** Allowed source IPs. An empty array means any IP is accepted. */
|
|
129
|
+
allowedips: string[];
|
|
130
|
+
scope: KeyScope;
|
|
131
|
+
}
|
|
132
|
+
/** What `validate()` returns: the account name and the key's own settings. */
|
|
133
|
+
interface ValidateResult {
|
|
134
|
+
username: string;
|
|
135
|
+
apiKey: ApiKeyInfo;
|
|
136
|
+
}
|
|
137
|
+
/** What `ping()` returns: the API's own status and each operator's reachability. */
|
|
138
|
+
interface ServiceHealth {
|
|
139
|
+
api: string;
|
|
140
|
+
operators: Record<string, string>;
|
|
141
|
+
}
|
|
142
|
+
interface Balance {
|
|
143
|
+
/** Current account balance in dinars. */
|
|
144
|
+
balance: number;
|
|
145
|
+
}
|
|
146
|
+
interface Transaction {
|
|
147
|
+
_id: string;
|
|
148
|
+
/** The kind of movement, such as a top-up or a deposit. */
|
|
149
|
+
type: string;
|
|
150
|
+
/** The direction of the movement: increment or decrement. */
|
|
151
|
+
operation: string;
|
|
152
|
+
amount: number;
|
|
153
|
+
oldBalance: number;
|
|
154
|
+
newBalance: number;
|
|
155
|
+
/** The id of the related order, when there is one. */
|
|
156
|
+
objid: string;
|
|
157
|
+
note: string;
|
|
158
|
+
time: string;
|
|
159
|
+
}
|
|
160
|
+
interface TransactionsParams {
|
|
161
|
+
page?: number;
|
|
162
|
+
pageSize?: number;
|
|
163
|
+
/** ISO 8601 start of the date filter. Pass `to` alongside it. */
|
|
164
|
+
from?: string;
|
|
165
|
+
/** ISO 8601 end of the date filter. Pass `from` alongside it. */
|
|
166
|
+
to?: string;
|
|
167
|
+
}
|
|
168
|
+
/** A paginated `{ items, pagination }` payload, the shape list endpoints return. */
|
|
169
|
+
interface ItemsPage<T> {
|
|
170
|
+
items: T[];
|
|
171
|
+
pagination: Pagination;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
declare class Core extends Resource {
|
|
175
|
+
/** Check the API and each operator's reachability. */
|
|
176
|
+
ping(signal?: AbortSignal): Promise<ServiceHealth>;
|
|
177
|
+
/** Confirm the key and read its environment, scope, and IP allowlist. */
|
|
178
|
+
validate(signal?: AbortSignal): Promise<ValidateResult>;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
declare class Account extends Resource {
|
|
182
|
+
/** The current balance in dinars. */
|
|
183
|
+
balance(signal?: AbortSignal): Promise<Balance>;
|
|
184
|
+
/** One page of the transaction ledger, newest first. */
|
|
185
|
+
transactions(params?: TransactionsParams): Promise<Page<Transaction>>;
|
|
186
|
+
/** Every transaction across every page, as an async iterator. */
|
|
187
|
+
paginateTransactions(params?: TransactionsParams): AsyncGenerator<Transaction>;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* The machine-readable error codes. The API's own codes are kept verbatim so
|
|
192
|
+
* `error.code` matches what the docs list. `network` is the one code the client
|
|
193
|
+
* adds itself, for a request that never reached the server.
|
|
194
|
+
*/
|
|
195
|
+
type OneClickErrorCode = "MISSING_ACCESS_TOKEN" | "INVALID_ACCESS_TOKEN" | "ERR_AUTH" | "NO_BALANCE" | "INSUFFICIENT_BALANCE" | "DUPLICATED_REF" | "IP_BLOCKED" | "IP_NOT_ALLOWED" | "ERR_VALIDATION" | "ERR_PHONE" | "ERR_STOCK" | "NOT_FOUND" | "RATE_LIMIT_EXCEEDED" | "INTERNAL_SERVER_ERROR" | "INTERNAL_ERROR" | "ERR_SERVICE" | "network" | (string & {});
|
|
196
|
+
interface OneClickErrorOptions {
|
|
197
|
+
status?: number;
|
|
198
|
+
/** The `error.details` object the API attaches to some failures. */
|
|
199
|
+
details?: unknown;
|
|
200
|
+
/** The request id from the envelope, handy when opening a support ticket. */
|
|
201
|
+
requestId?: string;
|
|
202
|
+
/** The full parsed response body, kept so callers can read everything. */
|
|
203
|
+
body?: unknown;
|
|
204
|
+
cause?: unknown;
|
|
205
|
+
}
|
|
206
|
+
declare class OneClickError extends Error {
|
|
207
|
+
/** HTTP status, or undefined for a client-side or network error. */
|
|
208
|
+
readonly status?: number;
|
|
209
|
+
readonly code: OneClickErrorCode;
|
|
210
|
+
readonly details: unknown;
|
|
211
|
+
readonly requestId?: string;
|
|
212
|
+
readonly body: unknown;
|
|
213
|
+
constructor(message: string, code: OneClickErrorCode, options?: OneClickErrorOptions);
|
|
214
|
+
}
|
|
215
|
+
/** 401. The key is missing, malformed, or rejected. */
|
|
216
|
+
declare class AuthError extends OneClickError {
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* 403. The key is valid but the action is not allowed: a blocked or unlisted IP,
|
|
220
|
+
* for instance. Balance and duplicate-ref cases have their own subclasses below
|
|
221
|
+
* so they can be caught on their own.
|
|
222
|
+
*/
|
|
223
|
+
declare class ForbiddenError extends OneClickError {
|
|
224
|
+
}
|
|
225
|
+
/** 403 with NO_BALANCE or INSUFFICIENT_BALANCE. Top up the account first. */
|
|
226
|
+
declare class InsufficientBalanceError extends ForbiddenError {
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* 403 with DUPLICATED_REF. The reference was already used, so the original order
|
|
230
|
+
* stands and nothing was charged twice. Look the first one up by its ref rather
|
|
231
|
+
* than sending again.
|
|
232
|
+
*/
|
|
233
|
+
declare class DuplicateRefError extends ForbiddenError {
|
|
234
|
+
}
|
|
235
|
+
interface ValidationIssue {
|
|
236
|
+
field: string;
|
|
237
|
+
message: string;
|
|
238
|
+
/** The order reference this issue belongs to, when checking a batch. */
|
|
239
|
+
ref?: string;
|
|
240
|
+
}
|
|
241
|
+
interface ValidationErrorOptions extends OneClickErrorOptions {
|
|
242
|
+
/** The API code for a server-side 400; defaults to ERR_VALIDATION. */
|
|
243
|
+
code?: OneClickErrorCode;
|
|
244
|
+
/** Filled when the client caught the problem before sending. */
|
|
245
|
+
issues?: ValidationIssue[];
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* A 400 from the API, or a client-side check. `issues` is filled when the client
|
|
249
|
+
* caught the problem before sending; for a server 400 it is empty and the detail
|
|
250
|
+
* sits in `code`, `message`, and `details`.
|
|
251
|
+
*/
|
|
252
|
+
declare class ValidationError extends OneClickError {
|
|
253
|
+
readonly issues: ValidationIssue[];
|
|
254
|
+
constructor(message: string, options?: ValidationErrorOptions);
|
|
255
|
+
}
|
|
256
|
+
/** 404. No order, product, or payment matches the id or reference. */
|
|
257
|
+
declare class NotFoundError extends OneClickError {
|
|
258
|
+
}
|
|
259
|
+
interface RateLimitErrorOptions extends OneClickErrorOptions {
|
|
260
|
+
/** Seconds to wait before retrying, read from the Retry-After header. */
|
|
261
|
+
retryAfter?: number;
|
|
262
|
+
}
|
|
263
|
+
/** 429. Too many requests inside the per-minute window. */
|
|
264
|
+
declare class RateLimitError extends OneClickError {
|
|
265
|
+
readonly retryAfter?: number;
|
|
266
|
+
constructor(message: string, options?: RateLimitErrorOptions);
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* 500 or 503. The request may or may not have been processed. For a top-up this
|
|
270
|
+
* matters: the docs say not to refund a server error for 24 hours, since the
|
|
271
|
+
* recharge can still settle. The client never auto-retries a send on a 5xx for
|
|
272
|
+
* the same reason.
|
|
273
|
+
*/
|
|
274
|
+
declare class ServiceError extends OneClickError {
|
|
275
|
+
}
|
|
276
|
+
/** The request never reached the server: DNS, socket, or a timeout abort. */
|
|
277
|
+
declare class NetworkError extends OneClickError {
|
|
278
|
+
constructor(message: string, options?: OneClickErrorOptions);
|
|
279
|
+
}
|
|
280
|
+
/** Any other 4xx the client does not model on its own. */
|
|
281
|
+
declare class RequestError extends OneClickError {
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Build the right error from a failed envelope. The API's `error.code` decides
|
|
285
|
+
* the class where we recognise it; otherwise the HTTP status does. The code is
|
|
286
|
+
* passed through verbatim so `error.code` matches the documentation.
|
|
287
|
+
*/
|
|
288
|
+
declare function errorFromResponse(status: number, body: unknown, retryAfter?: number): OneClickError;
|
|
289
|
+
|
|
290
|
+
interface PollOptions {
|
|
291
|
+
/** Milliseconds between checks. The docs recommend a fixed 5s. */
|
|
292
|
+
intervalMs?: number;
|
|
293
|
+
/** How many checks before giving up. */
|
|
294
|
+
maxAttempts?: number;
|
|
295
|
+
/** Cancel the wait early. The pending delay rejects at once when aborted. */
|
|
296
|
+
signal?: AbortSignal;
|
|
297
|
+
}
|
|
298
|
+
/** Raised when a status never reaches a terminal state within the attempt budget. */
|
|
299
|
+
declare class PollTimeoutError extends OneClickError {
|
|
300
|
+
/** The most recent value seen before time ran out. */
|
|
301
|
+
readonly last: unknown;
|
|
302
|
+
constructor(message: string, last: unknown, attempts: number);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Call `fetchOnce` until `isDone` accepts the result, then return that result.
|
|
306
|
+
* The first check happens immediately; the interval only applies between checks,
|
|
307
|
+
* so a status that is already settled returns without an extra wait.
|
|
308
|
+
*/
|
|
309
|
+
declare function pollUntil<T>(fetchOnce: () => Promise<T>, isDone: (value: T) => boolean, options?: PollOptions): Promise<T>;
|
|
310
|
+
|
|
311
|
+
interface MobilePlanBase {
|
|
312
|
+
code: string;
|
|
313
|
+
name: string;
|
|
314
|
+
operator: string;
|
|
315
|
+
/**
|
|
316
|
+
* Your wholesale cost factor. Absent on the wholesale `GROS_*` plans. Do not
|
|
317
|
+
* show it to end users; apply your own markup.
|
|
318
|
+
*/
|
|
319
|
+
cost?: number;
|
|
320
|
+
isEnabled: boolean;
|
|
321
|
+
}
|
|
322
|
+
/** A plan whose amount you choose, within a range. */
|
|
323
|
+
interface DynamicMobilePlan extends MobilePlanBase {
|
|
324
|
+
min_amount: number;
|
|
325
|
+
max_amount: number;
|
|
326
|
+
}
|
|
327
|
+
/** A plan with a fixed amount, such as a data pack. */
|
|
328
|
+
interface FixedMobilePlan extends MobilePlanBase {
|
|
329
|
+
amount: number;
|
|
330
|
+
}
|
|
331
|
+
interface MobilePlans {
|
|
332
|
+
dynamicPlans: DynamicMobilePlan[];
|
|
333
|
+
fixedPlans: FixedMobilePlan[];
|
|
334
|
+
}
|
|
335
|
+
interface MobileSendInput {
|
|
336
|
+
/** A plan code from `plans()`, such as `PREPAID_DJEZZY`. */
|
|
337
|
+
plan_code: string;
|
|
338
|
+
/** The recipient number: ten digits starting 05, 06, or 07. */
|
|
339
|
+
MSSIDN: string;
|
|
340
|
+
/** Required for dynamic plans, within the plan's min and max. */
|
|
341
|
+
amount?: number;
|
|
342
|
+
/** Your order reference. One is generated when omitted. */
|
|
343
|
+
ref?: string;
|
|
344
|
+
}
|
|
345
|
+
interface MobileSendResult {
|
|
346
|
+
topupId: string;
|
|
347
|
+
topupRef: string;
|
|
348
|
+
}
|
|
349
|
+
/** A retry the API suggests after a refund. */
|
|
350
|
+
interface SuggestedOffer {
|
|
351
|
+
typename: string;
|
|
352
|
+
plan_code: string;
|
|
353
|
+
amount: number;
|
|
354
|
+
}
|
|
355
|
+
interface MobileTopup {
|
|
356
|
+
_id: string;
|
|
357
|
+
ref?: string;
|
|
358
|
+
status: TopupStatus;
|
|
359
|
+
plan_code: string;
|
|
360
|
+
MSSIDN: string;
|
|
361
|
+
topup_amount: number;
|
|
362
|
+
balance_amount: number;
|
|
363
|
+
created_at: string;
|
|
364
|
+
/** Present on a REFUNDED order, explaining why it did not go through. */
|
|
365
|
+
refund_message?: string;
|
|
366
|
+
/** Alternative offers to try after a refund. */
|
|
367
|
+
suggested_offers?: SuggestedOffer[];
|
|
368
|
+
follow_orderid?: string;
|
|
369
|
+
retry_orderid?: string;
|
|
370
|
+
}
|
|
371
|
+
interface MobileListParams {
|
|
372
|
+
page?: number;
|
|
373
|
+
pageSize?: number;
|
|
374
|
+
from?: string;
|
|
375
|
+
to?: string;
|
|
376
|
+
}
|
|
377
|
+
declare class Mobile extends Resource {
|
|
378
|
+
/** The plans available to your account, split into dynamic and fixed. */
|
|
379
|
+
plans(signal?: AbortSignal): Promise<MobilePlans>;
|
|
380
|
+
/**
|
|
381
|
+
* Send a top-up. The number and amount are checked first, and a reference is
|
|
382
|
+
* generated when you do not pass one, so the returned `topupRef` is always set.
|
|
383
|
+
*/
|
|
384
|
+
send(input: MobileSendInput, signal?: AbortSignal): Promise<MobileSendResult>;
|
|
385
|
+
/** Look a top-up up by your own reference. */
|
|
386
|
+
checkByRef(ref: string, signal?: AbortSignal): Promise<MobileTopup>;
|
|
387
|
+
/** Look a top-up up by the id from `send`. */
|
|
388
|
+
checkById(id: string, signal?: AbortSignal): Promise<MobileTopup>;
|
|
389
|
+
/**
|
|
390
|
+
* Send a top-up and wait for it to settle, polling by reference. Resolves with
|
|
391
|
+
* the final top-up once it is FULFILLED, REFUNDED, or UNKNOWN_ERROR. Defaults
|
|
392
|
+
* to a check every 5 seconds for up to 5 minutes, which the docs recommend.
|
|
393
|
+
*/
|
|
394
|
+
sendAndWait(input: MobileSendInput, options?: PollOptions): Promise<MobileTopup>;
|
|
395
|
+
/** One page of your past top-ups, newest first. */
|
|
396
|
+
list(params?: MobileListParams): Promise<Page<MobileTopup>>;
|
|
397
|
+
/** Every past top-up across every page, as an async iterator. */
|
|
398
|
+
paginate(params?: MobileListParams): AsyncGenerator<MobileTopup>;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
declare const INSPECT: unique symbol;
|
|
402
|
+
declare class Secret<T = string> {
|
|
403
|
+
#private;
|
|
404
|
+
constructor(value: T);
|
|
405
|
+
/** The real value. Calling this is the deliberate, searchable moment a secret is read. */
|
|
406
|
+
reveal(): T;
|
|
407
|
+
/** Used by JSON.stringify, so a secret nested in an object serializes redacted. */
|
|
408
|
+
toJSON(): string;
|
|
409
|
+
toString(): string;
|
|
410
|
+
[INSPECT](): string;
|
|
411
|
+
static of<T>(value: T): Secret<T>;
|
|
412
|
+
}
|
|
413
|
+
declare function isSecret(value: unknown): value is Secret<unknown>;
|
|
414
|
+
/** Reveal a value whether or not it is wrapped, for code that handles both. */
|
|
415
|
+
declare function reveal<T>(value: Secret<T> | T): T;
|
|
416
|
+
|
|
417
|
+
type InternetType = "ADSL" | "4G";
|
|
418
|
+
interface InternetProduct {
|
|
419
|
+
/** Your wholesale cost. Strip this before showing products to end users. */
|
|
420
|
+
cost: number;
|
|
421
|
+
/** The card's face value in dinars. */
|
|
422
|
+
value: number;
|
|
423
|
+
available: boolean;
|
|
424
|
+
}
|
|
425
|
+
interface InternetProducts {
|
|
426
|
+
products: InternetProduct[];
|
|
427
|
+
type: string;
|
|
428
|
+
}
|
|
429
|
+
interface NumberCheck {
|
|
430
|
+
/** The masked client identifier the API returns for a valid line. */
|
|
431
|
+
ncli: string;
|
|
432
|
+
type: string;
|
|
433
|
+
/** The current offer, for ADSL lines. */
|
|
434
|
+
offre?: string;
|
|
435
|
+
}
|
|
436
|
+
interface InternetSendInput {
|
|
437
|
+
type: InternetType;
|
|
438
|
+
/** ADSL: nine digits starting 0. 4G: 213 followed by nine digits. */
|
|
439
|
+
number: string;
|
|
440
|
+
/** A face value from `products()`. */
|
|
441
|
+
value: number;
|
|
442
|
+
/** Your order reference. One is generated when omitted. */
|
|
443
|
+
ref?: string;
|
|
444
|
+
}
|
|
445
|
+
interface InternetSendResult {
|
|
446
|
+
topupId: string;
|
|
447
|
+
topupRef: string;
|
|
448
|
+
}
|
|
449
|
+
interface InternetTopup {
|
|
450
|
+
_id: string;
|
|
451
|
+
ref?: string;
|
|
452
|
+
status: TopupStatus;
|
|
453
|
+
type: string;
|
|
454
|
+
number: string;
|
|
455
|
+
topup_amount: number;
|
|
456
|
+
/** The recharge code, present once FULFILLED. Call `.reveal()` to read it. */
|
|
457
|
+
card_code?: Secret<string>;
|
|
458
|
+
num_trans?: string;
|
|
459
|
+
date_traitement?: string;
|
|
460
|
+
created_at: string;
|
|
461
|
+
}
|
|
462
|
+
interface InternetListParams {
|
|
463
|
+
page?: number;
|
|
464
|
+
pageSize?: number;
|
|
465
|
+
from?: string;
|
|
466
|
+
to?: string;
|
|
467
|
+
}
|
|
468
|
+
declare class Internet extends Resource {
|
|
469
|
+
/** The cards on offer for a service type, with their cost and stock. */
|
|
470
|
+
products(type: InternetType, signal?: AbortSignal): Promise<InternetProducts>;
|
|
471
|
+
/** Confirm a number is valid and active before sending to it. */
|
|
472
|
+
checkNumber(type: InternetType, number: string, signal?: AbortSignal): Promise<NumberCheck>;
|
|
473
|
+
/** Send a recharge. The number and value are checked first; a ref is filled in. */
|
|
474
|
+
send(input: InternetSendInput, signal?: AbortSignal): Promise<InternetSendResult>;
|
|
475
|
+
checkByRef(ref: string, signal?: AbortSignal): Promise<InternetTopup>;
|
|
476
|
+
checkById(id: string, signal?: AbortSignal): Promise<InternetTopup>;
|
|
477
|
+
/**
|
|
478
|
+
* Send and wait for the recharge to settle. Resolves with the final order,
|
|
479
|
+
* its `card_code` ready to reveal once FULFILLED. A QUEUED order can take up to
|
|
480
|
+
* 48 hours, well past the default polling window, so expect a timeout there.
|
|
481
|
+
*/
|
|
482
|
+
sendAndWait(input: InternetSendInput, options?: PollOptions): Promise<InternetTopup>;
|
|
483
|
+
list(params?: InternetListParams): Promise<Page<InternetTopup>>;
|
|
484
|
+
paginate(params?: InternetListParams): AsyncGenerator<InternetTopup>;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
interface GiftProductSummary {
|
|
488
|
+
id: string;
|
|
489
|
+
title: string;
|
|
490
|
+
enabled: boolean;
|
|
491
|
+
/** The region the product is valid in, such as france or turkey. Absent on some products. */
|
|
492
|
+
region?: string;
|
|
493
|
+
}
|
|
494
|
+
interface GiftCategory {
|
|
495
|
+
title: string;
|
|
496
|
+
products: GiftProductSummary[];
|
|
497
|
+
}
|
|
498
|
+
interface GiftCatalog {
|
|
499
|
+
categories: GiftCategory[];
|
|
500
|
+
totalCategories?: number;
|
|
501
|
+
totalProducts?: number;
|
|
502
|
+
}
|
|
503
|
+
interface GiftProductType {
|
|
504
|
+
id: string;
|
|
505
|
+
/** The denomination label, such as "PSN 500 DA". */
|
|
506
|
+
name: string;
|
|
507
|
+
/** Your wholesale price. Do not show it to end users. */
|
|
508
|
+
price: number;
|
|
509
|
+
/** Stock on hand. Zero means out of stock. */
|
|
510
|
+
quantity: number;
|
|
511
|
+
}
|
|
512
|
+
interface GiftProductDetails {
|
|
513
|
+
productId: string;
|
|
514
|
+
productTitle: string;
|
|
515
|
+
types: GiftProductType[];
|
|
516
|
+
}
|
|
517
|
+
interface GiftOrderInput {
|
|
518
|
+
/** A product id from the catalog. */
|
|
519
|
+
productId: string;
|
|
520
|
+
/** A type id from `checkProduct`. */
|
|
521
|
+
typeId: string;
|
|
522
|
+
/** How many cards to buy. At least one. */
|
|
523
|
+
quantity: number;
|
|
524
|
+
}
|
|
525
|
+
interface GiftOrderResult {
|
|
526
|
+
orderId: string;
|
|
527
|
+
}
|
|
528
|
+
/** A delivered card. Both fields are secrets; call `.reveal()` to read them. */
|
|
529
|
+
interface GiftCard {
|
|
530
|
+
value: Secret<string>;
|
|
531
|
+
serial: Secret<string>;
|
|
532
|
+
}
|
|
533
|
+
interface GiftOrder {
|
|
534
|
+
status: GiftOrderStatus;
|
|
535
|
+
quantity: number;
|
|
536
|
+
fulfilled_quantity: number;
|
|
537
|
+
fulfilled_amount: number;
|
|
538
|
+
price_per_card: number;
|
|
539
|
+
/** Filled once the order is FULFILLED or PARTIALLY_FILLED. */
|
|
540
|
+
cards: GiftCard[];
|
|
541
|
+
/** Present in the order list; the single-order check omits these. */
|
|
542
|
+
_id?: string;
|
|
543
|
+
product?: string;
|
|
544
|
+
type?: string;
|
|
545
|
+
time?: string;
|
|
546
|
+
}
|
|
547
|
+
interface GiftOrdersParams {
|
|
548
|
+
page?: number;
|
|
549
|
+
pageSize?: number;
|
|
550
|
+
from?: string;
|
|
551
|
+
to?: string;
|
|
552
|
+
}
|
|
553
|
+
declare class GiftCards extends Resource {
|
|
554
|
+
/** The full product catalog. Cache it; the docs say it changes rarely. */
|
|
555
|
+
catalog(signal?: AbortSignal): Promise<GiftCatalog>;
|
|
556
|
+
/** A product's denominations, with live pricing and stock. */
|
|
557
|
+
checkProduct(productId: string, signal?: AbortSignal): Promise<GiftProductDetails>;
|
|
558
|
+
/** Place an order. The product, type, and quantity are checked first. */
|
|
559
|
+
placeOrder(input: GiftOrderInput, signal?: AbortSignal): Promise<GiftOrderResult>;
|
|
560
|
+
/** Read an order's status and, once settled, its cards. */
|
|
561
|
+
checkOrder(orderId: string, signal?: AbortSignal): Promise<GiftOrder>;
|
|
562
|
+
/**
|
|
563
|
+
* Place an order and wait for it to settle. Resolves once the order is
|
|
564
|
+
* FULFILLED, PARTIALLY_FILLED, or REFUNDED. Gift cards can take longer than a
|
|
565
|
+
* top-up, so this checks every 5 seconds for up to 10 minutes by default.
|
|
566
|
+
*/
|
|
567
|
+
placeOrderAndWait(input: GiftOrderInput, options?: PollOptions): Promise<GiftOrder>;
|
|
568
|
+
/** One page of past orders, newest first. */
|
|
569
|
+
listOrders(params?: GiftOrdersParams): Promise<Page<GiftOrder>>;
|
|
570
|
+
/** Every past order across every page, as an async iterator. */
|
|
571
|
+
paginateOrders(params?: GiftOrdersParams): AsyncGenerator<GiftOrder>;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
/** Who pays the gateway fee. NO_FEE is the default. */
|
|
575
|
+
type FeeMode = "NO_FEE" | "SPLIT_FEE" | "CUSTOMER_FEE";
|
|
576
|
+
declare const MIN_PAYMENT_AMOUNT = 500;
|
|
577
|
+
declare const MAX_PAYMENT_AMOUNT = 500000;
|
|
578
|
+
interface PaymentProductInfo {
|
|
579
|
+
/** What the customer is paying for. One to two hundred characters. */
|
|
580
|
+
title: string;
|
|
581
|
+
/** Optional details, up to a thousand characters. Markdown is allowed. */
|
|
582
|
+
description?: string;
|
|
583
|
+
/** Amount in dinars: a whole number from 500 to 500000. */
|
|
584
|
+
amount: number;
|
|
585
|
+
}
|
|
586
|
+
interface CreateLinkInput {
|
|
587
|
+
productInfo: PaymentProductInfo;
|
|
588
|
+
feeMode?: FeeMode;
|
|
589
|
+
/** Shown to the customer after a successful payment, up to 500 characters. */
|
|
590
|
+
successMessage?: string;
|
|
591
|
+
/** Where to send the customer after payment. Must be http or https. */
|
|
592
|
+
redirectUrl?: string;
|
|
593
|
+
}
|
|
594
|
+
interface PaymentLink {
|
|
595
|
+
uid: string;
|
|
596
|
+
ref: string;
|
|
597
|
+
isSandbox: boolean;
|
|
598
|
+
productInfo: PaymentProductInfo;
|
|
599
|
+
feeMode: FeeMode;
|
|
600
|
+
successMessage?: string;
|
|
601
|
+
redirectUrl?: string;
|
|
602
|
+
time: string;
|
|
603
|
+
}
|
|
604
|
+
interface CreateLinkResult {
|
|
605
|
+
paymentLink: PaymentLink;
|
|
606
|
+
/** The URL to send the customer to. */
|
|
607
|
+
paymentUrl: string;
|
|
608
|
+
/** The reference to poll with `checkPayment`. */
|
|
609
|
+
paymentRef: string;
|
|
610
|
+
}
|
|
611
|
+
interface PaymentTransactionDetails {
|
|
612
|
+
amount: number;
|
|
613
|
+
currency: string;
|
|
614
|
+
isSandbox: boolean;
|
|
615
|
+
createdDate: string;
|
|
616
|
+
}
|
|
617
|
+
interface PaymentCheck {
|
|
618
|
+
status: PaymentStatus;
|
|
619
|
+
message: string;
|
|
620
|
+
paymentRef: string;
|
|
621
|
+
transactionDetails: PaymentTransactionDetails;
|
|
622
|
+
}
|
|
623
|
+
declare class Payments extends Resource {
|
|
624
|
+
/** Create a payment link. Returns the URL to send the customer to. */
|
|
625
|
+
createLink(input: CreateLinkInput, signal?: AbortSignal): Promise<CreateLinkResult>;
|
|
626
|
+
/** Check a payment's status by its reference. */
|
|
627
|
+
checkPayment(ref: string, signal?: AbortSignal): Promise<PaymentCheck>;
|
|
628
|
+
/**
|
|
629
|
+
* Poll a payment until it is CONFIRMED or FAILED. The default window is twenty
|
|
630
|
+
* minutes, matching how long an unpaid link stays open; a payment that is
|
|
631
|
+
* never started times out with a PollTimeoutError. Pass a signal to stop early.
|
|
632
|
+
*/
|
|
633
|
+
waitForPayment(ref: string, options?: PollOptions): Promise<PaymentCheck>;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
interface OneClickDZOptions {
|
|
637
|
+
/** Your access token, sandbox or production, from the dashboard. */
|
|
638
|
+
key: string;
|
|
639
|
+
/** Defaults to the production v3 endpoint. */
|
|
640
|
+
baseUrl?: string;
|
|
641
|
+
/** Per-request timeout in milliseconds. Defaults to 30000. */
|
|
642
|
+
timeoutMs?: number;
|
|
643
|
+
/** Override either retry field; the rest keep their defaults. */
|
|
644
|
+
retry?: Partial<RetryConfig>;
|
|
645
|
+
/** Supply a fetch for older runtimes or for tests. Defaults to the global. */
|
|
646
|
+
fetch?: FetchLike;
|
|
647
|
+
}
|
|
648
|
+
declare class OneClickDZ {
|
|
649
|
+
readonly core: Core;
|
|
650
|
+
readonly account: Account;
|
|
651
|
+
readonly mobile: Mobile;
|
|
652
|
+
readonly internet: Internet;
|
|
653
|
+
readonly giftCards: GiftCards;
|
|
654
|
+
readonly payments: Payments;
|
|
655
|
+
private readonly http;
|
|
656
|
+
constructor(options: OneClickDZOptions);
|
|
657
|
+
/** Shortcut for `core.ping()`: the API and operator status. */
|
|
658
|
+
ping(signal?: AbortSignal): Promise<ServiceHealth>;
|
|
659
|
+
/** Shortcut for `core.validate()`: confirm the key and read its environment. */
|
|
660
|
+
validate(signal?: AbortSignal): Promise<ValidateResult>;
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
/** Mobile MSISDN: Mobilis, Djezzy, or Ooredoo, ten digits starting 05, 06, or 07. */
|
|
664
|
+
declare const MOBILE_NUMBER: RegExp;
|
|
665
|
+
/** ADSL line number: nine digits starting with 0. */
|
|
666
|
+
declare const ADSL_NUMBER: RegExp;
|
|
667
|
+
/** 4G number: the 213 country code followed by nine digits. */
|
|
668
|
+
declare const FOURG_NUMBER: RegExp;
|
|
669
|
+
declare function isMobileNumber(value: string): boolean;
|
|
670
|
+
declare function isAdslNumber(value: string): boolean;
|
|
671
|
+
declare function isFourgNumber(value: string): boolean;
|
|
672
|
+
/** A whole number of dinars, at or above one. The API has no fractional amounts. */
|
|
673
|
+
declare function isWholeAmount(value: unknown): value is number;
|
|
674
|
+
/**
|
|
675
|
+
* Gathers field problems and turns them into one ValidationError. Using a
|
|
676
|
+
* collector rather than throwing on the first issue means a caller sees every
|
|
677
|
+
* problem with an input at once.
|
|
678
|
+
*/
|
|
679
|
+
declare class Issues {
|
|
680
|
+
private readonly list;
|
|
681
|
+
/** Record a problem. The ref ties an issue to one order when checking a batch. */
|
|
682
|
+
add(field: string, message: string, ref?: string): this;
|
|
683
|
+
/** Record a problem only when the condition holds. */
|
|
684
|
+
addIf(condition: boolean, field: string, message: string, ref?: string): this;
|
|
685
|
+
get any(): boolean;
|
|
686
|
+
all(): ValidationIssue[];
|
|
687
|
+
/** Throw if anything was collected; otherwise do nothing. */
|
|
688
|
+
throwIfAny(summary?: string): void;
|
|
689
|
+
}
|
|
690
|
+
/** A required string field that must be present and non-empty. */
|
|
691
|
+
declare function requireText(issues: Issues, value: unknown, field: string, ref?: string): void;
|
|
692
|
+
|
|
693
|
+
/** Build a unique-enough order reference with a readable prefix. */
|
|
694
|
+
declare function generateRef(prefix?: string): string;
|
|
695
|
+
|
|
696
|
+
/** A markup as a percentage of cost, or a flat number of dinars added on top. */
|
|
697
|
+
type Markup = {
|
|
698
|
+
percent: number;
|
|
699
|
+
} | {
|
|
700
|
+
flat: number;
|
|
701
|
+
};
|
|
702
|
+
/** Apply a markup to a wholesale cost and round to a whole dinar. */
|
|
703
|
+
declare function sellPrice(cost: number, markup: Markup): number;
|
|
704
|
+
/** An internet product as a customer should see it: face value, sell price, stock. */
|
|
705
|
+
interface CustomerInternetProduct {
|
|
706
|
+
value: number;
|
|
707
|
+
price: number;
|
|
708
|
+
available: boolean;
|
|
709
|
+
}
|
|
710
|
+
/**
|
|
711
|
+
* Turn the raw internet products into a customer-facing list. The wholesale
|
|
712
|
+
* `cost` is dropped and `price` is your sell price for the card's face value.
|
|
713
|
+
*/
|
|
714
|
+
declare function priceInternetProducts(products: InternetProduct[], markup: Markup): CustomerInternetProduct[];
|
|
715
|
+
/** A gift-card denomination as a customer should see it, with cost removed. */
|
|
716
|
+
interface CustomerGiftType {
|
|
717
|
+
id: string;
|
|
718
|
+
name: string;
|
|
719
|
+
price: number;
|
|
720
|
+
inStock: boolean;
|
|
721
|
+
}
|
|
722
|
+
/**
|
|
723
|
+
* Turn a product's types into a customer-facing list. The wholesale `price` is
|
|
724
|
+
* replaced by your sell price, and stock collapses to a single boolean.
|
|
725
|
+
*/
|
|
726
|
+
declare function priceGiftTypes(types: GiftProductType[], markup: Markup): CustomerGiftType[];
|
|
727
|
+
|
|
728
|
+
declare const VERSION = "0.1.0";
|
|
729
|
+
|
|
730
|
+
export { ADSL_NUMBER, Account, type ApiKeyInfo, AuthError, type Balance, Core, type CreateLinkInput, type CreateLinkResult, type CustomerGiftType, type CustomerInternetProduct, DuplicateRefError, type DynamicMobilePlan, type Envelope, FOURG_NUMBER, type FeeMode, type FetchLike, type FixedMobilePlan, ForbiddenError, GIFT_TERMINAL, type GiftCard, GiftCards, type GiftCatalog, type GiftCategory, type GiftOrder, type GiftOrderInput, type GiftOrderResult, type GiftOrderStatus, type GiftOrdersParams, type GiftProductDetails, type GiftProductSummary, type GiftProductType, type HttpMethod, InsufficientBalanceError, Internet, type InternetListParams, type InternetProduct, type InternetProducts, type InternetSendInput, type InternetSendResult, type InternetTopup, type InternetType, Issues, type ItemsPage, type KeyScope, type KeyType, MAX_PAYMENT_AMOUNT, MIN_PAYMENT_AMOUNT, MOBILE_NUMBER, type Markup, Mobile, type MobileListParams, type MobilePlans, type MobileSendInput, type MobileSendResult, type MobileTopup, NetworkError, NotFoundError, type NumberCheck, OneClickDZ, type OneClickDZOptions, OneClickError, type OneClickErrorCode, type OneClickErrorOptions, PAYMENT_TERMINAL, type Page, type Pagination, type PaymentCheck, type PaymentLink, type PaymentProductInfo, type PaymentStatus, type PaymentTransactionDetails, Payments, type PollOptions, PollTimeoutError, RateLimitError, type RateLimitErrorOptions, RequestError, type ResponseMeta, type RetryConfig, Secret, ServiceError, type ServiceHealth, type SuggestedOffer, TOPUP_TERMINAL, type TopupStatus, type Transaction, type TransactionsParams, VERSION, type ValidateResult, ValidationError, type ValidationErrorOptions, type ValidationIssue, errorFromResponse, generateRef, isAdslNumber, isFourgNumber, isMobileNumber, isSecret, isWholeAmount, pollUntil, priceGiftTypes, priceInternetProducts, requireText, reveal, sellPrice };
|