@livx.cc/native-kit 0.38.0 → 0.40.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/README.md +1 -1
- package/package.json +1 -1
- package/src/core/web-adapter.ts +7 -1
- package/src/index.ts +2 -0
- package/src/modules/billing/billing.ts +29 -5
- package/src/modules/billing/types.ts +21 -0
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@ mixpanel.register(await kit.context());
|
|
|
26
26
|
|
|
27
27
|
The kit detects whether it's running inside the appwrap shell and routes each call to the native bridge or a web fallback, so a single web build works everywhere. Capabilities advertise their real backing (`native` / `web` / `none`) so your UI can be honest about what's available.
|
|
28
28
|
|
|
29
|
-
Covers haptics, share, storage, notifications, OAuth, billing (IAP), health, geo, camera, photos, contacts, calendar, motion, reviews, tracking (iOS App Tracking Transparency), and more.
|
|
29
|
+
Covers haptics, share, storage, notifications, OAuth, billing (IAP), health, geo, heading (compass), camera, photos, contacts, calendar, motion, reviews, tracking (iOS App Tracking Transparency), and more.
|
|
30
30
|
|
|
31
31
|
**Full documentation, capability model, and the bridge protocol:** see the [appwrap README](https://github.com/Livshitz/appwrap#readme).
|
|
32
32
|
|
package/package.json
CHANGED
package/src/core/web-adapter.ts
CHANGED
|
@@ -332,9 +332,15 @@ export class WebAdapter implements NativeKitAdapter {
|
|
|
332
332
|
last = now;
|
|
333
333
|
const a = e.accelerationIncludingGravity;
|
|
334
334
|
const r = e.rotationRate;
|
|
335
|
+
// Map DOM → kit contract. Two corrections vs the raw event, BOTH load-bearing:
|
|
336
|
+
// 1. UNITS: the DOM reports rotationRate in deg/s; the kit contract (and both native
|
|
337
|
+
// handlers — CoreMotion + Android TYPE_GYROSCOPE) is rad/s. Convert, or web is 57× off.
|
|
338
|
+
// 2. AXES: DOM alpha/beta/gamma are the rates about Z/X/Y respectively — NOT x/y/z in
|
|
339
|
+
// order. So rx=beta, ry=gamma, rz=alpha; a naive alpha→rx puts the Z-rate on X.
|
|
340
|
+
const toRad = (d?: number | null) => (d == null ? undefined : (d * Math.PI) / 180);
|
|
335
341
|
this.emit('motion.data', {
|
|
336
342
|
ax: a?.x ?? 0, ay: a?.y ?? 0, az: a?.z ?? 0,
|
|
337
|
-
rx: r?.
|
|
343
|
+
rx: toRad(r?.beta), ry: toRad(r?.gamma), rz: toRad(r?.alpha),
|
|
338
344
|
});
|
|
339
345
|
};
|
|
340
346
|
window.addEventListener('devicemotion', this.motionHandler);
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
import type { NativeKit } from '../../core/NativeKit';
|
|
2
2
|
import { KitError, type Capability, type Unsubscribe } from '../../core/types';
|
|
3
3
|
import { ClientTrustedValidator } from './validators';
|
|
4
|
-
import type {
|
|
4
|
+
import type {
|
|
5
|
+
BillingProvider,
|
|
6
|
+
BillingValidator,
|
|
7
|
+
Entitlement,
|
|
8
|
+
Product,
|
|
9
|
+
PurchaseReceipt,
|
|
10
|
+
PurchaseResult,
|
|
11
|
+
ReceiptEntitlements,
|
|
12
|
+
ReceiptOutcome,
|
|
13
|
+
} from './types';
|
|
5
14
|
|
|
6
15
|
/**
|
|
7
16
|
* In-app purchases & subscriptions — ONE API across web and native.
|
|
@@ -89,14 +98,29 @@ export class BillingModule {
|
|
|
89
98
|
* Native iOS only, and only meaningful with a **server validator** (the bare receipt has no
|
|
90
99
|
* product id — a client-trusted validator can't interpret it). Resolves `[]` on the web,
|
|
91
100
|
* on Android (no StoreKit-1 receipt), or when no receipt is present (e.g. a dev build).
|
|
101
|
+
*
|
|
102
|
+
* The `[]` is AMBIGUOUS by design-history: it means both "no entitlements" and "never even
|
|
103
|
+
* asked". Use {@link receiptEntitlements} to tell those apart.
|
|
92
104
|
*/
|
|
93
105
|
async entitlementsFromReceipt(): Promise<Entitlement[]> {
|
|
106
|
+
return (await this.receiptEntitlements()).entitlements;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* {@link entitlementsFromReceipt} plus **why** — the same check, but the three
|
|
111
|
+
* didn't-even-ask paths are reported instead of being flattened into `[]`. See
|
|
112
|
+
* {@link ReceiptOutcome}: only `'validated'` makes an empty list a real answer.
|
|
113
|
+
*
|
|
114
|
+
* A validator that errors (network, Apple status 21004, …) REJECTS rather than
|
|
115
|
+
* reporting an outcome — a failed check is not a verdict about the user.
|
|
116
|
+
*/
|
|
117
|
+
async receiptEntitlements(): Promise<ReceiptEntitlements> {
|
|
94
118
|
await this.kit.ready();
|
|
95
|
-
if (this.capability !== 'native') return []; // web, or a shell with no native store handler (Android today)
|
|
96
|
-
if (this.validator instanceof ClientTrustedValidator) return []; // bare receipt has no product id → would grant a bogus active entitlement; needs a server validator
|
|
119
|
+
if (this.capability !== 'native') return { entitlements: [], outcome: 'not-native' }; // web, or a shell with no native store handler (Android today)
|
|
120
|
+
if (this.validator instanceof ClientTrustedValidator) return { entitlements: [], outcome: 'no-validator' }; // bare receipt has no product id → would grant a bogus active entitlement; needs a server validator
|
|
97
121
|
const receipt = await this.kit.invoke<PurchaseReceipt>('billing.appReceipt');
|
|
98
|
-
if (!receipt?.appReceipt) return [];
|
|
99
|
-
return this.validator.validate(receipt); // server-of-record turns the receipt into entitlements
|
|
122
|
+
if (!receipt?.appReceipt) return { entitlements: [], outcome: 'no-receipt' };
|
|
123
|
+
return { entitlements: await this.validator.validate(receipt), outcome: 'validated' }; // server-of-record turns the receipt into entitlements
|
|
100
124
|
}
|
|
101
125
|
|
|
102
126
|
/** Current entitlements from the configured server-of-record (web provider or validator). */
|
|
@@ -58,6 +58,27 @@ export interface PurchaseResult {
|
|
|
58
58
|
entitlements: Entitlement[];
|
|
59
59
|
}
|
|
60
60
|
|
|
61
|
+
/**
|
|
62
|
+
* Why a receipt check produced what it did — the four outcomes that `Entitlement[]`
|
|
63
|
+
* alone collapses into an indistinguishable `[]`.
|
|
64
|
+
*
|
|
65
|
+
* - `validated` the server-of-record read the receipt; `entitlements` is its verdict
|
|
66
|
+
* (still `[]` when the user genuinely owns nothing — the only outcome
|
|
67
|
+
* where an empty list is an ANSWER rather than a non-answer).
|
|
68
|
+
* - `not-native` web, or a shell with no native store handler (Android: no StoreKit-1 receipt).
|
|
69
|
+
* - `no-validator` only a {@link ClientTrustedValidator} is wired; a bare app receipt carries no
|
|
70
|
+
* product id, so trusting it would grant a bogus entitlement. Wire a server validator.
|
|
71
|
+
* - `no-receipt` this build has no App Store receipt. StoreKit only issues one after a purchase or
|
|
72
|
+
* restore, so locally-installed dev builds legitimately have none.
|
|
73
|
+
*/
|
|
74
|
+
export type ReceiptOutcome = 'validated' | 'not-native' | 'no-validator' | 'no-receipt';
|
|
75
|
+
|
|
76
|
+
/** The outcome-carrying result of {@link BillingModule.receiptEntitlements}. */
|
|
77
|
+
export interface ReceiptEntitlements {
|
|
78
|
+
entitlements: Entitlement[];
|
|
79
|
+
outcome: ReceiptOutcome;
|
|
80
|
+
}
|
|
81
|
+
|
|
61
82
|
/**
|
|
62
83
|
* The swappable seam. The kit owns the on-device purchase flow; *who decides the
|
|
63
84
|
* user is actually entitled* is up to the app. Implement this (or configure the
|