@open-mova/core 0.1.9 → 0.2.2

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 CHANGED
@@ -8,8 +8,9 @@
8
8
  contratos, tipos y utilidades transversales que puedan utilizar la shell y los
9
9
  microfrontales.
10
10
 
11
- Actualmente define el contrato `NativeCapabilities` v1 para Device y Camera,
12
- el token de DI Angular y `injectNativeCapabilities()`. No depende de Capacitor.
11
+ Define el contrato `NativeCapabilities` v1, el token de DI Angular y
12
+ `injectNativeCapabilities()`. No depende de Capacitor: los plugins reales solo
13
+ se instalan y se ejecutan dentro de la shell.
13
14
 
14
15
  ## Instalación
15
16
 
@@ -56,21 +57,35 @@ npm run build
56
57
  El paquete se identifica como `@open-mova/core`. Cuando se añada una pieza
57
58
  pública, debe exportarse desde `src/index.ts`.
58
59
 
59
- La shell proporciona el token `NATIVE_CAPABILITIES` y el MF accede a él por DI:
60
-
61
- ```ts
62
- import { injectNativeCapabilities } from '@open-mova/core';
63
-
64
- const native = injectNativeCapabilities(); // Dentro de un contexto de inyección Angular.
65
- const device = await native.device.getInfo();
66
- const photo = await native.camera.takePhoto();
67
- const selected = await native.camera.choosePhoto();
68
- ```
69
-
70
- `photo.webPath` sirve para mostrar la imagen; `photo.uri` puede existir en
71
- móvil. `choosePhoto()` devuelve `undefined` si la galería devuelve una lista
72
- vacía; cancelar el diálogo puede rechazar la promesa según la plataforma.
73
- Angular muestra un error de provider ausente si la shell no ofrece el contrato.
74
- Los MF que usan capacidades nativas dependen de `@open-mova/core`; en el
75
- monorepo se instala por ruta local tras compilar la librería. Shell y MF deben
76
- compartir una sola instancia de core mediante Native Federation.
60
+ ## Capacidades nativas
61
+
62
+ Cada plugin oficial se representa como una capacidad con tres operaciones
63
+ comunes:
64
+
65
+ - `isAvailable()` comprueba si el plugin está disponible en la plataforma.
66
+ - `invoke(nombre, opciones)` ejecuta una operación del plugin.
67
+ - `subscribe(evento, listener, contexto?)` registra un evento y devuelve un handle con
68
+ `remove()` para cancelarlo.
69
+
70
+ `NATIVE_CAPABILITY_API` contiene la lista completa y versionada de operaciones
71
+ y eventos soportados. El microfrontal de demostración la reutiliza para que su
72
+ referencia interactiva no pueda quedarse desactualizada respecto al contrato.
73
+ El tercer argumento de `subscribe()` solo es necesario en capacidades con
74
+ instancias, como Google Maps, donde se pasa `{ id: 'mapa-principal' }`.
75
+
76
+ El contrato expone una capacidad por cada plugin oficial soportado:
77
+ `actionSheet`, `app`, `appLauncher`, `backgroundRunner`,
78
+ `barcodeScanner`, `browser`, `calendar`, `camera`, `clipboard`, `contacts`,
79
+ `cookies`, `device`, `dialog`, `fileTransfer`, `fileViewer`, `filesystem`,
80
+ `geolocation`, `googleMaps`, `haptics`, `healthFitness`, `http`,
81
+ `inAppBrowser`, `keyboard`, `localLlm`, `localNotifications`, `motion`,
82
+ `network`, `preferences`, `privacyScreen`, `pushNotifications`,
83
+ `screenOrientation`, `screenReader`, `share`, `splashScreen`, `statusBar`,
84
+ `systemBars`, `textZoom` y `toast`. La lista completa de métodos y eventos de
85
+ cada capacidad se encuentra en `NATIVE_CAPABILITY_API`.
86
+
87
+ Las opciones y el resultado no exponen tipos de Capacitor. Esto evita que el MF
88
+ se acople a su versión; algunas operaciones avanzadas pueden requerir valores
89
+ propios de plataforma, como `Date` o `Blob`. Las operaciones más estables y
90
+ habituales conservan métodos explícitos: `device.getInfo()`,
91
+ `camera.takePhoto()` y `camera.choosePhoto()`.
@@ -0,0 +1,23 @@
1
+ /** Versión del paquete que implementa este contrato en tiempo de ejecución. */
2
+ export declare const OPEN_MOVA_CORE_VERSION = "0.2.1";
3
+ /** Versión del formato del manifiesto publicado por cada microfrontal. */
4
+ export declare const MICROFRONTEND_MANIFEST_SCHEMA_VERSION = 1;
5
+ export interface OpenMovaMicrofrontendManifest {
6
+ readonly schemaVersion: typeof MICROFRONTEND_MANIFEST_SCHEMA_VERSION;
7
+ readonly name: string;
8
+ readonly remoteName: string;
9
+ readonly core: {
10
+ readonly requiredVersion: string;
11
+ };
12
+ }
13
+ export interface CompatibilityResult {
14
+ readonly compatible: boolean;
15
+ readonly reason?: string;
16
+ }
17
+ /**
18
+ * Comprueba los rangos que genera Open Mova: versión exacta, caret y tilde.
19
+ * Mantener el formato acotado permite usarlo también en el navegador sin
20
+ * incorporar un segundo motor completo de semver al runtime compartido.
21
+ */
22
+ export declare function checkCoreCompatibility(requiredVersion: string, availableVersion?: string): CompatibilityResult;
23
+ export declare function parseMicrofrontendManifest(value: unknown): OpenMovaMicrofrontendManifest;
@@ -0,0 +1,94 @@
1
+ /** Versión del paquete que implementa este contrato en tiempo de ejecución. */
2
+ export const OPEN_MOVA_CORE_VERSION = '0.2.1';
3
+ /** Versión del formato del manifiesto publicado por cada microfrontal. */
4
+ export const MICROFRONTEND_MANIFEST_SCHEMA_VERSION = 1;
5
+ /**
6
+ * Comprueba los rangos que genera Open Mova: versión exacta, caret y tilde.
7
+ * Mantener el formato acotado permite usarlo también en el navegador sin
8
+ * incorporar un segundo motor completo de semver al runtime compartido.
9
+ */
10
+ export function checkCoreCompatibility(requiredVersion, availableVersion = OPEN_MOVA_CORE_VERSION) {
11
+ const range = parseSupportedRange(requiredVersion);
12
+ const available = parseVersion(availableVersion);
13
+ if (!range || !available) {
14
+ return {
15
+ compatible: false,
16
+ reason: `No se puede interpretar el rango ${requiredVersion} o la versión ${availableVersion}.`,
17
+ };
18
+ }
19
+ const minimumComparison = compareVersions(available, range.minimum);
20
+ const compatible = minimumComparison >= 0 && isBelowUpperBound(available, range);
21
+ return compatible
22
+ ? { compatible: true }
23
+ : {
24
+ compatible: false,
25
+ reason: `Requiere @open-mova/core ${requiredVersion}, pero la shell proporciona ${availableVersion}.`,
26
+ };
27
+ }
28
+ export function parseMicrofrontendManifest(value) {
29
+ if (!isRecord(value) || value.schemaVersion !== MICROFRONTEND_MANIFEST_SCHEMA_VERSION) {
30
+ throw new Error('El manifiesto del microfrontal tiene una versión no compatible.');
31
+ }
32
+ if (typeof value.name !== 'string' ||
33
+ typeof value.remoteName !== 'string' ||
34
+ !isRecord(value.core) ||
35
+ typeof value.core.requiredVersion !== 'string') {
36
+ throw new Error('El manifiesto del microfrontal está incompleto.');
37
+ }
38
+ return {
39
+ schemaVersion: MICROFRONTEND_MANIFEST_SCHEMA_VERSION,
40
+ name: value.name,
41
+ remoteName: value.remoteName,
42
+ core: { requiredVersion: value.core.requiredVersion },
43
+ };
44
+ }
45
+ function parseSupportedRange(value) {
46
+ if (value.trim() === '*') {
47
+ return {
48
+ operator: 'caret',
49
+ minimum: { major: 0, minor: 0, patch: 0 },
50
+ };
51
+ }
52
+ const match = value.trim().match(/^(\^|~)?(\d+)\.(\d+)\.(\d+)$/);
53
+ if (!match)
54
+ return undefined;
55
+ return {
56
+ operator: match[1] === '^' ? 'caret' : match[1] === '~' ? 'tilde' : 'exact',
57
+ minimum: {
58
+ major: Number(match[2]),
59
+ minor: Number(match[3]),
60
+ patch: Number(match[4]),
61
+ },
62
+ };
63
+ }
64
+ function parseVersion(value) {
65
+ const match = value.trim().match(/^v?(\d+)\.(\d+)\.(\d+)$/);
66
+ return match
67
+ ? { major: Number(match[1]), minor: Number(match[2]), patch: Number(match[3]) }
68
+ : undefined;
69
+ }
70
+ function isBelowUpperBound(version, range) {
71
+ if (range.operator === 'caret' &&
72
+ range.minimum.major === 0 &&
73
+ range.minimum.minor === 0 &&
74
+ range.minimum.patch === 0) {
75
+ return true;
76
+ }
77
+ if (range.operator === 'exact')
78
+ return compareVersions(version, range.minimum) === 0;
79
+ if (range.operator === 'tilde') {
80
+ return version.major === range.minimum.major && version.minor === range.minimum.minor;
81
+ }
82
+ if (range.minimum.major > 0)
83
+ return version.major === range.minimum.major;
84
+ if (range.minimum.minor > 0) {
85
+ return version.major === 0 && version.minor === range.minimum.minor;
86
+ }
87
+ return compareVersions(version, range.minimum) === 0;
88
+ }
89
+ function compareVersions(first, second) {
90
+ return first.major - second.major || first.minor - second.minor || first.patch - second.patch;
91
+ }
92
+ function isRecord(value) {
93
+ return typeof value === 'object' && value !== null;
94
+ }
package/dist/index.d.ts CHANGED
@@ -1,2 +1,4 @@
1
- export type { CameraCapability, DeviceCapability, DeviceDetails, NativeCapabilities, PhotoResult, } from './native.js';
2
- export { NATIVE_CAPABILITIES, injectNativeCapabilities } from './native.js';
1
+ export { checkCoreCompatibility, MICROFRONTEND_MANIFEST_SCHEMA_VERSION, OPEN_MOVA_CORE_VERSION, parseMicrofrontendManifest, } from './compatibility.js';
2
+ export type { CompatibilityResult, OpenMovaMicrofrontendManifest } from './compatibility.js';
3
+ export type { ActionSheetCapability, AppCapability, AppLauncherCapability, BackgroundRunnerCapability, BarcodeScannerCapability, BrowserCapability, CameraCapability, CalendarCapability, ClipboardCapability, ContactsCapability, CookiesCapability, DeviceCapability, DeviceDetails, DialogCapability, FileTransferCapability, FileViewerCapability, FilesystemCapability, GeolocationCapability, GoogleMapsCapability, HapticsCapability, HealthFitnessCapability, HttpCapability, InAppBrowserCapability, KeyboardCapability, LocalLlmCapability, LocalNotificationsCapability, MotionCapability, NativeCapabilities, NativeCapabilityName, NativeEvent, NativeOptions, NativeOperation, NativePluginCapability, NativeSubscription, NetworkCapability, PhotoResult, PreferencesCapability, PrivacyScreenCapability, PushNotificationsCapability, ScreenOrientationCapability, ScreenReaderCapability, ShareCapability, SplashScreenCapability, StatusBarCapability, SystemBarsCapability, TextZoomCapability, ToastCapability, } from './native.js';
4
+ export { NATIVE_CAPABILITIES, NATIVE_CAPABILITY_API, injectNativeCapabilities } from './native.js';
package/dist/index.js CHANGED
@@ -1 +1,2 @@
1
- export { NATIVE_CAPABILITIES, injectNativeCapabilities } from './native.js';
1
+ export { checkCoreCompatibility, MICROFRONTEND_MANIFEST_SCHEMA_VERSION, OPEN_MOVA_CORE_VERSION, parseMicrofrontendManifest, } from './compatibility.js';
2
+ export { NATIVE_CAPABILITIES, NATIVE_CAPABILITY_API, injectNativeCapabilities } from './native.js';
package/dist/native.d.ts CHANGED
@@ -1,24 +1,312 @@
1
1
  import { InjectionToken } from '@angular/core';
2
+ /**
3
+ * Superficie oficial que Open Mova expone para cada plugin de Capacitor.
4
+ * La demo consume también este catálogo para no mantener una segunda lista.
5
+ */
6
+ export declare const NATIVE_CAPABILITY_API: {
7
+ readonly actionSheet: {
8
+ readonly operations: readonly ["showActions"];
9
+ readonly events: readonly [];
10
+ };
11
+ readonly app: {
12
+ readonly operations: readonly ["exitApp", "getInfo", "getState", "getLaunchUrl", "minimizeApp", "getAppLanguage", "toggleBackButtonHandler", "removeAllListeners"];
13
+ readonly events: readonly ["appStateChange", "pause", "resume", "appUrlOpen", "appRestoredResult", "backButton"];
14
+ };
15
+ readonly appLauncher: {
16
+ readonly operations: readonly ["canOpenUrl", "openUrl"];
17
+ readonly events: readonly [];
18
+ };
19
+ readonly backgroundRunner: {
20
+ readonly operations: readonly ["checkPermissions", "requestPermissions", "dispatchEvent", "removeNotificationListeners"];
21
+ readonly events: readonly ["backgroundRunnerNotificationReceived"];
22
+ };
23
+ readonly barcodeScanner: {
24
+ readonly operations: readonly ["scanBarcode"];
25
+ readonly events: readonly [];
26
+ };
27
+ readonly browser: {
28
+ readonly operations: readonly ["open", "close", "removeAllListeners"];
29
+ readonly events: readonly ["browserFinished", "browserPageLoaded"];
30
+ };
31
+ readonly calendar: {
32
+ readonly operations: readonly ["checkPermissions", "requestPermissions", "createEvent", "createEventInteractively", "modifyEvent", "findEvents", "deleteEvent", "listCalendars", "createCalendar", "deleteCalendar", "openCalendar"];
33
+ readonly events: readonly [];
34
+ };
35
+ readonly camera: {
36
+ readonly operations: readonly ["takePhoto", "recordVideo", "playVideo", "chooseFromGallery", "editPhoto", "editURIPhoto", "pickLimitedLibraryPhotos", "getLimitedLibraryPhotos", "checkPermissions", "requestPermissions", "getPhoto", "pickImages"];
37
+ readonly events: readonly [];
38
+ };
39
+ readonly clipboard: {
40
+ readonly operations: readonly ["write", "read"];
41
+ readonly events: readonly [];
42
+ };
43
+ readonly contacts: {
44
+ readonly operations: readonly ["find", "save", "remove", "pickContact"];
45
+ readonly events: readonly [];
46
+ };
47
+ readonly cookies: {
48
+ readonly operations: readonly ["getCookies", "setCookie", "deleteCookie", "clearCookies", "clearAllCookies"];
49
+ readonly events: readonly [];
50
+ };
51
+ readonly device: {
52
+ readonly operations: readonly ["getId", "getInfo", "getBatteryInfo", "getLanguageCode", "getLanguageTag"];
53
+ readonly events: readonly [];
54
+ };
55
+ readonly dialog: {
56
+ readonly operations: readonly ["alert", "prompt", "confirm"];
57
+ readonly events: readonly [];
58
+ };
59
+ readonly fileTransfer: {
60
+ readonly operations: readonly ["downloadFile", "uploadFile", "removeAllListeners"];
61
+ readonly events: readonly ["progress"];
62
+ };
63
+ readonly fileViewer: {
64
+ readonly operations: readonly ["openDocumentFromLocalPath", "openDocumentFromResources", "openDocumentFromUrl", "previewMediaContentFromLocalPath", "previewMediaContentFromResources", "previewMediaContentFromUrl"];
65
+ readonly events: readonly [];
66
+ };
67
+ readonly filesystem: {
68
+ readonly operations: readonly ["checkPermissions", "requestPermissions", "readFile", "readFileInChunks", "writeFile", "appendFile", "deleteFile", "mkdir", "rmdir", "readdir", "getUri", "stat", "rename", "copy", "downloadFile", "removeAllListeners"];
69
+ readonly events: readonly ["progress"];
70
+ };
71
+ readonly geolocation: {
72
+ readonly operations: readonly ["getCurrentPosition", "watchPosition", "clearWatch", "checkPermissions", "requestPermissions"];
73
+ readonly events: readonly [];
74
+ };
75
+ readonly googleMaps: {
76
+ readonly operations: readonly ["create", "enableTouch", "disableTouch", "enableClustering", "disableClustering", "addTileOverlay", "removeTileOverlay", "addMarker", "addMarkers", "removeMarker", "removeMarkers", "addPolygons", "removePolygons", "addCircles", "removeCircles", "addPolylines", "removePolylines", "destroy", "setCamera", "getMapType", "setMapType", "enableIndoorMaps", "enableTrafficLayer", "enableAccessibilityElements", "enableCurrentLocation", "setPadding", "getMapBounds", "fitBounds", "removeAllMapListeners"];
77
+ readonly events: readonly ["boundsChanged", "cameraIdle", "cameraMoveStarted", "clusterClick", "clusterInfoWindowClick", "infoWindowClick", "mapClick", "markerClick", "polygonClick", "circleClick", "polylineClick", "markerDragStart", "markerDrag", "markerDragEnd", "myLocationButtonClick", "myLocationClick"];
78
+ };
79
+ readonly haptics: {
80
+ readonly operations: readonly ["impact", "notification", "vibrate", "selectionStart", "selectionChanged", "selectionEnd"];
81
+ readonly events: readonly [];
82
+ };
83
+ readonly healthFitness: {
84
+ readonly operations: readonly ["requestHealthPermissions", "getData", "getWorkoutData", "writeData", "getLastRecord", "setBackgroundJob", "deleteBackgroundJob", "listBackgroundJobs", "updateBackgroundJob", "disconnectFromHealthConnect", "openHealthConnect"];
85
+ readonly events: readonly [];
86
+ };
87
+ readonly http: {
88
+ readonly operations: readonly ["request", "get", "post", "put", "patch", "delete"];
89
+ readonly events: readonly [];
90
+ };
91
+ readonly inAppBrowser: {
92
+ readonly operations: readonly ["openInWebView", "openInSystemBrowser", "openInExternalBrowser", "close", "removeAllListeners"];
93
+ readonly events: readonly ["browserPageLoaded", "browserPageNavigationCompleted", "browserClosed"];
94
+ };
95
+ readonly keyboard: {
96
+ readonly operations: readonly ["show", "hide", "setAccessoryBarVisible", "setScroll", "setStyle", "setResizeMode", "getResizeMode", "removeAllListeners"];
97
+ readonly events: readonly ["keyboardWillShow", "keyboardDidShow", "keyboardWillHide", "keyboardDidHide"];
98
+ };
99
+ readonly localLlm: {
100
+ readonly operations: readonly ["systemAvailability", "download", "prompt", "endSession", "generateImage", "warmup", "removeAllListeners"];
101
+ readonly events: readonly ["systemAvailabilityChange"];
102
+ };
103
+ readonly localNotifications: {
104
+ readonly operations: readonly ["schedule", "update", "getPending", "registerActionTypes", "cancel", "cancelAll", "areEnabled", "getDeliveredNotifications", "removeDeliveredNotifications", "removeDeliveredNotificationsById", "removeAllDeliveredNotifications", "getByIds", "getAll", "createChannel", "deleteChannel", "listChannels", "checkPermissions", "requestPermissions", "changeExactNotificationSetting", "checkExactNotificationSetting", "removeAllListeners"];
105
+ readonly events: readonly ["localNotificationReceived", "localNotificationActionPerformed"];
106
+ };
107
+ readonly motion: {
108
+ readonly operations: readonly ["removeAllListeners"];
109
+ readonly events: readonly ["accel", "orientation"];
110
+ };
111
+ readonly network: {
112
+ readonly operations: readonly ["getStatus", "removeAllListeners"];
113
+ readonly events: readonly ["networkStatusChange"];
114
+ };
115
+ readonly preferences: {
116
+ readonly operations: readonly ["configure", "get", "set", "remove", "clear", "keys", "migrate", "removeOld"];
117
+ readonly events: readonly [];
118
+ };
119
+ readonly privacyScreen: {
120
+ readonly operations: readonly ["enable", "disable", "isEnabled"];
121
+ readonly events: readonly [];
122
+ };
123
+ readonly pushNotifications: {
124
+ readonly operations: readonly ["register", "unregister", "getDeliveredNotifications", "removeDeliveredNotifications", "removeAllDeliveredNotifications", "createChannel", "deleteChannel", "listChannels", "checkPermissions", "requestPermissions", "removeAllListeners"];
125
+ readonly events: readonly ["registration", "registrationError", "pushNotificationReceived", "pushNotificationActionPerformed"];
126
+ };
127
+ readonly screenOrientation: {
128
+ readonly operations: readonly ["orientation", "lock", "unlock", "removeAllListeners"];
129
+ readonly events: readonly ["screenOrientationChange"];
130
+ };
131
+ readonly screenReader: {
132
+ readonly operations: readonly ["isEnabled", "speak", "removeAllListeners"];
133
+ readonly events: readonly ["stateChange"];
134
+ };
135
+ readonly share: {
136
+ readonly operations: readonly ["canShare", "share"];
137
+ readonly events: readonly [];
138
+ };
139
+ readonly splashScreen: {
140
+ readonly operations: readonly ["show", "hide"];
141
+ readonly events: readonly [];
142
+ };
143
+ readonly statusBar: {
144
+ readonly operations: readonly ["setStyle", "setBackgroundColor", "show", "hide", "getInfo", "setOverlaysWebView"];
145
+ readonly events: readonly ["statusBarVisibilityChanged", "statusBarOverlayChanged"];
146
+ };
147
+ readonly systemBars: {
148
+ readonly operations: readonly ["setStyle", "show", "hide", "setAnimation"];
149
+ readonly events: readonly [];
150
+ };
151
+ readonly textZoom: {
152
+ readonly operations: readonly ["get", "getPreferred", "set"];
153
+ readonly events: readonly [];
154
+ };
155
+ readonly toast: {
156
+ readonly operations: readonly ["show"];
157
+ readonly events: readonly [];
158
+ };
159
+ };
160
+ export type NativeCapabilityName = keyof typeof NATIVE_CAPABILITY_API;
161
+ export type NativeOperation<TName extends NativeCapabilityName> = (typeof NATIVE_CAPABILITY_API)[TName]['operations'][number];
162
+ export type NativeEvent<TName extends NativeCapabilityName> = (typeof NATIVE_CAPABILITY_API)[TName]['events'][number];
163
+ /** Options passed across the shell boundary, including non-JSON native values. */
164
+ export type NativeOptions = Readonly<Record<string, unknown>>;
165
+ export interface NativeSubscription {
166
+ remove(): Promise<void>;
167
+ }
168
+ /** Capacitor stays private to the shell behind this stable public contract. */
169
+ export interface NativePluginCapability<TOperation extends string = string, TEvent extends string = never> {
170
+ isAvailable(): boolean;
171
+ invoke<TResult = unknown>(operation: TOperation, options?: NativeOptions): Promise<TResult>;
172
+ subscribe(event: TEvent, listener: (payload: unknown) => void, options?: NativeOptions): Promise<NativeSubscription>;
173
+ }
174
+ type Capability<TName extends NativeCapabilityName> = NativePluginCapability<NativeOperation<TName>, NativeEvent<TName>>;
2
175
  export interface DeviceDetails {
3
176
  readonly model: string;
4
177
  readonly platform: 'ios' | 'android' | 'web';
5
178
  readonly osVersion: string;
6
179
  }
7
- export interface DeviceCapability {
180
+ export interface DeviceCapability extends Capability<'device'> {
8
181
  getInfo(): Promise<DeviceDetails>;
9
182
  }
10
183
  export interface PhotoResult {
11
184
  readonly webPath?: string;
12
185
  readonly uri?: string;
13
186
  }
14
- export interface CameraCapability {
187
+ export interface CameraCapability extends Capability<'camera'> {
15
188
  takePhoto(): Promise<PhotoResult>;
16
189
  choosePhoto(): Promise<PhotoResult | undefined>;
17
190
  }
191
+ export interface ActionSheetCapability extends Capability<'actionSheet'> {
192
+ }
193
+ export interface AppCapability extends Capability<'app'> {
194
+ }
195
+ export interface AppLauncherCapability extends Capability<'appLauncher'> {
196
+ }
197
+ export interface BackgroundRunnerCapability extends Capability<'backgroundRunner'> {
198
+ }
199
+ export interface BarcodeScannerCapability extends Capability<'barcodeScanner'> {
200
+ }
201
+ export interface BrowserCapability extends Capability<'browser'> {
202
+ }
203
+ export interface CalendarCapability extends Capability<'calendar'> {
204
+ }
205
+ export interface ClipboardCapability extends Capability<'clipboard'> {
206
+ }
207
+ export interface ContactsCapability extends Capability<'contacts'> {
208
+ }
209
+ /** Cookies is bundled in @capacitor/core. */
210
+ export interface CookiesCapability extends Capability<'cookies'> {
211
+ }
212
+ export interface DialogCapability extends Capability<'dialog'> {
213
+ }
214
+ export interface FileTransferCapability extends Capability<'fileTransfer'> {
215
+ }
216
+ export interface FileViewerCapability extends Capability<'fileViewer'> {
217
+ }
218
+ export interface FilesystemCapability extends Capability<'filesystem'> {
219
+ }
220
+ export interface GeolocationCapability extends Capability<'geolocation'> {
221
+ }
222
+ /** Google Maps keeps stateful map instances inside the shell. */
223
+ export interface GoogleMapsCapability extends Capability<'googleMaps'> {
224
+ }
225
+ export interface HapticsCapability extends Capability<'haptics'> {
226
+ }
227
+ export interface HealthFitnessCapability extends Capability<'healthFitness'> {
228
+ }
229
+ /** HTTP is bundled in @capacitor/core. */
230
+ export interface HttpCapability extends Capability<'http'> {
231
+ }
232
+ export interface InAppBrowserCapability extends Capability<'inAppBrowser'> {
233
+ }
234
+ export interface KeyboardCapability extends Capability<'keyboard'> {
235
+ }
236
+ /** Experimental Capacitor plugin. Always call isAvailable before invoking it. */
237
+ export interface LocalLlmCapability extends Capability<'localLlm'> {
238
+ }
239
+ export interface LocalNotificationsCapability extends Capability<'localNotifications'> {
240
+ }
241
+ export interface MotionCapability extends Capability<'motion'> {
242
+ }
243
+ export interface NetworkCapability extends Capability<'network'> {
244
+ }
245
+ export interface PreferencesCapability extends Capability<'preferences'> {
246
+ }
247
+ export interface PrivacyScreenCapability extends Capability<'privacyScreen'> {
248
+ }
249
+ export interface PushNotificationsCapability extends Capability<'pushNotifications'> {
250
+ }
251
+ export interface ScreenOrientationCapability extends Capability<'screenOrientation'> {
252
+ }
253
+ export interface ScreenReaderCapability extends Capability<'screenReader'> {
254
+ }
255
+ export interface ShareCapability extends Capability<'share'> {
256
+ }
257
+ export interface SplashScreenCapability extends Capability<'splashScreen'> {
258
+ }
259
+ export interface StatusBarCapability extends Capability<'statusBar'> {
260
+ }
261
+ /** System Bars is bundled in @capacitor/core and supersedes Status Bar for edge-to-edge layouts. */
262
+ export interface SystemBarsCapability extends Capability<'systemBars'> {
263
+ }
264
+ export interface TextZoomCapability extends Capability<'textZoom'> {
265
+ }
266
+ export interface ToastCapability extends Capability<'toast'> {
267
+ }
18
268
  export interface NativeCapabilities {
269
+ /** Version 1 remains compatible with the original Device and Camera contract. */
19
270
  readonly version: 1;
20
- readonly device: DeviceCapability;
271
+ readonly actionSheet: ActionSheetCapability;
272
+ readonly app: AppCapability;
273
+ readonly appLauncher: AppLauncherCapability;
274
+ readonly backgroundRunner: BackgroundRunnerCapability;
275
+ readonly barcodeScanner: BarcodeScannerCapability;
276
+ readonly browser: BrowserCapability;
277
+ readonly calendar: CalendarCapability;
21
278
  readonly camera: CameraCapability;
279
+ readonly clipboard: ClipboardCapability;
280
+ readonly contacts: ContactsCapability;
281
+ readonly cookies: CookiesCapability;
282
+ readonly device: DeviceCapability;
283
+ readonly dialog: DialogCapability;
284
+ readonly fileTransfer: FileTransferCapability;
285
+ readonly fileViewer: FileViewerCapability;
286
+ readonly filesystem: FilesystemCapability;
287
+ readonly geolocation: GeolocationCapability;
288
+ readonly googleMaps: GoogleMapsCapability;
289
+ readonly haptics: HapticsCapability;
290
+ readonly healthFitness: HealthFitnessCapability;
291
+ readonly http: HttpCapability;
292
+ readonly inAppBrowser: InAppBrowserCapability;
293
+ readonly keyboard: KeyboardCapability;
294
+ readonly localLlm: LocalLlmCapability;
295
+ readonly localNotifications: LocalNotificationsCapability;
296
+ readonly motion: MotionCapability;
297
+ readonly network: NetworkCapability;
298
+ readonly preferences: PreferencesCapability;
299
+ readonly privacyScreen: PrivacyScreenCapability;
300
+ readonly pushNotifications: PushNotificationsCapability;
301
+ readonly screenOrientation: ScreenOrientationCapability;
302
+ readonly screenReader: ScreenReaderCapability;
303
+ readonly share: ShareCapability;
304
+ readonly splashScreen: SplashScreenCapability;
305
+ readonly statusBar: StatusBarCapability;
306
+ readonly systemBars: SystemBarsCapability;
307
+ readonly textZoom: TextZoomCapability;
308
+ readonly toast: ToastCapability;
22
309
  }
23
310
  export declare const NATIVE_CAPABILITIES: InjectionToken<NativeCapabilities>;
24
311
  export declare function injectNativeCapabilities(): NativeCapabilities;
312
+ export {};
package/dist/native.js CHANGED
@@ -1,4 +1,314 @@
1
1
  import { InjectionToken, inject } from '@angular/core';
2
+ /**
3
+ * Superficie oficial que Open Mova expone para cada plugin de Capacitor.
4
+ * La demo consume también este catálogo para no mantener una segunda lista.
5
+ */
6
+ export const NATIVE_CAPABILITY_API = {
7
+ actionSheet: { operations: ['showActions'], events: [] },
8
+ app: {
9
+ operations: [
10
+ 'exitApp',
11
+ 'getInfo',
12
+ 'getState',
13
+ 'getLaunchUrl',
14
+ 'minimizeApp',
15
+ 'getAppLanguage',
16
+ 'toggleBackButtonHandler',
17
+ 'removeAllListeners',
18
+ ],
19
+ events: ['appStateChange', 'pause', 'resume', 'appUrlOpen', 'appRestoredResult', 'backButton'],
20
+ },
21
+ appLauncher: { operations: ['canOpenUrl', 'openUrl'], events: [] },
22
+ backgroundRunner: {
23
+ operations: [
24
+ 'checkPermissions',
25
+ 'requestPermissions',
26
+ 'dispatchEvent',
27
+ 'removeNotificationListeners',
28
+ ],
29
+ events: ['backgroundRunnerNotificationReceived'],
30
+ },
31
+ barcodeScanner: { operations: ['scanBarcode'], events: [] },
32
+ browser: {
33
+ operations: ['open', 'close', 'removeAllListeners'],
34
+ events: ['browserFinished', 'browserPageLoaded'],
35
+ },
36
+ calendar: {
37
+ operations: [
38
+ 'checkPermissions',
39
+ 'requestPermissions',
40
+ 'createEvent',
41
+ 'createEventInteractively',
42
+ 'modifyEvent',
43
+ 'findEvents',
44
+ 'deleteEvent',
45
+ 'listCalendars',
46
+ 'createCalendar',
47
+ 'deleteCalendar',
48
+ 'openCalendar',
49
+ ],
50
+ events: [],
51
+ },
52
+ camera: {
53
+ operations: [
54
+ 'takePhoto',
55
+ 'recordVideo',
56
+ 'playVideo',
57
+ 'chooseFromGallery',
58
+ 'editPhoto',
59
+ 'editURIPhoto',
60
+ 'pickLimitedLibraryPhotos',
61
+ 'getLimitedLibraryPhotos',
62
+ 'checkPermissions',
63
+ 'requestPermissions',
64
+ 'getPhoto',
65
+ 'pickImages',
66
+ ],
67
+ events: [],
68
+ },
69
+ clipboard: { operations: ['write', 'read'], events: [] },
70
+ contacts: { operations: ['find', 'save', 'remove', 'pickContact'], events: [] },
71
+ cookies: {
72
+ operations: ['getCookies', 'setCookie', 'deleteCookie', 'clearCookies', 'clearAllCookies'],
73
+ events: [],
74
+ },
75
+ device: {
76
+ operations: ['getId', 'getInfo', 'getBatteryInfo', 'getLanguageCode', 'getLanguageTag'],
77
+ events: [],
78
+ },
79
+ dialog: { operations: ['alert', 'prompt', 'confirm'], events: [] },
80
+ fileTransfer: {
81
+ operations: ['downloadFile', 'uploadFile', 'removeAllListeners'],
82
+ events: ['progress'],
83
+ },
84
+ fileViewer: {
85
+ operations: [
86
+ 'openDocumentFromLocalPath',
87
+ 'openDocumentFromResources',
88
+ 'openDocumentFromUrl',
89
+ 'previewMediaContentFromLocalPath',
90
+ 'previewMediaContentFromResources',
91
+ 'previewMediaContentFromUrl',
92
+ ],
93
+ events: [],
94
+ },
95
+ filesystem: {
96
+ operations: [
97
+ 'checkPermissions',
98
+ 'requestPermissions',
99
+ 'readFile',
100
+ 'readFileInChunks',
101
+ 'writeFile',
102
+ 'appendFile',
103
+ 'deleteFile',
104
+ 'mkdir',
105
+ 'rmdir',
106
+ 'readdir',
107
+ 'getUri',
108
+ 'stat',
109
+ 'rename',
110
+ 'copy',
111
+ 'downloadFile',
112
+ 'removeAllListeners',
113
+ ],
114
+ events: ['progress'],
115
+ },
116
+ geolocation: {
117
+ operations: [
118
+ 'getCurrentPosition',
119
+ 'watchPosition',
120
+ 'clearWatch',
121
+ 'checkPermissions',
122
+ 'requestPermissions',
123
+ ],
124
+ events: [],
125
+ },
126
+ googleMaps: {
127
+ operations: [
128
+ 'create',
129
+ 'enableTouch',
130
+ 'disableTouch',
131
+ 'enableClustering',
132
+ 'disableClustering',
133
+ 'addTileOverlay',
134
+ 'removeTileOverlay',
135
+ 'addMarker',
136
+ 'addMarkers',
137
+ 'removeMarker',
138
+ 'removeMarkers',
139
+ 'addPolygons',
140
+ 'removePolygons',
141
+ 'addCircles',
142
+ 'removeCircles',
143
+ 'addPolylines',
144
+ 'removePolylines',
145
+ 'destroy',
146
+ 'setCamera',
147
+ 'getMapType',
148
+ 'setMapType',
149
+ 'enableIndoorMaps',
150
+ 'enableTrafficLayer',
151
+ 'enableAccessibilityElements',
152
+ 'enableCurrentLocation',
153
+ 'setPadding',
154
+ 'getMapBounds',
155
+ 'fitBounds',
156
+ 'removeAllMapListeners',
157
+ ],
158
+ events: [
159
+ 'boundsChanged',
160
+ 'cameraIdle',
161
+ 'cameraMoveStarted',
162
+ 'clusterClick',
163
+ 'clusterInfoWindowClick',
164
+ 'infoWindowClick',
165
+ 'mapClick',
166
+ 'markerClick',
167
+ 'polygonClick',
168
+ 'circleClick',
169
+ 'polylineClick',
170
+ 'markerDragStart',
171
+ 'markerDrag',
172
+ 'markerDragEnd',
173
+ 'myLocationButtonClick',
174
+ 'myLocationClick',
175
+ ],
176
+ },
177
+ haptics: {
178
+ operations: [
179
+ 'impact',
180
+ 'notification',
181
+ 'vibrate',
182
+ 'selectionStart',
183
+ 'selectionChanged',
184
+ 'selectionEnd',
185
+ ],
186
+ events: [],
187
+ },
188
+ healthFitness: {
189
+ operations: [
190
+ 'requestHealthPermissions',
191
+ 'getData',
192
+ 'getWorkoutData',
193
+ 'writeData',
194
+ 'getLastRecord',
195
+ 'setBackgroundJob',
196
+ 'deleteBackgroundJob',
197
+ 'listBackgroundJobs',
198
+ 'updateBackgroundJob',
199
+ 'disconnectFromHealthConnect',
200
+ 'openHealthConnect',
201
+ ],
202
+ events: [],
203
+ },
204
+ http: { operations: ['request', 'get', 'post', 'put', 'patch', 'delete'], events: [] },
205
+ inAppBrowser: {
206
+ operations: [
207
+ 'openInWebView',
208
+ 'openInSystemBrowser',
209
+ 'openInExternalBrowser',
210
+ 'close',
211
+ 'removeAllListeners',
212
+ ],
213
+ events: ['browserPageLoaded', 'browserPageNavigationCompleted', 'browserClosed'],
214
+ },
215
+ keyboard: {
216
+ operations: [
217
+ 'show',
218
+ 'hide',
219
+ 'setAccessoryBarVisible',
220
+ 'setScroll',
221
+ 'setStyle',
222
+ 'setResizeMode',
223
+ 'getResizeMode',
224
+ 'removeAllListeners',
225
+ ],
226
+ events: ['keyboardWillShow', 'keyboardDidShow', 'keyboardWillHide', 'keyboardDidHide'],
227
+ },
228
+ localLlm: {
229
+ operations: [
230
+ 'systemAvailability',
231
+ 'download',
232
+ 'prompt',
233
+ 'endSession',
234
+ 'generateImage',
235
+ 'warmup',
236
+ 'removeAllListeners',
237
+ ],
238
+ events: ['systemAvailabilityChange'],
239
+ },
240
+ localNotifications: {
241
+ operations: [
242
+ 'schedule',
243
+ 'update',
244
+ 'getPending',
245
+ 'registerActionTypes',
246
+ 'cancel',
247
+ 'cancelAll',
248
+ 'areEnabled',
249
+ 'getDeliveredNotifications',
250
+ 'removeDeliveredNotifications',
251
+ 'removeDeliveredNotificationsById',
252
+ 'removeAllDeliveredNotifications',
253
+ 'getByIds',
254
+ 'getAll',
255
+ 'createChannel',
256
+ 'deleteChannel',
257
+ 'listChannels',
258
+ 'checkPermissions',
259
+ 'requestPermissions',
260
+ 'changeExactNotificationSetting',
261
+ 'checkExactNotificationSetting',
262
+ 'removeAllListeners',
263
+ ],
264
+ events: ['localNotificationReceived', 'localNotificationActionPerformed'],
265
+ },
266
+ motion: { operations: ['removeAllListeners'], events: ['accel', 'orientation'] },
267
+ network: { operations: ['getStatus', 'removeAllListeners'], events: ['networkStatusChange'] },
268
+ preferences: {
269
+ operations: ['configure', 'get', 'set', 'remove', 'clear', 'keys', 'migrate', 'removeOld'],
270
+ events: [],
271
+ },
272
+ privacyScreen: { operations: ['enable', 'disable', 'isEnabled'], events: [] },
273
+ pushNotifications: {
274
+ operations: [
275
+ 'register',
276
+ 'unregister',
277
+ 'getDeliveredNotifications',
278
+ 'removeDeliveredNotifications',
279
+ 'removeAllDeliveredNotifications',
280
+ 'createChannel',
281
+ 'deleteChannel',
282
+ 'listChannels',
283
+ 'checkPermissions',
284
+ 'requestPermissions',
285
+ 'removeAllListeners',
286
+ ],
287
+ events: [
288
+ 'registration',
289
+ 'registrationError',
290
+ 'pushNotificationReceived',
291
+ 'pushNotificationActionPerformed',
292
+ ],
293
+ },
294
+ screenOrientation: {
295
+ operations: ['orientation', 'lock', 'unlock', 'removeAllListeners'],
296
+ events: ['screenOrientationChange'],
297
+ },
298
+ screenReader: {
299
+ operations: ['isEnabled', 'speak', 'removeAllListeners'],
300
+ events: ['stateChange'],
301
+ },
302
+ share: { operations: ['canShare', 'share'], events: [] },
303
+ splashScreen: { operations: ['show', 'hide'], events: [] },
304
+ statusBar: {
305
+ operations: ['setStyle', 'setBackgroundColor', 'show', 'hide', 'getInfo', 'setOverlaysWebView'],
306
+ events: ['statusBarVisibilityChanged', 'statusBarOverlayChanged'],
307
+ },
308
+ systemBars: { operations: ['setStyle', 'show', 'hide', 'setAnimation'], events: [] },
309
+ textZoom: { operations: ['get', 'getPreferred', 'set'], events: [] },
310
+ toast: { operations: ['show'], events: [] },
311
+ };
2
312
  // Shell y remotos deben compartir una sola instancia de este token.
3
313
  export const NATIVE_CAPABILITIES = new InjectionToken('Open Mova native capabilities');
4
314
  export function injectNativeCapabilities() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mova/core",
3
- "version": "0.1.9",
3
+ "version": "0.2.2",
4
4
  "description": "Contratos y utilidades Angular compartidas de Open Mova",
5
5
  "license": "MIT",
6
6
  "author": "Open Mova contributors",
@@ -42,7 +42,9 @@
42
42
  },
43
43
  "scripts": {
44
44
  "build": "tsc -p tsconfig.json",
45
- "typecheck": "tsc -p tsconfig.json --noEmit"
45
+ "typecheck": "tsc -p tsconfig.json --noEmit",
46
+ "test": "npm run build && npm run test:unit",
47
+ "test:unit": "node --test test/*.test.mjs"
46
48
  },
47
49
  "peerDependencies": {
48
50
  "@angular/core": "^21.2.23"