craft-native 0.0.236 → 0.0.238
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +71 -0
- package/dist/android/src/emulator.d.ts +23 -0
- package/dist/android/src/index.d.ts +7 -1
- package/dist/android/src/index.js +280 -98
- package/dist/android/templates/CraftBridge.kt.template +65 -54
- package/dist/android/templates/CraftNative.kt.template +27 -0
- package/dist/android/templates/CraftNativeCapabilities.kt.template +55 -6
- package/dist/android/templates/CraftNativeServices.kt.template +45 -35
- package/dist/android/templates/CraftNativeShell.kt.template +103 -20
- package/dist/android/templates/LocationRecordingService.kt.template +252 -46
- package/dist/android/templates/MainActivityNative.kt.template +163 -5
- package/dist/android-adb.d.ts +2 -0
- package/dist/api/index.d.ts +1 -1
- package/dist/api/mobile.d.ts +49 -14
- package/dist/browser/storage.d.ts +3 -0
- package/dist/browser.js +163 -51
- package/dist/cli.js +1 -1
- package/dist/components/index.d.ts +33 -0
- package/dist/index.cjs +126 -12
- package/dist/index.js +126 -12
- package/dist/ios/src/app-shortcuts.d.ts +11 -0
- package/dist/ios/src/index.d.ts +7 -0
- package/dist/ios/src/index.js +65 -1
- package/dist/ios/src/testing.d.ts +2 -0
- package/dist/ios/templates/CraftApp.swift +392 -88
- package/dist/ios/templates/CraftHeartRate.swift +141 -44
- package/dist/ios/templates/CraftNativeActions.swift +46 -48
- package/dist/ios/templates/CraftNativeScreen.swift +177 -10
- package/dist/ios/templates/CraftPersistentStorage.swift +99 -0
- package/dist/ios/templates/CraftRecordingArchive.swift +85 -0
- package/dist/ios/templates/testing/DriverTests.swift.template +8 -1
- package/dist/mobile-testing.js +30 -4
- package/dist/mobile.js +169 -17
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -575,3 +575,74 @@ MIT © [Chris Breuer](https://github.com/chrisbbreuer)
|
|
|
575
575
|
- [Examples](../examples-ts)
|
|
576
576
|
- [Benchmarks](../../benchmarks)
|
|
577
577
|
- [Issues](https://github.com/home-lang/craft/issues)
|
|
578
|
+
|
|
579
|
+
### Recording ownership and recovery
|
|
580
|
+
|
|
581
|
+
Native STX screens and the mobile page use the same native recorder. Before
|
|
582
|
+
starting an account-owned GPS or heart-rate session, require
|
|
583
|
+
`location.supportsRecordingOwnership()` or `heartRate.supportsRecordingOwnership()`.
|
|
584
|
+
The check requires both the current SDK adapter and a capable native host.
|
|
585
|
+
Unsupported hosts reject guarded operations with
|
|
586
|
+
`RECORDING_OWNERSHIP_UNSUPPORTED`; they never discard the guard and retry.
|
|
587
|
+
|
|
588
|
+
For account-owned recordings, also require `supportsRecordingIntentIdentity()`
|
|
589
|
+
on the chosen service. Allocate distinct GPS and heart-rate IDs with
|
|
590
|
+
`await crypto.randomUUID()` from `craft-native/mobile`, capture the account,
|
|
591
|
+
workout and clock generation, and persist those IDs **before** calling
|
|
592
|
+
`startRecording({ recordingId: id })`. Recheck the captured owner after each
|
|
593
|
+
await. The native recorder starts that exact ID and refuses reuse of a current,
|
|
594
|
+
completed or acknowledged ID. The SDK checks the response ID; older hosts and
|
|
595
|
+
adapters reject with `RECORDING_INTENT_IDENTITY_UNSUPPORTED`. A lost start
|
|
596
|
+
response or a full disk during a later checkpoint can then recover the exact
|
|
597
|
+
precommitted ID without adopting an unknown recording. The asynchronous Crypto
|
|
598
|
+
service uses the platform's secure UUID generator; an unsupported native host
|
|
599
|
+
rejects with `CRYPTO_UNSUPPORTED` without falling back to JavaScript entropy.
|
|
600
|
+
|
|
601
|
+
Pass `{ expectedId: id }` to pause, resume, stop, read and get-state calls. Heart-rate reads also accept
|
|
602
|
+
`since`. A supplied empty, whitespace or non-string ID rejects with
|
|
603
|
+
`INVALID_ARGUMENT`. Starting while another session is active rejects with
|
|
604
|
+
`RECORDING_ALREADY_ACTIVE`, preserving its files.
|
|
605
|
+
|
|
606
|
+
Completed recordings survive relaunch and subsequent sessions. Guarded reads,
|
|
607
|
+
get-state and repeated stops can recover a completed A while B is recording;
|
|
608
|
+
pausing or resuming A rejects with `RECORDING_CONFLICT`. The native recorder
|
|
609
|
+
archives A before reusing its current track. A failed archive or unreadable
|
|
610
|
+
known track refuses replacement rather than truncating the only copy.
|
|
611
|
+
|
|
612
|
+
After stopping, await durable storage of the result under the captured account
|
|
613
|
+
owner, then call `acknowledgeRecording({ expectedId: id })`. ACK is idempotent,
|
|
614
|
+
refuses active recordings and never removes another owner's current session.
|
|
615
|
+
It writes a persistent tombstone before cleanup, so interrupted deletion cannot
|
|
616
|
+
resurrect acknowledged data. Subsequent guarded reads return
|
|
617
|
+
`RECORDING_NOT_FOUND`. A failed account checkpoint must leave the native copy
|
|
618
|
+
unacknowledged for recovery. Stopping alone does not acknowledge a recording.
|
|
619
|
+
|
|
620
|
+
For account drafts, use `storage.supportsCompareAndSet()` and
|
|
621
|
+
`storage.compareAndSet(key, expectedValue, nextValue)`. This operation replaces
|
|
622
|
+
an **existing** matching JSON value under the native storage lock and waits for
|
|
623
|
+
its durable write. Object key order does not matter; array order and JSON types
|
|
624
|
+
do. A missing or changed key returns `false` without creating or changing it.
|
|
625
|
+
A storage failure rejects, preserving the previous value. Hosts without the
|
|
626
|
+
explicit `storageCompareAndSet` capability reject with
|
|
627
|
+
`STORAGE_COMPARE_AND_SET_UNSUPPORTED`; there is no read-then-set fallback.
|
|
628
|
+
|
|
629
|
+
For a missing draft, require `storage.supportsSetIfAbsent()` and atomically
|
|
630
|
+
register it with `storage.setIfAbsent(key, intent)`. It returns `true` only after
|
|
631
|
+
durable creation; any existing value, including JSON `null`, returns `false`.
|
|
632
|
+
An unsupported host rejects with `STORAGE_SET_IF_ABSENT_UNSUPPORTED`. Use CAS
|
|
633
|
+
for an existing draft; neither registration path uses ordinary `set` after a
|
|
634
|
+
read. The browser driver uses Web Locks across tabs for all Storage operations
|
|
635
|
+
and account cleanup. A queued operation whose captured account changes rejects
|
|
636
|
+
with `STORAGE_SCOPE_CHANGED`, so a previous account cannot write into the new
|
|
637
|
+
account's namespace or mistake that namespace for a deleted draft.
|
|
638
|
+
|
|
639
|
+
When keeping a completed result, read the latest value through asynchronous
|
|
640
|
+
`storage.get`, validate its captured account/session/recording identity, merge
|
|
641
|
+
its latest feedback, then compare-and-set that exact value. Retry concurrent
|
|
642
|
+
feedback changes with at most two fresh reads; never overwrite a newer session
|
|
643
|
+
or recreate a deleted draft. Only a successful durable checkpoint permits the
|
|
644
|
+
normal ACK. A failed write or exhausted conflict leaves the native archive.
|
|
645
|
+
An explicit discard may ACK the captured old ID only after a fresh committed
|
|
646
|
+
native read proves that its previously registered intent was deleted or
|
|
647
|
+
replaced. A cached missing draft or an unsuccessful initial registration is
|
|
648
|
+
not evidence of deletion.
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export interface AndroidEmulatorOptions {
|
|
2
|
+
sdkRoot: string;
|
|
3
|
+
sdkmanager: string;
|
|
4
|
+
avdmanager: string;
|
|
5
|
+
image: string;
|
|
6
|
+
acceleration: 'hardware' | 'software';
|
|
7
|
+
artifactsDirectory: string;
|
|
8
|
+
temporaryDirectory?: string;
|
|
9
|
+
port?: number;
|
|
10
|
+
acceptLicenses?: boolean;
|
|
11
|
+
/** Defaults to 10 minutes; hardware is capped there, software cold provisioning at 20 minutes. */
|
|
12
|
+
bootTimeoutMs?: number;
|
|
13
|
+
env?: Record<string, string | undefined>;
|
|
14
|
+
}
|
|
15
|
+
export interface AndroidEmulatorSession {
|
|
16
|
+
serial: string;
|
|
17
|
+
adb: string;
|
|
18
|
+
env: Record<string, string | undefined>;
|
|
19
|
+
/** Stops only this session's process and removes only its disposable AVD. */
|
|
20
|
+
dispose: () => Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** Provision and own a real Android emulator on a macOS or Linux SDK host. */
|
|
23
|
+
export declare function createAndroidEmulator(options: AndroidEmulatorOptions): Promise<AndroidEmulatorSession>;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Craft Android Builder
|
|
3
3
|
*
|
|
4
|
-
* Generates
|
|
4
|
+
* Generates Android apps with native Craft components and optional WebView content.
|
|
5
5
|
*/
|
|
6
6
|
export { runKotlinFixture } from './testing.js';
|
|
7
|
+
export { createAndroidEmulator } from './emulator.js';
|
|
8
|
+
export type { AndroidEmulatorOptions, AndroidEmulatorSession } from './emulator.js';
|
|
7
9
|
/** Package custom fonts and their licenses; removed fonts cannot linger in the app. */
|
|
8
10
|
export declare function syncNativeFonts(fonts: CraftAndroidConfig['nativeFonts'], output: string): string[];
|
|
9
11
|
/** Oldest Android API level supported by the generated Kotlin runtime. */
|
|
@@ -88,6 +90,10 @@ export interface CraftAndroidConfig {
|
|
|
88
90
|
id: string;
|
|
89
91
|
title: string;
|
|
90
92
|
symbol?: string;
|
|
93
|
+
/** Native selected-tab icon overrides, also supported by navigation.setOptions({ tabItem }). */
|
|
94
|
+
selectedSymbol?: string;
|
|
95
|
+
selectedIconTint?: string;
|
|
96
|
+
selectedIconPulse?: boolean;
|
|
91
97
|
}>;
|
|
92
98
|
nativeApp?: string;
|
|
93
99
|
/** Wake the app script every so often (`craftBackgroundRefresh`), through WorkManager. */
|