@wix/himalaya-cli 0.1230.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 +141 -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"),
|
|
@@ -6877,6 +6878,7 @@ function resolveTranslation(value, catalog, sourceCatalog) {
|
|
|
6877
6878
|
var BINDING_SIGILS, BINDING_SIGIL_RE, TRANSLATION_PREFIX, TRANSLATION_KEY_RE;
|
|
6878
6879
|
var init_bindings = __esm({
|
|
6879
6880
|
"../../core/ts/src/bindings.ts"() {
|
|
6881
|
+
"use strict";
|
|
6880
6882
|
BINDING_SIGILS = ["service", "flag", "item", "t"];
|
|
6881
6883
|
BINDING_SIGIL_RE = new RegExp(
|
|
6882
6884
|
`^\\$(?:${BINDING_SIGILS.filter((s2) => s2 !== "t").join("|")})\\b|^\\$t:`
|
|
@@ -17164,6 +17166,86 @@ var init_native_requirements = __esm({
|
|
|
17164
17166
|
]
|
|
17165
17167
|
}
|
|
17166
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
|
+
},
|
|
17167
17249
|
media_playback: {
|
|
17168
17250
|
ios: {
|
|
17169
17251
|
// Background audio for SDUI MediaPlayer sessions that opt into background playback.
|
|
@@ -17402,17 +17484,27 @@ function androidPlanFor(ids, ov = {}) {
|
|
|
17402
17484
|
const perms = /* @__PURE__ */ new Set();
|
|
17403
17485
|
const feats = /* @__PURE__ */ new Map();
|
|
17404
17486
|
const svcs = /* @__PURE__ */ new Map();
|
|
17487
|
+
const acts = /* @__PURE__ */ new Map();
|
|
17488
|
+
const queries = /* @__PURE__ */ new Set();
|
|
17405
17489
|
const add = (req) => {
|
|
17406
17490
|
for (const p2 of req?.permissions ?? []) perms.add(p2);
|
|
17407
17491
|
for (const f2 of req?.features ?? []) feats.set(f2.name, (feats.get(f2.name) ?? false) || f2.required);
|
|
17408
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);
|
|
17409
17495
|
};
|
|
17410
17496
|
for (const id of ids) add(nativeRequirementsFor(id)?.android);
|
|
17411
17497
|
add(ov);
|
|
17412
17498
|
return {
|
|
17413
17499
|
permissions: [...perms].sort(),
|
|
17414
17500
|
features: [...feats.entries()].sort((a2, b2) => a2[0].localeCompare(b2[0])).map(([name, required3]) => ({ name, required: required3 })),
|
|
17415
|
-
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()
|
|
17416
17508
|
};
|
|
17417
17509
|
}
|
|
17418
17510
|
var init_plan = __esm({
|
|
@@ -17447,6 +17539,9 @@ var init_builtins = __esm({
|
|
|
17447
17539
|
"files",
|
|
17448
17540
|
"godot",
|
|
17449
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",
|
|
17450
17545
|
"himi_apps",
|
|
17451
17546
|
"iap",
|
|
17452
17547
|
"keyboard",
|
|
@@ -17560,6 +17655,7 @@ var init_known = __esm({
|
|
|
17560
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",
|
|
17561
17656
|
live_activity: "needs a WidgetKit extension target in the shell's project, which a build cannot add",
|
|
17562
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`)",
|
|
17563
17659
|
godot: "needs the opt-in Godot SPM product linked into the shell",
|
|
17564
17660
|
wix_platform: "needs the shell's boot to configure it with a Wix API client and launch services",
|
|
17565
17661
|
himi_apps: "is a multi-app host surface (Himi Player), not something one app's binary serves",
|
|
@@ -18355,12 +18451,34 @@ function renderAndroidXml(plan, indent) {
|
|
|
18355
18451
|
const lines = [];
|
|
18356
18452
|
for (const p2 of plan.permissions) lines.push(`${indent}<uses-permission android:name="${p2}" />`);
|
|
18357
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
|
+
}
|
|
18358
18460
|
return lines;
|
|
18359
18461
|
}
|
|
18360
18462
|
function renderAndroidServicesXml(plan, indent) {
|
|
18361
|
-
|
|
18463
|
+
const lines = plan.services.map(
|
|
18362
18464
|
(s2) => `${indent}<service android:name="${s2.name}" android:exported="false" android:foregroundServiceType="${s2.foregroundServiceType}" />`
|
|
18363
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;
|
|
18364
18482
|
}
|
|
18365
18483
|
function isBegin(line, kind, label2) {
|
|
18366
18484
|
const s2 = line.trim();
|
|
@@ -22503,6 +22621,7 @@ var init_capabilities_generated = __esm({
|
|
|
22503
22621
|
"files": ["list", "readText", "remove", "stat", "write"],
|
|
22504
22622
|
"godot": ["loadPack", "release", "send"],
|
|
22505
22623
|
"haptic": ["play"],
|
|
22624
|
+
"health": ["availability", "getPermissionStatus", "query", "requestPermission", "saveWorkout"],
|
|
22506
22625
|
"himi_apps": ["canOpen", "current", "hostInfo", "open"],
|
|
22507
22626
|
"iap": ["consume", "entitlements", "finishTransaction", "getPaywallConfig", "getProducts", "getUnfinishedTransactions", "purchase", "purchaseForVerification", "restore"],
|
|
22508
22627
|
"keyboard": ["dismiss"],
|
|
@@ -22545,6 +22664,7 @@ var init_capabilities_generated = __esm({
|
|
|
22545
22664
|
"files": ["@himalaya/files"],
|
|
22546
22665
|
"godot": ["@himalaya/godot"],
|
|
22547
22666
|
"haptic": ["@himalaya/haptic"],
|
|
22667
|
+
"health": ["@himalaya/health"],
|
|
22548
22668
|
"himi_apps": ["@himalaya/himi-apps"],
|
|
22549
22669
|
"iap": ["@himalaya/iap"],
|
|
22550
22670
|
"keyboard": ["@himalaya/keyboard"],
|
|
@@ -22604,8 +22724,8 @@ var init_shell_capabilities_generated = __esm({
|
|
|
22604
22724
|
appDir: "apps/demo-app",
|
|
22605
22725
|
shared: false,
|
|
22606
22726
|
extensible: false,
|
|
22607
|
-
built: ["base44", "biometrics", "calendar", "calls", "contacts", "haptic", "keyboard", "live_activity", "location", "media_playback", "on_device_ai", "photos", "push", "speech", "tasks", "ui"],
|
|
22608
|
-
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"]
|
|
22609
22729
|
},
|
|
22610
22730
|
"owner-lite": {
|
|
22611
22731
|
appDir: "apps/himi-owner-lite",
|
|
@@ -143328,23 +143448,23 @@ var init_preview_assets_generated = __esm({
|
|
|
143328
143448
|
"../../packages/serve/src/preview-assets.generated.ts"() {
|
|
143329
143449
|
init_preview_assets_format();
|
|
143330
143450
|
PREVIEW_ASSET_MANIFEST = [
|
|
143331
|
-
{ key: "assets/index-
|
|
143332
|
-
{ key: "assets/pdf.worker.min-BmVo14Nb.mjs", contentType: "application/octet-stream", offset:
|
|
143333
|
-
{ key: "assets/pdfDocument-
|
|
143334
|
-
{ key: "fonts/Roboto-LICENSE.txt", contentType: "application/octet-stream", offset:
|
|
143335
|
-
{ key: "fonts/Roboto-Variable.ttf", contentType: "font/ttf", offset:
|
|
143336
|
-
{ key: "fonts/WixMadeforDisplay-Bold.ttf", contentType: "font/ttf", offset:
|
|
143337
|
-
{ key: "fonts/WixMadeforDisplay-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
143338
|
-
{ key: "fonts/WixMadeforDisplay-Medium.ttf", contentType: "font/ttf", offset:
|
|
143339
|
-
{ key: "fonts/WixMadeforDisplay-Regular.ttf", contentType: "font/ttf", offset:
|
|
143340
|
-
{ key: "fonts/WixMadeforDisplay-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
143341
|
-
{ key: "fonts/WixMadeforText-Bold.ttf", contentType: "font/ttf", offset:
|
|
143342
|
-
{ key: "fonts/WixMadeforText-ExtraBold.ttf", contentType: "font/ttf", offset:
|
|
143343
|
-
{ key: "fonts/WixMadeforText-Medium.ttf", contentType: "font/ttf", offset:
|
|
143344
|
-
{ key: "fonts/WixMadeforText-Regular.ttf", contentType: "font/ttf", offset:
|
|
143345
|
-
{ key: "fonts/WixMadeforText-SemiBold.ttf", contentType: "font/ttf", offset:
|
|
143346
|
-
{ key: "index.html", contentType: "text/html; charset=utf-8", offset:
|
|
143347
|
-
{ 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" }
|
|
143348
143468
|
];
|
|
143349
143469
|
}
|
|
143350
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
|
}
|