@koolbase/core 11.4.0 → 12.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/dist/cjs/aggregate.d.ts +115 -0
- package/dist/cjs/aggregate.js +26 -0
- package/dist/cjs/auth-errors.d.ts +8 -0
- package/dist/cjs/auth-errors.js +27 -14
- package/dist/cjs/auth.d.ts +130 -7
- package/dist/cjs/auth.js +252 -10
- package/dist/cjs/database-errors.d.ts +46 -0
- package/dist/cjs/database-errors.js +71 -1
- package/dist/cjs/database.d.ts +23 -0
- package/dist/cjs/database.js +64 -0
- package/dist/cjs/device-metadata.js +7 -1
- package/dist/cjs/fiscal.d.ts +114 -0
- package/dist/cjs/fiscal.js +167 -0
- package/dist/cjs/index.d.ts +3 -0
- package/dist/cjs/index.js +8 -1
- package/dist/cjs/types.d.ts +58 -0
- package/dist/esm/aggregate.d.ts +115 -0
- package/dist/esm/aggregate.js +25 -0
- package/dist/esm/auth-errors.d.ts +8 -0
- package/dist/esm/auth-errors.js +25 -13
- package/dist/esm/auth.d.ts +130 -7
- package/dist/esm/auth.js +253 -11
- package/dist/esm/database-errors.d.ts +46 -0
- package/dist/esm/database-errors.js +66 -0
- package/dist/esm/database.d.ts +23 -0
- package/dist/esm/database.js +64 -0
- package/dist/esm/device-metadata.js +7 -1
- package/dist/esm/fiscal.d.ts +114 -0
- package/dist/esm/fiscal.js +159 -0
- package/dist/esm/index.d.ts +3 -0
- package/dist/esm/index.js +2 -0
- package/dist/esm/types.d.ts +58 -0
- package/package.json +1 -1
package/dist/esm/database.js
CHANGED
|
@@ -421,6 +421,70 @@ export class KoolbaseDatabase {
|
|
|
421
421
|
const { pending } = await readOfflineState(userId);
|
|
422
422
|
return pending.map(toPendingWrite);
|
|
423
423
|
}
|
|
424
|
+
/**
|
|
425
|
+
* Count and total over a whole collection, with the read rule applied
|
|
426
|
+
* inside the query.
|
|
427
|
+
*
|
|
428
|
+
* Not a paged query you add up yourself: the server aggregates the entire
|
|
429
|
+
* authorized set. And never a bare number — collections are schemaless, so
|
|
430
|
+
* a sum that quietly skipped three malformed rows would be a wrong number
|
|
431
|
+
* that looks right. Check `accounting` for what contributed.
|
|
432
|
+
*
|
|
433
|
+
* ```ts
|
|
434
|
+
* const r = await db.aggregate({
|
|
435
|
+
* collection: 'orders',
|
|
436
|
+
* groupBy: { field: 'created_at', bucket: 'month', timezone: 'Africa/Accra' },
|
|
437
|
+
* measures: [{ aggregate: 'sum', field: 'total', as: 'revenue' }],
|
|
438
|
+
* });
|
|
439
|
+
* ```
|
|
440
|
+
*
|
|
441
|
+
* A calendar bucket requires a timezone and the types enforce it: midnight
|
|
442
|
+
* means nothing without one, and Accra and UTC disagree about which day a
|
|
443
|
+
* 23:30 sale belongs to.
|
|
444
|
+
*/
|
|
445
|
+
async aggregate(request) {
|
|
446
|
+
const raw = await this.request('POST', '/v1/sdk/db/aggregate', {
|
|
447
|
+
collection: request.collection,
|
|
448
|
+
...(request.where?.length ? { where: request.where } : {}),
|
|
449
|
+
...(request.groupBy
|
|
450
|
+
? {
|
|
451
|
+
group_by: {
|
|
452
|
+
field: request.groupBy.field,
|
|
453
|
+
...(request.groupBy.bucket
|
|
454
|
+
? {
|
|
455
|
+
bucket: request.groupBy.bucket,
|
|
456
|
+
timezone: request.groupBy.timezone,
|
|
457
|
+
}
|
|
458
|
+
: {}),
|
|
459
|
+
},
|
|
460
|
+
}
|
|
461
|
+
: {}),
|
|
462
|
+
measures: request.measures.map((m) => ({
|
|
463
|
+
aggregate: m.aggregate,
|
|
464
|
+
...(m.field ? { field: m.field } : {}),
|
|
465
|
+
as: m.as,
|
|
466
|
+
})),
|
|
467
|
+
});
|
|
468
|
+
const accounting = {};
|
|
469
|
+
for (const [name, a] of Object.entries(raw.accounting ?? {})) {
|
|
470
|
+
accounting[name] = {
|
|
471
|
+
counted: Number(a.counted ?? 0),
|
|
472
|
+
skipped: Number(a.skipped ?? 0),
|
|
473
|
+
skippedReason: a.skipped_reason,
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
return {
|
|
477
|
+
groups: (raw.groups ?? []).map((g) => ({
|
|
478
|
+
category: String(g.category ?? ''),
|
|
479
|
+
values: g.values ?? {},
|
|
480
|
+
})),
|
|
481
|
+
matched: Number(raw.matched ?? 0),
|
|
482
|
+
accounting,
|
|
483
|
+
// Explicitly boolean: a missing field must read as false, not
|
|
484
|
+
// undefined, or `if (!r.tooManyGroups)` passes on a refused request.
|
|
485
|
+
tooManyGroups: raw.too_many_groups === true,
|
|
486
|
+
};
|
|
487
|
+
}
|
|
424
488
|
async conflicts() {
|
|
425
489
|
const userId = this.requireUserId('the conflict list');
|
|
426
490
|
const { conflicts } = await readOfflineState(userId);
|
|
@@ -49,7 +49,13 @@ export class DeviceMetadata {
|
|
|
49
49
|
if (this.cached)
|
|
50
50
|
return this.cached;
|
|
51
51
|
const platform = getPlatform().info.os;
|
|
52
|
-
|
|
52
|
+
// 'unknown' rather than empty, matching appVersion above. A browser
|
|
53
|
+
// outside the handful browserVersion() recognises — Brave, Opera,
|
|
54
|
+
// Samsung Internet, an in-app webview — reports nothing, and an empty
|
|
55
|
+
// header stored against a session is indistinguishable from an SDK that
|
|
56
|
+
// never reported itself at all. 'unknown' says the SDK spoke and could
|
|
57
|
+
// not identify the host, which is a different and more useful fact.
|
|
58
|
+
const platformVersion = getPlatform().info.version || 'unknown';
|
|
53
59
|
const deviceLabel = await this.getOrCreateDeviceLabel();
|
|
54
60
|
// No User-Agent: a browser forbids setting it, and the same header set
|
|
55
61
|
// now goes out from both hosts. The platform and version below carry
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import { KoolbaseConfig } from './types.js';
|
|
2
|
+
import { KoolbaseError } from './errors.js';
|
|
3
|
+
/**
|
|
4
|
+
* The lifecycle status of a fiscal intent.
|
|
5
|
+
*
|
|
6
|
+
* A sale is durably recorded the moment `submit` returns; fiscal numbers and
|
|
7
|
+
* the authority's certification follow this state machine:
|
|
8
|
+
*
|
|
9
|
+
* - `queued` / `submitting` / `retrying` — sealed with allocated numbers;
|
|
10
|
+
* delivery to the authority is in progress.
|
|
11
|
+
* - `fiscalized` — the authority answered; for certifying document kinds the
|
|
12
|
+
* `certification` is present.
|
|
13
|
+
* - `blocked` — a precondition failed BEFORE any fiscal number was consumed
|
|
14
|
+
* (see `blockedReason`). Resubmitting the same `clientRef` after fixing the
|
|
15
|
+
* cause resumes it.
|
|
16
|
+
* - `attention` — the authority rejected the document, or its credential died
|
|
17
|
+
* after sealing. An operator resolves it; the register's chain waits behind
|
|
18
|
+
* it.
|
|
19
|
+
* - `voided` — terminally closed by an operator without fiscalization.
|
|
20
|
+
*
|
|
21
|
+
* `unknown` is the forward-compatible fallback: a status this SDK version has
|
|
22
|
+
* not heard of parses as unknown rather than throwing, so a server that grows
|
|
23
|
+
* a state does not break older clients.
|
|
24
|
+
*/
|
|
25
|
+
export type FiscalStatus = 'created' | 'blocked' | 'queued' | 'submitting' | 'retrying' | 'fiscalized' | 'attention' | 'voided' | 'unknown';
|
|
26
|
+
/**
|
|
27
|
+
* The state of one fiscal intent.
|
|
28
|
+
*
|
|
29
|
+
* Jurisdiction-neutral by design: this SDK never learns a jurisdiction's
|
|
30
|
+
* vocabulary. Payloads travel as objects shaped by the device's adapter, and
|
|
31
|
+
* `certification` comes back as the authority granted it — for Ghana that
|
|
32
|
+
* means `ysdcregsig`, `ysdcrecnum`, `qr_code` and so on, which the SDK
|
|
33
|
+
* passes through without naming.
|
|
34
|
+
*/
|
|
35
|
+
export interface FiscalIntentResult {
|
|
36
|
+
intentId: string;
|
|
37
|
+
status: FiscalStatus;
|
|
38
|
+
/** Why a `blocked` intent stopped, when the server said. */
|
|
39
|
+
blockedReason?: string;
|
|
40
|
+
/** Fiscal numbers allocated at sealing. */
|
|
41
|
+
numbers?: Record<string, number>;
|
|
42
|
+
/** When the intent was sealed and its numbers allocated. */
|
|
43
|
+
sealedAt?: string;
|
|
44
|
+
/**
|
|
45
|
+
* What the authority granted, once `status` is `fiscalized`. This is the
|
|
46
|
+
* receipt-rendering payload: for Ghana, the signature, receipt number and
|
|
47
|
+
* QR verification URL.
|
|
48
|
+
*/
|
|
49
|
+
certification?: Record<string, unknown>;
|
|
50
|
+
}
|
|
51
|
+
/** True once the authority has certified the document. */
|
|
52
|
+
export declare function isFiscalized(r: FiscalIntentResult): boolean;
|
|
53
|
+
/** True while delivery to the authority is still in progress. */
|
|
54
|
+
export declare function isPending(r: FiscalIntentResult): boolean;
|
|
55
|
+
/** A fiscal request that failed. Carries the HTTP status where there was one. */
|
|
56
|
+
export declare class KoolbaseFiscalError extends KoolbaseError {
|
|
57
|
+
readonly statusCode?: number;
|
|
58
|
+
constructor(message: string, statusCode?: number);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Classify a response. Status and body in, result or error out.
|
|
62
|
+
*
|
|
63
|
+
* Exported for testability, and because auth handling belongs with the
|
|
64
|
+
* session hook rather than here — the same split the Flutter SDK makes.
|
|
65
|
+
*/
|
|
66
|
+
export declare function decodeFiscalResponse(status: number, body: string): Promise<FiscalIntentResult>;
|
|
67
|
+
/**
|
|
68
|
+
* Koolbase Fiscal — submitting sales to a tax authority.
|
|
69
|
+
*
|
|
70
|
+
* Jurisdiction-neutral: the SDK moves payloads and reads back whatever the
|
|
71
|
+
* authority certified. Ghana's GRA E-VAT is the first jurisdiction; nothing
|
|
72
|
+
* here names it.
|
|
73
|
+
*/
|
|
74
|
+
export declare class KoolbaseFiscal {
|
|
75
|
+
private config;
|
|
76
|
+
private getToken;
|
|
77
|
+
private onSessionExpired?;
|
|
78
|
+
constructor(config: KoolbaseConfig, getToken: () => Promise<string | null>, onSessionExpired?: () => Promise<void>);
|
|
79
|
+
private buildHeaders;
|
|
80
|
+
private decode;
|
|
81
|
+
/**
|
|
82
|
+
* Submit a sale for fiscalization.
|
|
83
|
+
*
|
|
84
|
+
* The sale is durably recorded the moment this returns; fiscal numbers and
|
|
85
|
+
* the authority's certification follow asynchronously — poll `status()`
|
|
86
|
+
* with the same `clientRef` to watch it.
|
|
87
|
+
*
|
|
88
|
+
* **On timeout, do not resubmit blindly.** The sale may have fiscalized
|
|
89
|
+
* anyway: the request reached the server and the response was lost. Poll
|
|
90
|
+
* `status()` with the same `clientRef` instead, which is idempotent and
|
|
91
|
+
* tells you what actually happened.
|
|
92
|
+
*
|
|
93
|
+
* @param clientRef your own reference for this sale; the idempotency key
|
|
94
|
+
* and the handle you poll and render receipts by.
|
|
95
|
+
*/
|
|
96
|
+
submit(params: {
|
|
97
|
+
deviceId: string;
|
|
98
|
+
clientRef: string;
|
|
99
|
+
payload: Record<string, unknown>;
|
|
100
|
+
timeoutMs?: number;
|
|
101
|
+
}): Promise<FiscalIntentResult>;
|
|
102
|
+
/**
|
|
103
|
+
* Read an intent's current state by the reference it was submitted under.
|
|
104
|
+
*
|
|
105
|
+
* This is the receipt-rendering read: once the status is `fiscalized`, the
|
|
106
|
+
* `certification` carries what the receipt must show — for Ghana, the
|
|
107
|
+
* signature, receipt number and QR verification URL.
|
|
108
|
+
*/
|
|
109
|
+
status(params: {
|
|
110
|
+
deviceId: string;
|
|
111
|
+
clientRef: string;
|
|
112
|
+
timeoutMs?: number;
|
|
113
|
+
}): Promise<FiscalIntentResult>;
|
|
114
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { KoolbaseError, KoolbaseUnauthenticatedError } from './errors.js';
|
|
2
|
+
const KNOWN_STATUSES = [
|
|
3
|
+
'created', 'blocked', 'queued', 'submitting',
|
|
4
|
+
'retrying', 'fiscalized', 'attention', 'voided',
|
|
5
|
+
];
|
|
6
|
+
function parseStatus(raw) {
|
|
7
|
+
return typeof raw === 'string' && KNOWN_STATUSES.includes(raw)
|
|
8
|
+
? raw
|
|
9
|
+
: 'unknown';
|
|
10
|
+
}
|
|
11
|
+
/** True once the authority has certified the document. */
|
|
12
|
+
export function isFiscalized(r) {
|
|
13
|
+
return r.status === 'fiscalized';
|
|
14
|
+
}
|
|
15
|
+
/** True while delivery to the authority is still in progress. */
|
|
16
|
+
export function isPending(r) {
|
|
17
|
+
return r.status === 'queued'
|
|
18
|
+
|| r.status === 'submitting'
|
|
19
|
+
|| r.status === 'retrying';
|
|
20
|
+
}
|
|
21
|
+
/** A fiscal request that failed. Carries the HTTP status where there was one. */
|
|
22
|
+
export class KoolbaseFiscalError extends KoolbaseError {
|
|
23
|
+
constructor(message, statusCode) {
|
|
24
|
+
super(message, 'fiscal_failed');
|
|
25
|
+
this.statusCode = statusCode;
|
|
26
|
+
this.name = 'KoolbaseFiscalError';
|
|
27
|
+
Object.setPrototypeOf(this, KoolbaseFiscalError.prototype);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function resultFromJson(json) {
|
|
31
|
+
const numbers = json.numbers;
|
|
32
|
+
return {
|
|
33
|
+
intentId: String(json.intent_id ?? ''),
|
|
34
|
+
status: parseStatus(json.status),
|
|
35
|
+
blockedReason: json.blocked_reason,
|
|
36
|
+
numbers: numbers ?? undefined,
|
|
37
|
+
sealedAt: json.sealed_at,
|
|
38
|
+
certification: json.certification,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Classify a response. Status and body in, result or error out.
|
|
43
|
+
*
|
|
44
|
+
* Exported for testability, and because auth handling belongs with the
|
|
45
|
+
* session hook rather than here — the same split the Flutter SDK makes.
|
|
46
|
+
*/
|
|
47
|
+
export async function decodeFiscalResponse(status, body) {
|
|
48
|
+
let parsed;
|
|
49
|
+
try {
|
|
50
|
+
parsed = JSON.parse(body);
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
throw new KoolbaseFiscalError(`fiscal: unreadable response (${status})`, status);
|
|
54
|
+
}
|
|
55
|
+
if ((status >= 200 && status < 300) || status === 202) {
|
|
56
|
+
return resultFromJson(parsed);
|
|
57
|
+
}
|
|
58
|
+
throw new KoolbaseFiscalError(parsed.error ?? 'fiscal: request failed', status);
|
|
59
|
+
}
|
|
60
|
+
// ─── KoolbaseFiscal ──────────────────────────────────────────────────────────
|
|
61
|
+
/**
|
|
62
|
+
* Koolbase Fiscal — submitting sales to a tax authority.
|
|
63
|
+
*
|
|
64
|
+
* Jurisdiction-neutral: the SDK moves payloads and reads back whatever the
|
|
65
|
+
* authority certified. Ghana's GRA E-VAT is the first jurisdiction; nothing
|
|
66
|
+
* here names it.
|
|
67
|
+
*/
|
|
68
|
+
export class KoolbaseFiscal {
|
|
69
|
+
constructor(config, getToken, onSessionExpired) {
|
|
70
|
+
this.config = config;
|
|
71
|
+
this.getToken = getToken;
|
|
72
|
+
this.onSessionExpired = onSessionExpired;
|
|
73
|
+
}
|
|
74
|
+
async buildHeaders() {
|
|
75
|
+
const token = await this.getToken();
|
|
76
|
+
return {
|
|
77
|
+
'Content-Type': 'application/json',
|
|
78
|
+
'x-api-key': this.config.publicKey,
|
|
79
|
+
...(token ? { Authorization: `Bearer ${token}` } : {}),
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async decode(res) {
|
|
83
|
+
if (res.status === 401 || res.status === 403) {
|
|
84
|
+
await this.onSessionExpired?.();
|
|
85
|
+
throw new KoolbaseUnauthenticatedError(`fiscal: unauthenticated (${res.status})`);
|
|
86
|
+
}
|
|
87
|
+
return decodeFiscalResponse(res.status, await res.text());
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Submit a sale for fiscalization.
|
|
91
|
+
*
|
|
92
|
+
* The sale is durably recorded the moment this returns; fiscal numbers and
|
|
93
|
+
* the authority's certification follow asynchronously — poll `status()`
|
|
94
|
+
* with the same `clientRef` to watch it.
|
|
95
|
+
*
|
|
96
|
+
* **On timeout, do not resubmit blindly.** The sale may have fiscalized
|
|
97
|
+
* anyway: the request reached the server and the response was lost. Poll
|
|
98
|
+
* `status()` with the same `clientRef` instead, which is idempotent and
|
|
99
|
+
* tells you what actually happened.
|
|
100
|
+
*
|
|
101
|
+
* @param clientRef your own reference for this sale; the idempotency key
|
|
102
|
+
* and the handle you poll and render receipts by.
|
|
103
|
+
*/
|
|
104
|
+
async submit(params) {
|
|
105
|
+
const controller = new AbortController();
|
|
106
|
+
const timer = setTimeout(() => controller.abort(), params.timeoutMs ?? 30000);
|
|
107
|
+
try {
|
|
108
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/fiscal/submit`, {
|
|
109
|
+
method: 'POST',
|
|
110
|
+
headers: await this.buildHeaders(),
|
|
111
|
+
signal: controller.signal,
|
|
112
|
+
body: JSON.stringify({
|
|
113
|
+
device_id: params.deviceId,
|
|
114
|
+
client_ref: params.clientRef,
|
|
115
|
+
payload: params.payload,
|
|
116
|
+
}),
|
|
117
|
+
});
|
|
118
|
+
return await this.decode(res);
|
|
119
|
+
}
|
|
120
|
+
catch (e) {
|
|
121
|
+
if (e instanceof Error && e.name === 'AbortError') {
|
|
122
|
+
throw new KoolbaseFiscalError('fiscal submit timed out — the sale may still fiscalize; '
|
|
123
|
+
+ 'poll status with the same clientRef');
|
|
124
|
+
}
|
|
125
|
+
throw e;
|
|
126
|
+
}
|
|
127
|
+
finally {
|
|
128
|
+
clearTimeout(timer);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Read an intent's current state by the reference it was submitted under.
|
|
133
|
+
*
|
|
134
|
+
* This is the receipt-rendering read: once the status is `fiscalized`, the
|
|
135
|
+
* `certification` carries what the receipt must show — for Ghana, the
|
|
136
|
+
* signature, receipt number and QR verification URL.
|
|
137
|
+
*/
|
|
138
|
+
async status(params) {
|
|
139
|
+
const controller = new AbortController();
|
|
140
|
+
const timer = setTimeout(() => controller.abort(), params.timeoutMs ?? 15000);
|
|
141
|
+
try {
|
|
142
|
+
const q = new URLSearchParams({
|
|
143
|
+
device_id: params.deviceId,
|
|
144
|
+
client_ref: params.clientRef,
|
|
145
|
+
});
|
|
146
|
+
const res = await fetch(`${this.config.baseUrl}/v1/sdk/fiscal/status?${q.toString()}`, { method: 'GET', headers: await this.buildHeaders(), signal: controller.signal });
|
|
147
|
+
return await this.decode(res);
|
|
148
|
+
}
|
|
149
|
+
catch (e) {
|
|
150
|
+
if (e instanceof Error && e.name === 'AbortError') {
|
|
151
|
+
throw new KoolbaseFiscalError('fiscal status timed out');
|
|
152
|
+
}
|
|
153
|
+
throw e;
|
|
154
|
+
}
|
|
155
|
+
finally {
|
|
156
|
+
clearTimeout(timer);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export * from './errors.js';
|
|
3
|
+
export * from './aggregate.js';
|
|
3
4
|
export * from './conflict.js';
|
|
4
5
|
export * from './pending-write.js';
|
|
5
6
|
export * from './function-errors.js';
|
|
@@ -13,6 +14,8 @@ export { KoolbaseFunctions } from './functions.js';
|
|
|
13
14
|
export { KoolbaseRealtime } from './realtime.js';
|
|
14
15
|
export { KoolbaseStorage } from './storage.js';
|
|
15
16
|
export { KoolbaseAnalytics } from './analytics.js';
|
|
17
|
+
export { KoolbaseFiscal, KoolbaseFiscalError, decodeFiscalResponse, isFiscalized, isPending } from './fiscal.js';
|
|
18
|
+
export type { FiscalIntentResult, FiscalStatus } from './fiscal.js';
|
|
16
19
|
export { KoolbaseMessaging } from './messaging.js';
|
|
17
20
|
export type { RegisterTokenOptions } from './messaging.js';
|
|
18
21
|
export { getOrCreateDeviceId } from './device-id.js';
|
package/dist/esm/index.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
// code installs the platform package, never this one directly.
|
|
6
6
|
export * from './types.js';
|
|
7
7
|
export * from './errors.js';
|
|
8
|
+
export * from './aggregate.js';
|
|
8
9
|
export * from './conflict.js';
|
|
9
10
|
export * from './pending-write.js';
|
|
10
11
|
export * from './function-errors.js';
|
|
@@ -18,6 +19,7 @@ export { KoolbaseFunctions } from './functions.js';
|
|
|
18
19
|
export { KoolbaseRealtime } from './realtime.js';
|
|
19
20
|
export { KoolbaseStorage } from './storage.js';
|
|
20
21
|
export { KoolbaseAnalytics } from './analytics.js';
|
|
22
|
+
export { KoolbaseFiscal, KoolbaseFiscalError, decodeFiscalResponse, isFiscalized, isPending } from './fiscal.js';
|
|
21
23
|
export { KoolbaseMessaging } from './messaging.js';
|
|
22
24
|
export { getOrCreateDeviceId } from './device-id.js';
|
|
23
25
|
export { koolbaseSdkVersion } from './device-metadata.js';
|
package/dist/esm/types.d.ts
CHANGED
|
@@ -88,6 +88,64 @@ export type SignUpResult = {
|
|
|
88
88
|
user: KoolbaseUser;
|
|
89
89
|
session: null;
|
|
90
90
|
};
|
|
91
|
+
/**
|
|
92
|
+
* One active session — somewhere the user is signed in.
|
|
93
|
+
*
|
|
94
|
+
* Token hashes are never included; the server excludes them deliberately.
|
|
95
|
+
*/
|
|
96
|
+
export interface KoolbaseSessionInfo {
|
|
97
|
+
id: string;
|
|
98
|
+
/** Where it signed in from, when the server captured it. */
|
|
99
|
+
ip?: string;
|
|
100
|
+
/** What signed in. A browser sets this; native SDKs send their own. */
|
|
101
|
+
userAgent?: string;
|
|
102
|
+
/** A per-install label, where the SDK supplied one. */
|
|
103
|
+
deviceLabel?: string;
|
|
104
|
+
createdAt: string;
|
|
105
|
+
expiresAt: string;
|
|
106
|
+
/**
|
|
107
|
+
* True for the session making the request.
|
|
108
|
+
*
|
|
109
|
+
* A device list needs this: without it a user cannot tell which row is the
|
|
110
|
+
* phone in their hand, and "sign out everywhere else" has nothing to
|
|
111
|
+
* exclude.
|
|
112
|
+
*/
|
|
113
|
+
isCurrent: boolean;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* One thing that happened to this account.
|
|
117
|
+
*
|
|
118
|
+
* The server sanitizes these: `eventData` carries only the fields allowed
|
|
119
|
+
* for that event type, so a lockout can say which address was attempted
|
|
120
|
+
* while a successful login carries nothing extra.
|
|
121
|
+
*/
|
|
122
|
+
export interface KoolbaseAuditEvent {
|
|
123
|
+
id: string;
|
|
124
|
+
/**
|
|
125
|
+
* What happened. One of: auth.login.success, auth.login.failed,
|
|
126
|
+
* auth.account.locked, auth.account.unlocked, auth.session.created,
|
|
127
|
+
* auth.session.refreshed, auth.session.revoked, auth.password.changed,
|
|
128
|
+
* auth.user.verified.
|
|
129
|
+
*
|
|
130
|
+
* A string rather than a union: the server may add one, and an app that
|
|
131
|
+
* stops compiling because it did would be worse than one that shows an
|
|
132
|
+
* event it does not recognise.
|
|
133
|
+
*/
|
|
134
|
+
eventType: string;
|
|
135
|
+
occurredAt: string;
|
|
136
|
+
ip?: string;
|
|
137
|
+
userAgent?: string;
|
|
138
|
+
/** Whatever that event type is allowed to carry. Often empty. */
|
|
139
|
+
eventData: Record<string, unknown>;
|
|
140
|
+
}
|
|
141
|
+
/** A page of audit events, and how many there are in total. */
|
|
142
|
+
export interface KoolbaseAuditPage {
|
|
143
|
+
events: KoolbaseAuditEvent[];
|
|
144
|
+
/** Across all pages, so an app knows whether to offer "show more". */
|
|
145
|
+
total: number;
|
|
146
|
+
limit: number;
|
|
147
|
+
offset: number;
|
|
148
|
+
}
|
|
91
149
|
export interface ResendVerificationResult {
|
|
92
150
|
alreadyVerified: boolean;
|
|
93
151
|
/** When the link in the email stops working. Null when nothing was sent. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koolbase/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "12.1.0",
|
|
4
4
|
"description": "Koolbase SDK core \u2014 shared behaviour behind @koolbase/react-native and @koolbase/js. Install one of those, not this.",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"types": "./dist/esm/index.d.ts",
|