@wix/himalaya-cli 0.1231.0 → 0.1232.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/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/health/src/index.d.ts +93 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/health.mjs +127 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +4 -0
- package/dist/cli.mjs +140 -21
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/app-config.md +1 -1
- package/guides/importable-sdks.md +1 -0
- package/guides/sdk-reference.json +145 -0
- package/package.json +2 -2
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/health/src/index.d.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/** A readable health data type. */
|
|
2
|
+
export type HealthType = "steps" | "heartRate" | "activeEnergy" | "distance" | "workouts";
|
|
3
|
+
/** A writable health data type. v1 writes workouts only. */
|
|
4
|
+
export type HealthWriteType = "workouts";
|
|
5
|
+
export type HealthPermissionState = "granted" | "denied" | "notDetermined";
|
|
6
|
+
/** Aggregation bucket for `query`. Omitted ⇒ one total (cumulative types) or raw samples. */
|
|
7
|
+
export type HealthBucket = "hour" | "day";
|
|
8
|
+
export type WorkoutActivity = "running" | "walking" | "cycling" | "strength" | "other";
|
|
9
|
+
export type HealthErrorCode = "unavailable" | "not_authorized" | "invalid_argument" | "failed";
|
|
10
|
+
export declare const HEALTH_TYPES: readonly HealthType[];
|
|
11
|
+
export declare const WORKOUT_ACTIVITIES: readonly WorkoutActivity[];
|
|
12
|
+
/** The fixed unit each type's `value` is reported in. */
|
|
13
|
+
export declare const HEALTH_UNITS: Readonly<Record<HealthType, string>>;
|
|
14
|
+
export interface HealthAvailability {
|
|
15
|
+
available: boolean;
|
|
16
|
+
/** Why not, when `available` is false — e.g. "web has no health store",
|
|
17
|
+
* "Health Connect is not installed". */
|
|
18
|
+
reason?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface HealthSample {
|
|
21
|
+
/** ISO-8601. */
|
|
22
|
+
start: string;
|
|
23
|
+
/** ISO-8601. */
|
|
24
|
+
end: string;
|
|
25
|
+
value: number;
|
|
26
|
+
unit: string;
|
|
27
|
+
/** Workouts only: the activity, mapped back onto the v1 set ("other" for anything else). */
|
|
28
|
+
activity?: WorkoutActivity;
|
|
29
|
+
}
|
|
30
|
+
export interface HealthQuery {
|
|
31
|
+
type: HealthType;
|
|
32
|
+
/** ISO-8601, inclusive. */
|
|
33
|
+
from: string;
|
|
34
|
+
/** ISO-8601, exclusive. */
|
|
35
|
+
to: string;
|
|
36
|
+
/** steps / activeEnergy / distance are SUMMED per bucket; heartRate is AVERAGED per bucket;
|
|
37
|
+
* workouts ignore it (one sample per workout). */
|
|
38
|
+
bucket?: HealthBucket;
|
|
39
|
+
}
|
|
40
|
+
export interface Workout {
|
|
41
|
+
activity: WorkoutActivity;
|
|
42
|
+
/** ISO-8601. */
|
|
43
|
+
start: string;
|
|
44
|
+
/** ISO-8601, after `start`. */
|
|
45
|
+
end: string;
|
|
46
|
+
energyKcal?: number;
|
|
47
|
+
distanceM?: number;
|
|
48
|
+
}
|
|
49
|
+
/** The typed rejection every verb throws. A plain Error carrying `code` — worker bundles are
|
|
50
|
+
* compiled to a target without class syntax, so this is a factory, not a subclass. */
|
|
51
|
+
export interface HealthError extends Error {
|
|
52
|
+
name: "HealthError";
|
|
53
|
+
code: HealthErrorCode;
|
|
54
|
+
}
|
|
55
|
+
/** Build a [HealthError] — what the binding throws for every native `{ error }` reply. */
|
|
56
|
+
export declare function healthError(code: HealthErrorCode, message: string): HealthError;
|
|
57
|
+
/** Narrow a caught value: `catch (e) { if (isHealthError(e) && e.code === "unavailable") … }`. */
|
|
58
|
+
export declare function isHealthError(e: unknown): e is HealthError;
|
|
59
|
+
/** Whether this device has a health store the app can reach. Call it first and branch. */
|
|
60
|
+
export declare function availability(): Promise<HealthAvailability>;
|
|
61
|
+
/**
|
|
62
|
+
* Prompt for read (and optionally write) access. Resolves with the types the platform
|
|
63
|
+
* reports as granted — on iOS a read type counts as granted once asked (see header).
|
|
64
|
+
* Writing workouts also covers the energy + distance samples a saved workout carries.
|
|
65
|
+
*/
|
|
66
|
+
export declare function requestPermission(p: {
|
|
67
|
+
read: HealthType[];
|
|
68
|
+
write?: HealthWriteType[];
|
|
69
|
+
}): Promise<{
|
|
70
|
+
granted: HealthType[];
|
|
71
|
+
}>;
|
|
72
|
+
/** Current READ permission per type, without prompting. iOS reads are always "notDetermined". */
|
|
73
|
+
export declare function getPermissionStatus(p: {
|
|
74
|
+
types: HealthType[];
|
|
75
|
+
}): Promise<Record<HealthType, HealthPermissionState>>;
|
|
76
|
+
/** Read samples of one type over [from, to). */
|
|
77
|
+
export declare function query(p: HealthQuery): Promise<{
|
|
78
|
+
samples: HealthSample[];
|
|
79
|
+
}>;
|
|
80
|
+
/** Save a completed workout (with its energy/distance, when given). Resolves with its store id. */
|
|
81
|
+
export declare function saveWorkout(w: Workout): Promise<{
|
|
82
|
+
id: string;
|
|
83
|
+
}>;
|
|
84
|
+
export declare const version = 1;
|
|
85
|
+
/** The whole surface as one namespace: `import { health } from "@wix/himalaya/health"`. */
|
|
86
|
+
export declare const health: {
|
|
87
|
+
availability: typeof availability;
|
|
88
|
+
requestPermission: typeof requestPermission;
|
|
89
|
+
getPermissionStatus: typeof getPermissionStatus;
|
|
90
|
+
query: typeof query;
|
|
91
|
+
saveWorkout: typeof saveWorkout;
|
|
92
|
+
version: number;
|
|
93
|
+
};
|
|
@@ -14,6 +14,7 @@ export declare const CAPABILITY_REGISTRY: {
|
|
|
14
14
|
readonly files: readonly ["list", "readText", "remove", "stat", "write"];
|
|
15
15
|
readonly godot: readonly ["loadPack", "release", "send"];
|
|
16
16
|
readonly haptic: readonly ["play"];
|
|
17
|
+
readonly health: readonly ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"];
|
|
17
18
|
readonly himi_apps: readonly ["canOpen", "current", "hostInfo", "open"];
|
|
18
19
|
readonly iap: readonly ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"];
|
|
19
20
|
readonly keyboard: readonly ["dismiss"];
|
|
@@ -39,7 +40,7 @@ export declare const CAPABILITY_REGISTRY: {
|
|
|
39
40
|
readonly wix_cashier: readonly ["isAvailable", "proceedToPayment"];
|
|
40
41
|
};
|
|
41
42
|
/** A capability id backed by an @himalaya/* SDK binding. */
|
|
42
|
-
export type SdkCapability = "app_info" | "audio_record" | "base44" | "biometrics" | "browser_auth" | "calendar" | "calls" | "camera" | "clipboard" | "contacts" | "file_picker" | "files" | "godot" | "haptic" | "himi_apps" | "iap" | "keyboard" | "live_activity" | "local_database" | "location" | "media_playback" | "motion" | "on_device_ai" | "open_url" | "pdf" | "photos" | "presigned_upload" | "push" | "release_control" | "secure_storage" | "share" | "speaker_diarization" | "speech" | "system_intents" | "tasks" | "ui" | "wix_cashier";
|
|
43
|
+
export type SdkCapability = "app_info" | "audio_record" | "base44" | "biometrics" | "browser_auth" | "calendar" | "calls" | "camera" | "clipboard" | "contacts" | "file_picker" | "files" | "godot" | "haptic" | "health" | "himi_apps" | "iap" | "keyboard" | "live_activity" | "local_database" | "location" | "media_playback" | "motion" | "on_device_ai" | "open_url" | "pdf" | "photos" | "presigned_upload" | "push" | "release_control" | "secure_storage" | "share" | "speaker_diarization" | "speech" | "system_intents" | "tasks" | "ui" | "wix_cashier";
|
|
43
44
|
/** All `capability.<id>.<verb>` action ids, flattened (the worker-bridge wire vocabulary). */
|
|
44
45
|
export declare const CAPABILITY_ACTION_IDS: readonly string[];
|
|
45
46
|
/** Capability id → the @himalaya/* package(s) a worker imports to reach it — every dispatch
|
package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts
CHANGED
|
@@ -734,7 +734,7 @@ export interface OrientationEnvelope {
|
|
|
734
734
|
export declare const DEFAULT_ORIENTATION_ENVELOPE: Required<OrientationEnvelope>;
|
|
735
735
|
/** Fill in the absent families. Total, so callers never branch on `undefined`. */
|
|
736
736
|
export declare function resolveOrientationEnvelope(env?: OrientationEnvelope): Required<OrientationEnvelope>;
|
|
737
|
-
export type Capability = "camera" | "barcode_scanner" | "biometrics" | "secure_storage" | "share" | "push" | "file_picker" | "files" | "open_url" | "pdf" | "clipboard" | "photos" | "presigned_upload" | "ui" | "calendar" | "contacts" | "tasks" | "audio_record" | "audio_record_background" | "calls" | "location" | "location_background" | "motion" | "media_playback" | "webview" | "browser_auth" | "haptic" | "himi_apps" | "iap" | "keyboard" | "wix_cashier" | "live_activity" | "local_database" | "speech" | "speaker_diarization" | "system_intents" | "on_device_ai" | "app_info" | "release_control" | "godot" | "base44";
|
|
737
|
+
export type Capability = "camera" | "barcode_scanner" | "biometrics" | "secure_storage" | "share" | "push" | "file_picker" | "files" | "open_url" | "pdf" | "clipboard" | "photos" | "presigned_upload" | "ui" | "calendar" | "contacts" | "tasks" | "audio_record" | "audio_record_background" | "calls" | "location" | "location_background" | "motion" | "health" | "media_playback" | "webview" | "browser_auth" | "haptic" | "himi_apps" | "iap" | "keyboard" | "wix_cashier" | "live_activity" | "local_database" | "speech" | "speaker_diarization" | "system_intents" | "on_device_ai" | "app_info" | "release_control" | "godot" | "base44";
|
|
738
738
|
/** `defineApp({ base44 })` — which Base44 app `@himalaya/base44` talks to. */
|
|
739
739
|
export interface Base44Config {
|
|
740
740
|
/** The Base44 app id (24 hex chars, e.g. `69725232345f461f64ad1623`). */
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
// ../../core/sdk/dispatch/src/index.ts
|
|
2
|
+
function dispatch(handlerId, params, _options) {
|
|
3
|
+
const himalaya = globalThis.himalaya;
|
|
4
|
+
if (!himalaya) {
|
|
5
|
+
return Promise.reject(
|
|
6
|
+
new Error("@himalaya/dispatch: called outside a Himalaya runtime. This bundle must run inside a JSWorker (Tier 5).")
|
|
7
|
+
);
|
|
8
|
+
}
|
|
9
|
+
const stringParams = {};
|
|
10
|
+
if (params) {
|
|
11
|
+
for (const [k, v] of Object.entries(params)) stringParams[k] = String(v);
|
|
12
|
+
}
|
|
13
|
+
return himalaya.dispatch(handlerId, stringParams);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ../../core/sdk/health/src/index.ts
|
|
17
|
+
var HEALTH_TYPES = ["steps", "heartRate", "activeEnergy", "distance", "workouts"];
|
|
18
|
+
var WORKOUT_ACTIVITIES = ["running", "walking", "cycling", "strength", "other"];
|
|
19
|
+
var HEALTH_UNITS = {
|
|
20
|
+
steps: "count",
|
|
21
|
+
heartRate: "bpm",
|
|
22
|
+
activeEnergy: "kcal",
|
|
23
|
+
distance: "m",
|
|
24
|
+
workouts: "s"
|
|
25
|
+
};
|
|
26
|
+
function healthError(code, message) {
|
|
27
|
+
const e = new Error(message);
|
|
28
|
+
e.name = "HealthError";
|
|
29
|
+
e.code = code;
|
|
30
|
+
return e;
|
|
31
|
+
}
|
|
32
|
+
function isHealthError(e) {
|
|
33
|
+
return e instanceof Error && e.name === "HealthError" && typeof e.code === "string";
|
|
34
|
+
}
|
|
35
|
+
var ERROR_CODES = ["unavailable", "not_authorized", "invalid_argument", "failed"];
|
|
36
|
+
function unwrap(r) {
|
|
37
|
+
const err = r?.error;
|
|
38
|
+
if (err) {
|
|
39
|
+
const code = ERROR_CODES.includes(err.code ?? "") ? err.code : "failed";
|
|
40
|
+
throw healthError(code, err.message ?? code);
|
|
41
|
+
}
|
|
42
|
+
return r ?? {};
|
|
43
|
+
}
|
|
44
|
+
function assertTypes(types, allowed, what) {
|
|
45
|
+
for (const t of types) {
|
|
46
|
+
if (!allowed.includes(t)) throw healthError("invalid_argument", `health: unknown ${what} "${t}"`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function assertRange(from, to) {
|
|
50
|
+
const a = Date.parse(from), b = Date.parse(to);
|
|
51
|
+
if (Number.isNaN(a) || Number.isNaN(b)) throw healthError("invalid_argument", "health: from/to must be ISO-8601");
|
|
52
|
+
if (b <= a) throw healthError("invalid_argument", "health: `to` must be after `from`");
|
|
53
|
+
}
|
|
54
|
+
async function availability() {
|
|
55
|
+
const r = await dispatch("capability.health.availability");
|
|
56
|
+
const out = { available: r?.available === true };
|
|
57
|
+
if (typeof r?.reason === "string" && r.reason) out.reason = r.reason;
|
|
58
|
+
return out;
|
|
59
|
+
}
|
|
60
|
+
async function requestPermission(p) {
|
|
61
|
+
const read = p.read ?? [];
|
|
62
|
+
const write = p.write ?? [];
|
|
63
|
+
assertTypes(read, HEALTH_TYPES, "read type");
|
|
64
|
+
assertTypes(write, ["workouts"], "write type");
|
|
65
|
+
const r = unwrap(
|
|
66
|
+
await dispatch("capability.health.requestPermission", { read: read.join(","), write: write.join(",") })
|
|
67
|
+
);
|
|
68
|
+
const granted = Array.isArray(r.granted) ? r.granted : [];
|
|
69
|
+
return { granted: granted.filter((t) => HEALTH_TYPES.includes(t)) };
|
|
70
|
+
}
|
|
71
|
+
async function getPermissionStatus(p) {
|
|
72
|
+
const types = p.types ?? [];
|
|
73
|
+
assertTypes(types, HEALTH_TYPES, "type");
|
|
74
|
+
const r = unwrap(
|
|
75
|
+
await dispatch("capability.health.getPermissionStatus", { types: types.join(",") })
|
|
76
|
+
);
|
|
77
|
+
const out = {};
|
|
78
|
+
for (const t of types) {
|
|
79
|
+
const s = r.statuses?.[t];
|
|
80
|
+
out[t] = s === "granted" || s === "denied" ? s : "notDetermined";
|
|
81
|
+
}
|
|
82
|
+
return out;
|
|
83
|
+
}
|
|
84
|
+
async function query(p) {
|
|
85
|
+
assertTypes([p.type], HEALTH_TYPES, "type");
|
|
86
|
+
assertRange(p.from, p.to);
|
|
87
|
+
if (p.bucket !== void 0 && p.bucket !== "hour" && p.bucket !== "day") {
|
|
88
|
+
throw healthError("invalid_argument", `health: unknown bucket "${String(p.bucket)}"`);
|
|
89
|
+
}
|
|
90
|
+
const params = { type: p.type, from: p.from, to: p.to };
|
|
91
|
+
if (p.bucket) params.bucket = p.bucket;
|
|
92
|
+
const r = unwrap(await dispatch("capability.health.query", params));
|
|
93
|
+
return { samples: Array.isArray(r.samples) ? r.samples : [] };
|
|
94
|
+
}
|
|
95
|
+
async function saveWorkout(w) {
|
|
96
|
+
assertTypes([w.activity], WORKOUT_ACTIVITIES, "activity");
|
|
97
|
+
assertRange(w.start, w.end);
|
|
98
|
+
const params = { activity: w.activity, start: w.start, end: w.end };
|
|
99
|
+
if (typeof w.energyKcal === "number") {
|
|
100
|
+
if (!Number.isFinite(w.energyKcal) || w.energyKcal < 0) throw healthError("invalid_argument", "health: energyKcal must be a finite number >= 0");
|
|
101
|
+
params.energyKcal = w.energyKcal;
|
|
102
|
+
}
|
|
103
|
+
if (typeof w.distanceM === "number") {
|
|
104
|
+
if (!Number.isFinite(w.distanceM) || w.distanceM < 0) throw healthError("invalid_argument", "health: distanceM must be a finite number >= 0");
|
|
105
|
+
params.distanceM = w.distanceM;
|
|
106
|
+
}
|
|
107
|
+
const r = unwrap(await dispatch("capability.health.saveWorkout", params));
|
|
108
|
+
if (!r.id) throw healthError("failed", "health.saveWorkout: native returned no id");
|
|
109
|
+
return { id: r.id };
|
|
110
|
+
}
|
|
111
|
+
var version = 1;
|
|
112
|
+
var health = { availability, requestPermission, getPermissionStatus, query, saveWorkout, version };
|
|
113
|
+
export {
|
|
114
|
+
HEALTH_TYPES,
|
|
115
|
+
HEALTH_UNITS,
|
|
116
|
+
WORKOUT_ACTIVITIES,
|
|
117
|
+
availability,
|
|
118
|
+
getPermissionStatus,
|
|
119
|
+
health,
|
|
120
|
+
healthError,
|
|
121
|
+
isHealthError,
|
|
122
|
+
query,
|
|
123
|
+
requestPermission,
|
|
124
|
+
saveWorkout,
|
|
125
|
+
version
|
|
126
|
+
};
|
|
127
|
+
//# sourceMappingURL=health.mjs.map
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -14,6 +14,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
14
14
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
15
15
|
"godot": ["loadPack", "release", "send"],
|
|
16
16
|
"haptic": ["play"],
|
|
17
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
17
18
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
18
19
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
19
20
|
"keyboard": ["dismiss"],
|
|
@@ -29,6 +29,7 @@ var CAPABILITY_REGISTRY = {
|
|
|
29
29
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
30
30
|
"godot": ["loadPack", "release", "send"],
|
|
31
31
|
"haptic": ["play"],
|
|
32
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
32
33
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
33
34
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
34
35
|
"keyboard": ["dismiss"],
|
|
@@ -114,6 +114,10 @@
|
|
|
114
114
|
"types": "./dist/_types/core/sdk/haptic/src/index.d.ts",
|
|
115
115
|
"import": "./dist/haptic.mjs"
|
|
116
116
|
},
|
|
117
|
+
"./health": {
|
|
118
|
+
"types": "./dist/_types/core/sdk/health/src/index.d.ts",
|
|
119
|
+
"import": "./dist/health.mjs"
|
|
120
|
+
},
|
|
117
121
|
"./himi-apps": {
|
|
118
122
|
"types": "./dist/_types/core/sdk/himi-apps/src/index.d.ts",
|
|
119
123
|
"import": "./dist/himi-apps.mjs"
|
package/dist/cli.mjs
CHANGED
|
@@ -5002,6 +5002,7 @@ var init_build_lib = __esm({
|
|
|
5002
5002
|
// module comments — so the committed artifact differed per machine (a clone whose
|
|
5003
5003
|
// node_modules points elsewhere emitted /Users/<name>/... into a tracked file).
|
|
5004
5004
|
"@himalaya/motion": resolve8(REPO_ROOT4, "core/sdk/motion/src/index.ts"),
|
|
5005
|
+
"@himalaya/health": resolve8(REPO_ROOT4, "core/sdk/health/src/index.ts"),
|
|
5005
5006
|
// Pure TypeScript (GPX parse/serialize + track stats) — no dispatch, so no capability
|
|
5006
5007
|
// grant, same class as @himalaya/state.
|
|
5007
5008
|
"@himalaya/gpx": resolve8(REPO_ROOT4, "core/sdk/gpx/src/index.ts"),
|
|
@@ -17165,6 +17166,86 @@ var init_native_requirements = __esm({
|
|
|
17165
17166
|
]
|
|
17166
17167
|
}
|
|
17167
17168
|
},
|
|
17169
|
+
health: {
|
|
17170
|
+
// Apple Health (HealthKit) / Health Connect (@himalaya/health): read steps, heart rate,
|
|
17171
|
+
// active energy, distance and workouts; write a completed workout back. A different
|
|
17172
|
+
// privacy class from `motion` (the platform HEALTH store, not raw sensors), so its own row.
|
|
17173
|
+
ios: {
|
|
17174
|
+
// HealthKit throws (and App Review rejects) when either key is missing for the
|
|
17175
|
+
// direction the app uses. Both are declared because the surface is read + write.
|
|
17176
|
+
usageStrings: [
|
|
17177
|
+
{ key: "NSHealthShareUsageDescription", suggested: "Read your steps, heart rate, energy and workouts from Apple Health to show your activity." },
|
|
17178
|
+
{ key: "NSHealthUpdateUsageDescription", suggested: "Save the workouts you complete to Apple Health." }
|
|
17179
|
+
],
|
|
17180
|
+
// The App ID must have the HealthKit capability enabled for a DEVICE / TestFlight
|
|
17181
|
+
// build to sign with this — see docs/capability-native-config.md. Simulator builds
|
|
17182
|
+
// do not need the App ID step.
|
|
17183
|
+
entitlements: { "com.apple.developer.healthkit": true }
|
|
17184
|
+
},
|
|
17185
|
+
// macOS has no Health store (HKHealthStore.isHealthDataAvailable() is false on Mac), so
|
|
17186
|
+
// the capability answers `available: false` there and contributes no config.
|
|
17187
|
+
android: {
|
|
17188
|
+
// Health Connect permissions are runtime-granted through Health Connect's own dialog,
|
|
17189
|
+
// but the dialog only offers a permission the manifest declares.
|
|
17190
|
+
permissions: [
|
|
17191
|
+
"android.permission.health.READ_ACTIVE_CALORIES_BURNED",
|
|
17192
|
+
"android.permission.health.READ_DISTANCE",
|
|
17193
|
+
"android.permission.health.READ_EXERCISE",
|
|
17194
|
+
"android.permission.health.READ_HEART_RATE",
|
|
17195
|
+
"android.permission.health.READ_STEPS",
|
|
17196
|
+
// A saved workout carries its energy + distance as their OWN records alongside the
|
|
17197
|
+
// ExerciseSessionRecord, so writing them needs their write permissions too.
|
|
17198
|
+
"android.permission.health.WRITE_ACTIVE_CALORIES_BURNED",
|
|
17199
|
+
"android.permission.health.WRITE_DISTANCE",
|
|
17200
|
+
"android.permission.health.WRITE_EXERCISE"
|
|
17201
|
+
],
|
|
17202
|
+
// Health Connect will not show its permission dialog to an app with no privacy-
|
|
17203
|
+
// rationale screen. Android ≤13 finds it by the ACTION_SHOW_PERMISSIONS_RATIONALE
|
|
17204
|
+
// intent-filter; Android 14+ by a VIEW_PERMISSION_USAGE alias that only the system's
|
|
17205
|
+
// permission controller may start (START_VIEW_PERMISSION_USAGE).
|
|
17206
|
+
activities: [
|
|
17207
|
+
{
|
|
17208
|
+
name: "io.himalaya.health.HealthPermissionsRationaleActivity",
|
|
17209
|
+
exported: true,
|
|
17210
|
+
intentFilters: [{ actions: ["androidx.health.ACTION_SHOW_PERMISSIONS_RATIONALE"] }]
|
|
17211
|
+
},
|
|
17212
|
+
{
|
|
17213
|
+
name: "io.himalaya.health.HealthViewPermissionUsageActivity",
|
|
17214
|
+
targetActivity: "io.himalaya.health.HealthPermissionsRationaleActivity",
|
|
17215
|
+
exported: true,
|
|
17216
|
+
permission: "android.permission.START_VIEW_PERMISSION_USAGE",
|
|
17217
|
+
intentFilters: [
|
|
17218
|
+
{
|
|
17219
|
+
actions: ["android.intent.action.VIEW_PERMISSION_USAGE"],
|
|
17220
|
+
categories: ["android.intent.category.HEALTH_PERMISSIONS"]
|
|
17221
|
+
}
|
|
17222
|
+
]
|
|
17223
|
+
}
|
|
17224
|
+
],
|
|
17225
|
+
// On Android ≤13 Health Connect is a separate APK; without package visibility the
|
|
17226
|
+
// client reports it as not installed even when it is.
|
|
17227
|
+
queries: ["com.google.android.apps.healthdata"]
|
|
17228
|
+
},
|
|
17229
|
+
privacy: {
|
|
17230
|
+
// Health = heart rate; Fitness = steps / energy / distance / workouts. NOT linked and
|
|
17231
|
+
// NOT tracking: read on device for the app's own display. An app that syncs these to
|
|
17232
|
+
// a server must mark them linked in its native-config overrides.
|
|
17233
|
+
collectedDataTypes: [
|
|
17234
|
+
{ type: "NSPrivacyCollectedDataTypeHealth", linked: false, tracking: false, purposes: [APP_FUNCTIONALITY] },
|
|
17235
|
+
{ type: "NSPrivacyCollectedDataTypeFitness", linked: false, tracking: false, purposes: [APP_FUNCTIONALITY] }
|
|
17236
|
+
],
|
|
17237
|
+
dataSafety: [
|
|
17238
|
+
{ category: "Health and fitness", dataType: "Health info", purpose: "App functionality" },
|
|
17239
|
+
{ category: "Health and fitness", dataType: "Fitness info", purpose: "App functionality" }
|
|
17240
|
+
],
|
|
17241
|
+
reviewNotes: [
|
|
17242
|
+
"health: HealthKit (iOS) / Health Connect (Android). Apple Guideline 5.1.3 and Google Play's Health Connect policy both forbid using health data for advertising or selling it, and both require a privacy policy that names the health data read.",
|
|
17243
|
+
"Google Play requires a Health Connect declaration form in the Play Console for every android.permission.health.* permission requested; an app that ships these permissions without it is rejected.",
|
|
17244
|
+
"iOS hides READ denials: HealthKit never reports whether read access was refused, so `getPermissionStatus` answers `notDetermined` for reads and a denied read simply returns no samples.",
|
|
17245
|
+
"The HealthKit entitlement requires the HealthKit capability on the App ID for device and TestFlight builds."
|
|
17246
|
+
]
|
|
17247
|
+
}
|
|
17248
|
+
},
|
|
17168
17249
|
media_playback: {
|
|
17169
17250
|
ios: {
|
|
17170
17251
|
// Background audio for SDUI MediaPlayer sessions that opt into background playback.
|
|
@@ -17403,17 +17484,27 @@ function androidPlanFor(ids, ov = {}) {
|
|
|
17403
17484
|
const perms = /* @__PURE__ */ new Set();
|
|
17404
17485
|
const feats = /* @__PURE__ */ new Map();
|
|
17405
17486
|
const svcs = /* @__PURE__ */ new Map();
|
|
17487
|
+
const acts = /* @__PURE__ */ new Map();
|
|
17488
|
+
const queries = /* @__PURE__ */ new Set();
|
|
17406
17489
|
const add = (req) => {
|
|
17407
17490
|
for (const p2 of req?.permissions ?? []) perms.add(p2);
|
|
17408
17491
|
for (const f2 of req?.features ?? []) feats.set(f2.name, (feats.get(f2.name) ?? false) || f2.required);
|
|
17409
17492
|
for (const s2 of req?.services ?? []) svcs.set(s2.name, s2);
|
|
17493
|
+
for (const a2 of req?.activities ?? []) acts.set(a2.name, a2);
|
|
17494
|
+
for (const q2 of req?.queries ?? []) queries.add(q2);
|
|
17410
17495
|
};
|
|
17411
17496
|
for (const id of ids) add(nativeRequirementsFor(id)?.android);
|
|
17412
17497
|
add(ov);
|
|
17413
17498
|
return {
|
|
17414
17499
|
permissions: [...perms].sort(),
|
|
17415
17500
|
features: [...feats.entries()].sort((a2, b2) => a2[0].localeCompare(b2[0])).map(([name, required3]) => ({ name, required: required3 })),
|
|
17416
|
-
services: [...svcs.values()].sort((a2, b2) => a2.name.localeCompare(b2.name))
|
|
17501
|
+
services: [...svcs.values()].sort((a2, b2) => a2.name.localeCompare(b2.name)),
|
|
17502
|
+
// An <activity-alias> must come AFTER the activity it targets, or the manifest merger
|
|
17503
|
+
// rejects it — so aliases sort after plain activities, then by name.
|
|
17504
|
+
activities: [...acts.values()].sort(
|
|
17505
|
+
(a2, b2) => Number(!!a2.targetActivity) - Number(!!b2.targetActivity) || a2.name.localeCompare(b2.name)
|
|
17506
|
+
),
|
|
17507
|
+
queries: [...queries].sort()
|
|
17417
17508
|
};
|
|
17418
17509
|
}
|
|
17419
17510
|
var init_plan = __esm({
|
|
@@ -17448,6 +17539,9 @@ var init_builtins = __esm({
|
|
|
17448
17539
|
"files",
|
|
17449
17540
|
"godot",
|
|
17450
17541
|
"haptic",
|
|
17542
|
+
// Registered on every arm. Web (and the macOS build of the iOS arm) answer
|
|
17543
|
+
// `availability → { available: false }` and refuse the rest with `unavailable`.
|
|
17544
|
+
"health",
|
|
17451
17545
|
"himi_apps",
|
|
17452
17546
|
"iap",
|
|
17453
17547
|
"keyboard",
|
|
@@ -17561,6 +17655,7 @@ var init_known = __esm({
|
|
|
17561
17655
|
local_database: "registering it without the app's dataSchema writes declared-encrypted entities in plaintext (#1896) \u2014 the shell has to install the schema first",
|
|
17562
17656
|
live_activity: "needs a WidgetKit extension target in the shell's project, which a build cannot add",
|
|
17563
17657
|
base44: "needs the opt-in HimalayaCoreBase44 / :core-runtime-base44 SDK linked into the shell",
|
|
17658
|
+
health: "needs the opt-in HimalayaCoreHealth / :core-runtime-health store linked into the shell (unlinked, every verb answers `unavailable`)",
|
|
17564
17659
|
godot: "needs the opt-in Godot SPM product linked into the shell",
|
|
17565
17660
|
wix_platform: "needs the shell's boot to configure it with a Wix API client and launch services",
|
|
17566
17661
|
himi_apps: "is a multi-app host surface (Himi Player), not something one app's binary serves",
|
|
@@ -18356,12 +18451,34 @@ function renderAndroidXml(plan, indent) {
|
|
|
18356
18451
|
const lines = [];
|
|
18357
18452
|
for (const p2 of plan.permissions) lines.push(`${indent}<uses-permission android:name="${p2}" />`);
|
|
18358
18453
|
for (const f2 of plan.features) lines.push(`${indent}<uses-feature android:name="${f2.name}" android:required="${f2.required}" />`);
|
|
18454
|
+
const queries = plan.queries ?? [];
|
|
18455
|
+
if (queries.length > 0) {
|
|
18456
|
+
lines.push(`${indent}<queries>`);
|
|
18457
|
+
for (const q2 of queries) lines.push(`${indent} <package android:name="${q2}" />`);
|
|
18458
|
+
lines.push(`${indent}</queries>`);
|
|
18459
|
+
}
|
|
18359
18460
|
return lines;
|
|
18360
18461
|
}
|
|
18361
18462
|
function renderAndroidServicesXml(plan, indent) {
|
|
18362
|
-
|
|
18463
|
+
const lines = plan.services.map(
|
|
18363
18464
|
(s2) => `${indent}<service android:name="${s2.name}" android:exported="false" android:foregroundServiceType="${s2.foregroundServiceType}" />`
|
|
18364
18465
|
);
|
|
18466
|
+
for (const a2 of plan.activities ?? []) {
|
|
18467
|
+
const tag = a2.targetActivity ? "activity-alias" : "activity";
|
|
18468
|
+
const attrs = [`android:name="${a2.name}"`];
|
|
18469
|
+
if (a2.targetActivity) attrs.push(`android:targetActivity="${a2.targetActivity}"`);
|
|
18470
|
+
attrs.push(`android:exported="${a2.exported}"`);
|
|
18471
|
+
if (a2.permission) attrs.push(`android:permission="${a2.permission}"`);
|
|
18472
|
+
lines.push(`${indent}<${tag} ${attrs.join(" ")}>`);
|
|
18473
|
+
for (const f2 of a2.intentFilters) {
|
|
18474
|
+
lines.push(`${indent} <intent-filter>`);
|
|
18475
|
+
for (const act of f2.actions) lines.push(`${indent} <action android:name="${act}" />`);
|
|
18476
|
+
for (const c2 of f2.categories ?? []) lines.push(`${indent} <category android:name="${c2}" />`);
|
|
18477
|
+
lines.push(`${indent} </intent-filter>`);
|
|
18478
|
+
}
|
|
18479
|
+
lines.push(`${indent}</${tag}>`);
|
|
18480
|
+
}
|
|
18481
|
+
return lines;
|
|
18365
18482
|
}
|
|
18366
18483
|
function isBegin(line, kind, label2) {
|
|
18367
18484
|
const s2 = line.trim();
|
|
@@ -22504,6 +22621,7 @@ var init_capabilities_generated = __esm({
|
|
|
22504
22621
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
22505
22622
|
"godot": ["loadPack", "release", "send"],
|
|
22506
22623
|
"haptic": ["play"],
|
|
22624
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
22507
22625
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
22508
22626
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
22509
22627
|
"keyboard": ["dismiss"],
|
|
@@ -22546,6 +22664,7 @@ var init_capabilities_generated = __esm({
|
|
|
22546
22664
|
"files": ["@himalaya/files"],
|
|
22547
22665
|
"godot": ["@himalaya/godot"],
|
|
22548
22666
|
"haptic": ["@himalaya/haptic"],
|
|
22667
|
+
"health": ["@himalaya/health"],
|
|
22549
22668
|
"himi_apps": ["@himalaya/himi-apps"],
|
|
22550
22669
|
"iap": ["@himalaya/iap"],
|
|
22551
22670
|
"keyboard": ["@himalaya/keyboard"],
|
|
@@ -22605,8 +22724,8 @@ var init_shell_capabilities_generated = __esm({
|
|
|
22605
22724
|
appDir: "apps/demo-app",
|
|
22606
22725
|
shared: false,
|
|
22607
22726
|
extensible: false,
|
|
22608
|
-
built: ["base44", "biometrics", "calendar", "calls", "contacts", "haptic", "keyboard", "live_activity", "location", "media_playback", "on_device_ai", "photos", "push", "speech", "tasks", "ui"],
|
|
22609
|
-
serves: ["base44", "biometrics", "calendar", "calls", "contacts", "haptic", "keyboard", "live_activity", "location", "media_playback", "on_device_ai", "photos", "push", "speech", "tasks", "ui"]
|
|
22727
|
+
built: ["base44", "biometrics", "calendar", "calls", "contacts", "haptic", "health", "keyboard", "live_activity", "location", "media_playback", "on_device_ai", "photos", "push", "speech", "tasks", "ui"],
|
|
22728
|
+
serves: ["base44", "biometrics", "calendar", "calls", "contacts", "haptic", "health", "keyboard", "live_activity", "location", "media_playback", "on_device_ai", "photos", "push", "speech", "tasks", "ui"]
|
|
22610
22729
|
},
|
|
22611
22730
|
"owner-lite": {
|
|
22612
22731
|
appDir: "apps/himi-owner-lite",
|
|
@@ -143329,23 +143448,23 @@ var init_preview_assets_generated = __esm({
|
|
|
143329
143448
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
143330
143449
|
init_preview_assets_format();
|
|
143331
143450
|
PREVIEW_ASSET_MANIFEST = [
|
|
143332
|
-
{ key: "assets/index-
|
|
143333
|
-
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/octet-stream", offset:
|
|
143334
|
-
{ key: "assets/pdfDocument-
|
|
143335
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
143336
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
143337
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
143338
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
143339
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
143340
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
143341
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
143342
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
143343
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
143344
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
143345
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
143346
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
143347
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
143348
|
-
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset:
|
|
143451
|
+
{ key: "assets/index-DcqakqyW.js", contentType: "application/javascript; charset=utf-8", offset: 8, length: 1191096, sha256: "83e1d51efc75dc63a19cd5bd9072d50e8b831d6c39152922cdc491225f43d696" },
|
|
143452
|
+
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/octet-stream", offset: 1191104, length: 1317034, sha256: "a33cfe728c584fdba4fcc1fd54bcdc2f9f2f13889ddbb5b2bd1d0f8cbe49b84e" },
|
|
143453
|
+
{ key: "assets/pdfDocument-CITrNgUQ.js", contentType: "application/javascript; charset=utf-8", offset: 2508138, length: 489166, sha256: "202328a260c149a8bdf211a58a04cb74114e40510a4c0dd0511045b3a6279b47" },
|
|
143454
|
+
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset: 2997304, length: 4610, sha256: "994062dd7af4186a739de55dd9e151c63b6301f8e2cbafc608d35c2e87da0cd2" },
|
|
143455
|
+
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset: 3001914, length: 488584, sha256: "d7598e12c5dbef095ff8272cfc55da0250bd07fbdecbac8a530b9b277872a134" },
|
|
143456
|
+
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset: 3490498, length: 90924, sha256: "ec4c7d63772d980d6e147b2df6215fd2737e4b04cebe0cf7e11dc695fb63cdcf" },
|
|
143457
|
+
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset: 3581422, length: 90984, sha256: "bf4c16a2774edd38a921edf3099469866cd74c094fd596f3fa4e81f54a04dfaa" },
|
|
143458
|
+
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset: 3672406, length: 90980, sha256: "368faca44fb9f7207e4af784e94750b1ee59c1098b8689e0f4a918926f244fb5" },
|
|
143459
|
+
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset: 3763386, length: 90872, sha256: "97ed8f1a6772abe26e3d8af5cecfc4b02faa94497d585b0398b5053b739a70c1" },
|
|
143460
|
+
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset: 3854258, length: 90980, sha256: "642feab8a48ddf6c7a89d7c2a7c0edfa0e6e773f671287e460e222703563191e" },
|
|
143461
|
+
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset: 3945238, length: 108636, sha256: "37c179b4fefb63ea9637322b84583a2df53aa226c150294eea1675c14b1b8e29" },
|
|
143462
|
+
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset: 4053874, length: 109084, sha256: "62e2fe4718129f36ecdb0ae4de385bd6b81ecc876146447167c6c140fad699a9" },
|
|
143463
|
+
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset: 4162958, length: 109048, sha256: "4ecf270136af928612c76fe4ebade91d8156975e5ea4c0cf9225501dd1788e02" },
|
|
143464
|
+
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset: 4272006, length: 107700, sha256: "dee56f09fd3efc127c1ea95557edc74110c1460a46287da36e0af25efd341ef5" },
|
|
143465
|
+
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset: 4379706, length: 88108, sha256: "dced97a77624bc5f8b1ae65850360908297f4588e09feb6f22792d29dc7e765b" },
|
|
143466
|
+
{ key: "index.html", contentType: "text/html; charset=utf-8", offset: 4467814, length: 4947, sha256: "2189ce1438ed15f3a041d5e9950c92b27a18d288103ac04249b184c369137721" },
|
|
143467
|
+
{ key: "t5-frame.html", contentType: "text/html; charset=utf-8", offset: 4472761, length: 17344, sha256: "d057298d75e7373e5e2c4d11b7d1bcbea88e03af555ba63d97641c78509c58e4" }
|
|
143349
143468
|
];
|
|
143350
143469
|
}
|
|
143351
143470
|
});
|
|
Binary file
|
package/guides/app-config.md
CHANGED
|
@@ -115,7 +115,7 @@ with a native footprint only arrives with a new binary. `himi docs capabilities`
|
|
|
115
115
|
loop — discover, declare, validate, ship — and `himi capabilities <id>` shows the import and which
|
|
116
116
|
shells' binaries serve it.
|
|
117
117
|
|
|
118
|
-
App-level capability vocabulary: `camera`, `barcode_scanner`, `biometrics`, `secure_storage`, `share`, `push`, `file_picker`, `files`, `open_url`, `pdf`, `clipboard`, `photos`, `presigned_upload`, `ui`, `calendar`, `contacts`, `tasks`, `audio_record`, `audio_record_background`, `calls`, `location`, `location_background`, `motion`, `media_playback`, `webview`, `browser_auth`, `haptic`, `himi_apps`, `iap`, `keyboard`, `wix_cashier`, `live_activity`, `local_database`, `speech`, `speaker_diarization`, `system_intents`, `on_device_ai`, `app_info`, `release_control`, `godot`, `base44`.
|
|
118
|
+
App-level capability vocabulary: `camera`, `barcode_scanner`, `biometrics`, `secure_storage`, `share`, `push`, `file_picker`, `files`, `open_url`, `pdf`, `clipboard`, `photos`, `presigned_upload`, `ui`, `calendar`, `contacts`, `tasks`, `audio_record`, `audio_record_background`, `calls`, `location`, `location_background`, `motion`, `health`, `media_playback`, `webview`, `browser_auth`, `haptic`, `himi_apps`, `iap`, `keyboard`, `wix_cashier`, `live_activity`, `local_database`, `speech`, `speaker_diarization`, `system_intents`, `on_device_ai`, `app_info`, `release_control`, `godot`, `base44`.
|
|
119
119
|
|
|
120
120
|
## What `himi validate` checks (7 passes)
|
|
121
121
|
|
|
@@ -31,6 +31,7 @@ package in one greppable file) or `GET /v1/sdk/<name>` over HTTP; in the CLI,
|
|
|
31
31
|
- `@himalaya/godot` — Tier-5 typed binding for a Godot game surface.
|
|
32
32
|
- `@himalaya/gpx` — read and write GPX 1.1, and compute track statistics.
|
|
33
33
|
- `@himalaya/haptic` — Tier-5 typed binding for the platform's haptic capability.
|
|
34
|
+
- `@himalaya/health` — Tier-5 typed binding for the platform HEALTH store.
|
|
34
35
|
- `@himalaya/himi-apps` — Tier-5 typed binding for cross-app open / host queries.
|
|
35
36
|
- `@himalaya/iap` — Tier-5 typed binding to the platform's in-app-purchase capability.
|
|
36
37
|
- `@himalaya/keyboard` — Tier-5 typed binding for the platform's keyboard capability.
|
|
@@ -1368,6 +1368,151 @@
|
|
|
1368
1368
|
}
|
|
1369
1369
|
]
|
|
1370
1370
|
},
|
|
1371
|
+
{
|
|
1372
|
+
"name": "@himalaya/health",
|
|
1373
|
+
"source": "core/sdk/health/src/index.ts",
|
|
1374
|
+
"description": "Tier-5 typed binding for the platform HEALTH store.",
|
|
1375
|
+
"api": [
|
|
1376
|
+
{
|
|
1377
|
+
"name": "HealthType",
|
|
1378
|
+
"kind": "type",
|
|
1379
|
+
"jsdoc": "/** A readable health data type. */",
|
|
1380
|
+
"decl": "export type HealthType = \"steps\" | \"heartRate\" | \"activeEnergy\" | \"distance\" | \"workouts\";"
|
|
1381
|
+
},
|
|
1382
|
+
{
|
|
1383
|
+
"name": "HealthWriteType",
|
|
1384
|
+
"kind": "type",
|
|
1385
|
+
"jsdoc": "/** A writable health data type. v1 writes workouts only. */",
|
|
1386
|
+
"decl": "export type HealthWriteType = \"workouts\";"
|
|
1387
|
+
},
|
|
1388
|
+
{
|
|
1389
|
+
"name": "HealthPermissionState",
|
|
1390
|
+
"kind": "type",
|
|
1391
|
+
"jsdoc": "",
|
|
1392
|
+
"decl": "export type HealthPermissionState = \"granted\" | \"denied\" | \"notDetermined\";"
|
|
1393
|
+
},
|
|
1394
|
+
{
|
|
1395
|
+
"name": "HealthBucket",
|
|
1396
|
+
"kind": "type",
|
|
1397
|
+
"jsdoc": "/** Aggregation bucket for `query`. Omitted ⇒ one total (cumulative types) or raw samples. */",
|
|
1398
|
+
"decl": "export type HealthBucket = \"hour\" | \"day\";"
|
|
1399
|
+
},
|
|
1400
|
+
{
|
|
1401
|
+
"name": "WorkoutActivity",
|
|
1402
|
+
"kind": "type",
|
|
1403
|
+
"jsdoc": "",
|
|
1404
|
+
"decl": "export type WorkoutActivity = \"running\" | \"walking\" | \"cycling\" | \"strength\" | \"other\";"
|
|
1405
|
+
},
|
|
1406
|
+
{
|
|
1407
|
+
"name": "HealthErrorCode",
|
|
1408
|
+
"kind": "type",
|
|
1409
|
+
"jsdoc": "",
|
|
1410
|
+
"decl": "export type HealthErrorCode = \"unavailable\" | \"not_authorized\" | \"invalid_argument\" | \"failed\";"
|
|
1411
|
+
},
|
|
1412
|
+
{
|
|
1413
|
+
"name": "HEALTH_TYPES",
|
|
1414
|
+
"kind": "const",
|
|
1415
|
+
"jsdoc": "",
|
|
1416
|
+
"decl": "export const HEALTH_TYPES: readonly HealthType[] = [\"steps\", \"heartRate\", \"activeEnergy\", \"distance\", \"workouts\"];"
|
|
1417
|
+
},
|
|
1418
|
+
{
|
|
1419
|
+
"name": "WORKOUT_ACTIVITIES",
|
|
1420
|
+
"kind": "const",
|
|
1421
|
+
"jsdoc": "",
|
|
1422
|
+
"decl": "export const WORKOUT_ACTIVITIES: readonly WorkoutActivity[] = [\"running\", \"walking\", \"cycling\", \"strength\", \"other\"];"
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
"name": "HEALTH_UNITS",
|
|
1426
|
+
"kind": "const",
|
|
1427
|
+
"jsdoc": "/** The fixed unit each type's `value` is reported in. */",
|
|
1428
|
+
"decl": "export const HEALTH_UNITS: Readonly<Record<HealthType, string>> = {\n steps: \"count\",\n heartRate: \"bpm\",\n activeEnergy: \"kcal\",\n distance: \"m\",\n workouts: \"s\",\n};"
|
|
1429
|
+
},
|
|
1430
|
+
{
|
|
1431
|
+
"name": "HealthAvailability",
|
|
1432
|
+
"kind": "interface",
|
|
1433
|
+
"jsdoc": "",
|
|
1434
|
+
"decl": "export interface HealthAvailability {\n available: boolean;\n /** Why not, when `available` is false — e.g. \"web has no health store\",\n * \"Health Connect is not installed\". */\n reason?: string;\n}"
|
|
1435
|
+
},
|
|
1436
|
+
{
|
|
1437
|
+
"name": "HealthSample",
|
|
1438
|
+
"kind": "interface",
|
|
1439
|
+
"jsdoc": "",
|
|
1440
|
+
"decl": "export interface HealthSample {\n /** ISO-8601. */\n start: string;\n /** ISO-8601. */\n end: string;\n value: number;\n unit: string;\n /** Workouts only: the activity, mapped back onto the v1 set (\"other\" for anything else). */\n activity?: WorkoutActivity;\n}"
|
|
1441
|
+
},
|
|
1442
|
+
{
|
|
1443
|
+
"name": "HealthQuery",
|
|
1444
|
+
"kind": "interface",
|
|
1445
|
+
"jsdoc": "",
|
|
1446
|
+
"decl": "export interface HealthQuery {\n type: HealthType;\n /** ISO-8601, inclusive. */\n from: string;\n /** ISO-8601, exclusive. */\n to: string;\n /** steps / activeEnergy / distance are SUMMED per bucket; heartRate is AVERAGED per bucket;\n * workouts ignore it (one sample per workout). */\n bucket?: HealthBucket;\n}"
|
|
1447
|
+
},
|
|
1448
|
+
{
|
|
1449
|
+
"name": "Workout",
|
|
1450
|
+
"kind": "interface",
|
|
1451
|
+
"jsdoc": "",
|
|
1452
|
+
"decl": "export interface Workout {\n activity: WorkoutActivity;\n /** ISO-8601. */\n start: string;\n /** ISO-8601, after `start`. */\n end: string;\n energyKcal?: number;\n distanceM?: number;\n}"
|
|
1453
|
+
},
|
|
1454
|
+
{
|
|
1455
|
+
"name": "HealthError",
|
|
1456
|
+
"kind": "interface",
|
|
1457
|
+
"jsdoc": "/** The typed rejection every verb throws. A plain Error carrying `code` — worker bundles are\n * compiled to a target without class syntax, so this is a factory, not a subclass. */",
|
|
1458
|
+
"decl": "export interface HealthError extends Error {\n name: \"HealthError\";\n code: HealthErrorCode;\n}"
|
|
1459
|
+
},
|
|
1460
|
+
{
|
|
1461
|
+
"name": "healthError",
|
|
1462
|
+
"kind": "function",
|
|
1463
|
+
"jsdoc": "/** Build a [HealthError] — what the binding throws for every native `{ error }` reply. */",
|
|
1464
|
+
"decl": "export function healthError(code: HealthErrorCode, message: string): HealthError;"
|
|
1465
|
+
},
|
|
1466
|
+
{
|
|
1467
|
+
"name": "isHealthError",
|
|
1468
|
+
"kind": "function",
|
|
1469
|
+
"jsdoc": "/** Narrow a caught value: `catch (e) { if (isHealthError(e) && e.code === \"unavailable\") … }`. */",
|
|
1470
|
+
"decl": "export function isHealthError(e: unknown): e is HealthError;"
|
|
1471
|
+
},
|
|
1472
|
+
{
|
|
1473
|
+
"name": "availability",
|
|
1474
|
+
"kind": "function",
|
|
1475
|
+
"jsdoc": "/** Whether this device has a health store the app can reach. Call it first and branch. */",
|
|
1476
|
+
"decl": "export async function availability(): Promise<HealthAvailability>;"
|
|
1477
|
+
},
|
|
1478
|
+
{
|
|
1479
|
+
"name": "requestPermission",
|
|
1480
|
+
"kind": "function",
|
|
1481
|
+
"jsdoc": "/**\n * Prompt for read (and optionally write) access. Resolves with the types the platform\n * reports as granted — on iOS a read type counts as granted once asked (see header).\n * Writing workouts also covers the energy + distance samples a saved workout carries.\n */",
|
|
1482
|
+
"decl": "export async function requestPermission(p: { read: HealthType[]; write?: HealthWriteType[] }): Promise<{ granted: HealthType[] }>;"
|
|
1483
|
+
},
|
|
1484
|
+
{
|
|
1485
|
+
"name": "getPermissionStatus",
|
|
1486
|
+
"kind": "function",
|
|
1487
|
+
"jsdoc": "/** Current READ permission per type, without prompting. iOS reads are always \"notDetermined\". */",
|
|
1488
|
+
"decl": "export async function getPermissionStatus(p: { types: HealthType[] }): Promise<Record<HealthType, HealthPermissionState>>;"
|
|
1489
|
+
},
|
|
1490
|
+
{
|
|
1491
|
+
"name": "query",
|
|
1492
|
+
"kind": "function",
|
|
1493
|
+
"jsdoc": "/** Read samples of one type over [from, to). */",
|
|
1494
|
+
"decl": "export async function query(p: HealthQuery): Promise<{ samples: HealthSample[] }>;"
|
|
1495
|
+
},
|
|
1496
|
+
{
|
|
1497
|
+
"name": "saveWorkout",
|
|
1498
|
+
"kind": "function",
|
|
1499
|
+
"jsdoc": "/** Save a completed workout (with its energy/distance, when given). Resolves with its store id. */",
|
|
1500
|
+
"decl": "export async function saveWorkout(w: Workout): Promise<{ id: string }>;"
|
|
1501
|
+
},
|
|
1502
|
+
{
|
|
1503
|
+
"name": "version",
|
|
1504
|
+
"kind": "const",
|
|
1505
|
+
"jsdoc": "",
|
|
1506
|
+
"decl": "export const version = 1;"
|
|
1507
|
+
},
|
|
1508
|
+
{
|
|
1509
|
+
"name": "health",
|
|
1510
|
+
"kind": "const",
|
|
1511
|
+
"jsdoc": "/** The whole surface as one namespace: `import { health } from \"@himalaya/health\"`. */",
|
|
1512
|
+
"decl": "export const health = { availability, requestPermission, getPermissionStatus, query, saveWorkout, version };"
|
|
1513
|
+
}
|
|
1514
|
+
]
|
|
1515
|
+
},
|
|
1371
1516
|
{
|
|
1372
1517
|
"name": "@himalaya/himi-apps",
|
|
1373
1518
|
"source": "core/sdk/himi-apps/src/index.ts",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1232.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"artifactId": "himalaya-cli"
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"falconPackageHash": "
|
|
70
|
+
"falconPackageHash": "19c1239851ec3856adb71952d1e9dcb18ea9cdd23456e90bb311a12d"
|
|
71
71
|
}
|