@nebula-rn/client 0.0.1

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.
Files changed (98) hide show
  1. package/dist/chooseMedia/index.d.ts +22 -0
  2. package/dist/chooseMedia/index.js +4 -0
  3. package/dist/compressImage/index.d.ts +7 -0
  4. package/dist/compressImage/index.js +4 -0
  5. package/dist/descriptions.d.ts +9 -0
  6. package/dist/descriptions.js +259 -0
  7. package/dist/file.d.ts +51 -0
  8. package/dist/file.js +14 -0
  9. package/dist/getAppBaseInfo/index.d.ts +6 -0
  10. package/dist/getAppBaseInfo/index.js +4 -0
  11. package/dist/getClipboardData/index.d.ts +1 -0
  12. package/dist/getClipboardData/index.js +4 -0
  13. package/dist/getFileInfo/index.d.ts +9 -0
  14. package/dist/getFileInfo/index.js +4 -0
  15. package/dist/getFileSystemManager/index.d.ts +70 -0
  16. package/dist/getFileSystemManager/index.js +43 -0
  17. package/dist/getImageInfo/index.d.ts +16 -0
  18. package/dist/getImageInfo/index.js +20 -0
  19. package/dist/getLocation/index.d.ts +15 -0
  20. package/dist/getLocation/index.js +4 -0
  21. package/dist/getScreenBrightness/index.d.ts +1 -0
  22. package/dist/getScreenBrightness/index.js +4 -0
  23. package/dist/getStorage/index.d.ts +1 -0
  24. package/dist/getStorage/index.js +8 -0
  25. package/dist/getStorageInfo/index.d.ts +6 -0
  26. package/dist/getStorageInfo/index.js +12 -0
  27. package/dist/getSystemInfo/index.d.ts +1 -0
  28. package/dist/getSystemInfo/index.js +4 -0
  29. package/dist/index.d.ts +26 -0
  30. package/dist/index.js +26 -0
  31. package/dist/location.d.ts +10 -0
  32. package/dist/location.js +18 -0
  33. package/dist/makePhoneCall/index.d.ts +1 -0
  34. package/dist/makePhoneCall/index.js +4 -0
  35. package/dist/media.d.ts +5 -0
  36. package/dist/media.js +8 -0
  37. package/dist/miniAppUpdate/index.d.ts +3 -0
  38. package/dist/miniAppUpdate/index.js +7 -0
  39. package/dist/network.d.ts +9 -0
  40. package/dist/network.js +15 -0
  41. package/dist/onUserCaptureScreen/index.d.ts +1 -0
  42. package/dist/onUserCaptureScreen/index.js +11 -0
  43. package/dist/previewImage/index.d.ts +8 -0
  44. package/dist/previewImage/index.js +4 -0
  45. package/dist/runtime/host.d.ts +41 -0
  46. package/dist/runtime/host.js +152 -0
  47. package/dist/scanCode/contract.d.ts +7 -0
  48. package/dist/scanCode/contract.js +8 -0
  49. package/dist/scanCode/icon_close.png +0 -0
  50. package/dist/scanCode/icon_pic.png +0 -0
  51. package/dist/scanCode/index.d.ts +6 -0
  52. package/dist/scanCode/index.js +72 -0
  53. package/dist/scanCode/types.d.ts +25 -0
  54. package/dist/scanCode/types.js +8 -0
  55. package/dist/sensors.d.ts +13 -0
  56. package/dist/sensors.js +15 -0
  57. package/dist/setClipboardData/index.d.ts +1 -0
  58. package/dist/setClipboardData/index.js +2 -0
  59. package/dist/setStorage/index.d.ts +5 -0
  60. package/dist/setStorage/index.js +5 -0
  61. package/dist/storage.d.ts +9 -0
  62. package/dist/storage.js +36 -0
  63. package/dist/uploadFile/index.d.ts +30 -0
  64. package/dist/uploadFile/index.js +6 -0
  65. package/package.json +77 -0
  66. package/src/chooseMedia/index.ts +36 -0
  67. package/src/compressImage/index.ts +14 -0
  68. package/src/descriptions.ts +294 -0
  69. package/src/file.ts +89 -0
  70. package/src/getAppBaseInfo/index.ts +10 -0
  71. package/src/getClipboardData/index.ts +5 -0
  72. package/src/getFileInfo/index.ts +17 -0
  73. package/src/getFileSystemManager/index.ts +141 -0
  74. package/src/getImageInfo/index.ts +40 -0
  75. package/src/getLocation/index.ts +23 -0
  76. package/src/getScreenBrightness/index.ts +5 -0
  77. package/src/getStorage/index.ts +10 -0
  78. package/src/getStorageInfo/index.ts +20 -0
  79. package/src/getSystemInfo/index.ts +5 -0
  80. package/src/index.ts +26 -0
  81. package/src/location.ts +40 -0
  82. package/src/makePhoneCall/index.ts +5 -0
  83. package/src/media.ts +19 -0
  84. package/src/miniAppUpdate/index.ts +20 -0
  85. package/src/network.ts +36 -0
  86. package/src/onUserCaptureScreen/index.ts +17 -0
  87. package/src/previewImage/index.tsx +13 -0
  88. package/src/runtime/host.ts +356 -0
  89. package/src/scanCode/contract.ts +20 -0
  90. package/src/scanCode/icon_close.png +0 -0
  91. package/src/scanCode/icon_pic.png +0 -0
  92. package/src/scanCode/index.tsx +127 -0
  93. package/src/scanCode/types.ts +38 -0
  94. package/src/sensors.ts +48 -0
  95. package/src/setClipboardData/index.ts +4 -0
  96. package/src/setStorage/index.ts +11 -0
  97. package/src/storage.ts +51 -0
  98. package/src/uploadFile/index.ts +57 -0
@@ -0,0 +1,40 @@
1
+ import { invokeHostApi } from '../runtime/host';
2
+
3
+ type GetImageInfoOption = {
4
+ src: string;
5
+ success?: (res: Record<string, unknown>) => void;
6
+ fail?: (res: Record<string, unknown>) => void;
7
+ complete?: (res: Record<string, unknown>) => void;
8
+ };
9
+
10
+ type GetImageInfoSuccessResult = {
11
+ width: number;
12
+ height: number;
13
+ path: string;
14
+ orientation: string;
15
+ type: string;
16
+ errMsg: string;
17
+ };
18
+
19
+ export function getImageInfo(
20
+ option: GetImageInfoOption,
21
+ ): Promise<GetImageInfoSuccessResult> {
22
+ const { src, success, fail, complete } = option;
23
+
24
+ return invokeHostApi<GetImageInfoSuccessResult>('getImageInfo', {
25
+ src,
26
+ })
27
+ .then(res => {
28
+ success?.(res);
29
+ complete?.(res);
30
+ return res;
31
+ })
32
+ .catch(error => {
33
+ const res = {
34
+ errMsg: error instanceof Error ? error.message : 'getImageInfo:fail',
35
+ };
36
+ fail?.(res);
37
+ complete?.(res);
38
+ throw res;
39
+ });
40
+ }
@@ -0,0 +1,23 @@
1
+ import { invokeHostApi } from '../runtime/host';
2
+
3
+ export interface GetLocationOption {
4
+ altitude?: boolean;
5
+ isHighAccuracy?: boolean;
6
+ highAccuracyExpireTime?: number;
7
+ }
8
+
9
+ export interface GetLocationResult {
10
+ latitude: number;
11
+ longitude: number;
12
+ speed: number;
13
+ accuracy: number;
14
+ altitude: number;
15
+ verticalAccuracy: number;
16
+ horizontalAccuracy: number;
17
+ }
18
+
19
+ export const getLocation = (
20
+ options: GetLocationOption = {},
21
+ ): Promise<GetLocationResult> => {
22
+ return invokeHostApi<GetLocationResult>('getLocation', options);
23
+ };
@@ -0,0 +1,5 @@
1
+ import { invokeHostApi } from '../runtime/host';
2
+
3
+ export const getScreenBrightness = () => {
4
+ return invokeHostApi<number>('getScreenBrightness');
5
+ };
@@ -0,0 +1,10 @@
1
+ import { deserializeStorageValue, getStorageItem } from '../storage';
2
+
3
+ export const getStorage = async <T>(key: string): Promise<T> => {
4
+ const data = await getStorageItem(key);
5
+ if (data !== undefined && data !== null) {
6
+ return deserializeStorageValue<T>(data);
7
+ }
8
+
9
+ throw new Error('getStorage:fail data not found');
10
+ };
@@ -0,0 +1,20 @@
1
+ import { getStorageCurrentSize, getStorageKeys } from '../storage';
2
+
3
+ export interface GetStorageInfoResult {
4
+ keys: string[];
5
+ currentSize: number;
6
+ limitSize: number;
7
+ }
8
+
9
+ export const getStorageInfo = async (): Promise<GetStorageInfoResult> => {
10
+ const [keys, currentSize] = await Promise.all([
11
+ getStorageKeys(),
12
+ getStorageCurrentSize(),
13
+ ]);
14
+
15
+ return {
16
+ keys,
17
+ currentSize,
18
+ limitSize: 10240,
19
+ };
20
+ };
@@ -0,0 +1,5 @@
1
+ import { invokeHostApi } from '../runtime/host';
2
+
3
+ export function getSystemInfo() {
4
+ return invokeHostApi<Record<string, unknown>>('getSystemInfo');
5
+ }
package/src/index.ts ADDED
@@ -0,0 +1,26 @@
1
+ export * from './chooseMedia';
2
+ export * from './compressImage';
3
+ export * from './descriptions';
4
+ export * from './file';
5
+ export * from './getAppBaseInfo';
6
+ export * from './getClipboardData';
7
+ export * from './getFileInfo';
8
+ export * from './getFileSystemManager';
9
+ export * from './getImageInfo';
10
+ export * from './getLocation';
11
+ export * from './getScreenBrightness';
12
+ export * from './getStorage';
13
+ export * from './getStorageInfo';
14
+ export * from './getSystemInfo';
15
+ export * from './location';
16
+ export * from './makePhoneCall';
17
+ export * from './media';
18
+ export * from './miniAppUpdate';
19
+ export * from './network';
20
+ export * from './onUserCaptureScreen';
21
+ export * from './previewImage';
22
+ export * from './scanCode';
23
+ export * from './sensors';
24
+ export * from './setClipboardData';
25
+ export * from './setStorage';
26
+ export * from './storage';
@@ -0,0 +1,40 @@
1
+ import { subscribeToHostEvent } from './runtime/host';
2
+
3
+ export interface LocationData {
4
+ accuracy: number;
5
+ altitude: number | null;
6
+ latitude: number;
7
+ longitude: number;
8
+ speed: number | null;
9
+ timestamp: number;
10
+ }
11
+
12
+ export type UnsubscribeFn = () => void | Promise<void>;
13
+
14
+ export const onLocationChange = (
15
+ enableHighAccuracy: boolean = true,
16
+ onSuccess: (data: LocationData) => void,
17
+ onError?: (error: unknown) => void,
18
+ ): UnsubscribeFn => {
19
+ let unsubscribePromise: Promise<void> | null = null;
20
+
21
+ const handle = subscribeToHostEvent<LocationData>(
22
+ 'locationChange',
23
+ {
24
+ enableHighAccuracy,
25
+ },
26
+ onSuccess,
27
+ ).catch(error => {
28
+ onError?.(error);
29
+ throw error;
30
+ });
31
+
32
+ return () => {
33
+ if (!unsubscribePromise) {
34
+ unsubscribePromise = handle
35
+ .then(subscription => subscription.unsubscribe())
36
+ .catch(() => {});
37
+ }
38
+ return unsubscribePromise;
39
+ };
40
+ };
@@ -0,0 +1,5 @@
1
+ import { invokeHostApi } from '../runtime/host';
2
+
3
+ export async function makePhoneCall(phoneNumber: string) {
4
+ return invokeHostApi<boolean>('makePhoneCall', { phoneNumber });
5
+ }
package/src/media.ts ADDED
@@ -0,0 +1,19 @@
1
+ import { invokeHostApi } from './runtime/host';
2
+
3
+ export type MediaType = 'photo' | 'video';
4
+
5
+ export interface SaveMediaOptions {
6
+ album?: string;
7
+ }
8
+
9
+ export const saveMedia = (
10
+ url: string,
11
+ type: MediaType,
12
+ options?: SaveMediaOptions,
13
+ ) => {
14
+ return invokeHostApi<string>('saveMedia', {
15
+ url,
16
+ type,
17
+ album: options?.album,
18
+ });
19
+ };
@@ -0,0 +1,20 @@
1
+ import type { MiniAppUpdateInfo } from '@nebula-rn/sdk';
2
+ import { invokeHostApi } from '../runtime/host';
3
+
4
+ export function getMiniAppUpdateInfo(): Promise<MiniAppUpdateInfo> {
5
+ return invokeHostApi<MiniAppUpdateInfo>(
6
+ 'getMiniAppUpdateInfo',
7
+ {},
8
+ '1.0',
9
+ 15000,
10
+ );
11
+ }
12
+
13
+ export function applyMiniAppUpdate(): Promise<MiniAppUpdateInfo> {
14
+ return invokeHostApi<MiniAppUpdateInfo>(
15
+ 'applyMiniAppUpdate',
16
+ {},
17
+ '1.0',
18
+ 120000,
19
+ );
20
+ }
package/src/network.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { invokeHostApi, subscribeToHostEvent } from './runtime/host';
2
+
3
+ export interface GetNetworkTypeResult {
4
+ networkType: string;
5
+ }
6
+
7
+ export interface NetworkStatusChangeResult {
8
+ isConnected: boolean;
9
+ networkType: string;
10
+ }
11
+
12
+ export const getNetworkType = async () => {
13
+ const result = await invokeHostApi<GetNetworkTypeResult>('getNetworkType');
14
+ return result.networkType;
15
+ };
16
+
17
+ export const onNetworkStatusChange = (
18
+ callback: (res: NetworkStatusChangeResult) => void,
19
+ ) => {
20
+ let unsubscribePromise: Promise<void> | null = null;
21
+
22
+ const handle = subscribeToHostEvent<NetworkStatusChangeResult>(
23
+ 'networkStatusChange',
24
+ {},
25
+ callback,
26
+ );
27
+
28
+ return () => {
29
+ if (!unsubscribePromise) {
30
+ unsubscribePromise = handle.then(subscription =>
31
+ subscription.unsubscribe(),
32
+ );
33
+ }
34
+ return unsubscribePromise;
35
+ };
36
+ };
@@ -0,0 +1,17 @@
1
+ import { subscribeToHostEvent } from '../runtime/host';
2
+
3
+ export const onUserCaptureScreen = (callback: () => void) => {
4
+ let unsubscribePromise: Promise<void> | null = null;
5
+ const handle = subscribeToHostEvent<null>('userCaptureScreen', {}, () =>
6
+ callback(),
7
+ );
8
+
9
+ return () => {
10
+ if (!unsubscribePromise) {
11
+ unsubscribePromise = handle.then(subscription =>
12
+ subscription.unsubscribe(),
13
+ );
14
+ }
15
+ return unsubscribePromise;
16
+ };
17
+ };
@@ -0,0 +1,13 @@
1
+ import { invokeHostApi } from '../runtime/host';
2
+
3
+ export interface PreviewImageOptions {
4
+ urls: string[];
5
+ current?: string;
6
+ showMenu?: boolean;
7
+ saveMediaText?: string;
8
+ cancelText?: string;
9
+ }
10
+
11
+ export function previewImages(options: PreviewImageOptions): Promise<void> {
12
+ return invokeHostApi<void>('previewImage', options, '1.0', 120000);
13
+ }
@@ -0,0 +1,356 @@
1
+ import { Miniapp } from '@nebula-rn/sdk';
2
+ import type { NebulaApiInvokeResult } from '@nebula-rn/sdk';
3
+
4
+ export type HostApiEventMessage<TPayload = unknown> = {
5
+ __nebulaApiEvent: 'v1';
6
+ apiName: string;
7
+ channel: string;
8
+ subscriptionId?: string;
9
+ taskId?: string;
10
+ payload?: TPayload;
11
+ };
12
+
13
+ type HostEventListener<TPayload> = (payload: TPayload) => void;
14
+
15
+ type HostTaskProgressListener<TProgress> = (payload: TProgress) => void;
16
+ type HostTaskHeadersListener<THeaders> = (payload: THeaders) => void;
17
+
18
+ export type HostTask<TData, TProgress, THeaders> = {
19
+ abort(): Promise<void>;
20
+ onProgressUpdate(listener: HostTaskProgressListener<TProgress>): void;
21
+ offProgressUpdate(listener: HostTaskProgressListener<TProgress>): void;
22
+ onHeadersReceived(listener: HostTaskHeadersListener<THeaders>): void;
23
+ offHeadersReceived(listener: HostTaskHeadersListener<THeaders>): void;
24
+ then<TResult1 = TData, TResult2 = never>(
25
+ onfulfilled?:
26
+ ((value: TData) => TResult1 | PromiseLike<TResult1>) | undefined | null,
27
+ onrejected?:
28
+ | ((reason: unknown) => TResult2 | PromiseLike<TResult2>)
29
+ | undefined
30
+ | null,
31
+ ): Promise<TResult1 | TResult2>;
32
+ catch<TResult = never>(
33
+ onrejected?:
34
+ ((reason: unknown) => TResult | PromiseLike<TResult>) | undefined | null,
35
+ ): Promise<TData | TResult>;
36
+ };
37
+
38
+ export type HostSubscriptionHandle = {
39
+ subscriptionId: string;
40
+ unsubscribe: () => Promise<void>;
41
+ };
42
+
43
+ type HostApiError = {
44
+ code?: unknown;
45
+ message?: unknown;
46
+ };
47
+
48
+ function isRecord(value: unknown): value is Record<string, unknown> {
49
+ return !!value && typeof value === 'object' && !Array.isArray(value);
50
+ }
51
+
52
+ function isHostApiEventMessage(
53
+ value: Record<string, unknown>,
54
+ ): value is HostApiEventMessage {
55
+ return (
56
+ value.__nebulaApiEvent === 'v1' &&
57
+ typeof value.apiName === 'string' &&
58
+ typeof value.channel === 'string'
59
+ );
60
+ }
61
+
62
+ export function createHostApiError(
63
+ apiName: string,
64
+ error: unknown,
65
+ fallbackCode = 'HOST_API_FAILED',
66
+ ): Error & { code: string } {
67
+ const details = isRecord(error) ? (error as HostApiError) : undefined;
68
+ const code = typeof details?.code === 'string' ? details.code : fallbackCode;
69
+ const message =
70
+ typeof details?.message === 'string'
71
+ ? details.message
72
+ : error instanceof Error
73
+ ? error.message
74
+ : `${apiName}:fail host request failed`;
75
+
76
+ const hostError = new Error(message) as Error & { code: string };
77
+ hostError.code = code;
78
+ return hostError;
79
+ }
80
+
81
+ export async function invokeHostApi<TData = unknown>(
82
+ apiName: string,
83
+ payload: object = {},
84
+ version = '1.0',
85
+ timeoutMs = 15000,
86
+ ): Promise<TData> {
87
+ const result = await Miniapp.invokeHostApi<TData>(
88
+ apiName,
89
+ payload as Record<string, unknown>,
90
+ version,
91
+ timeoutMs,
92
+ );
93
+
94
+ if (!result.ok) {
95
+ throw createHostApiError(apiName, result.error);
96
+ }
97
+
98
+ return result.data;
99
+ }
100
+
101
+ export async function invokeHostApiResult<TData = unknown>(
102
+ apiName: string,
103
+ payload: object = {},
104
+ version = '1.0',
105
+ timeoutMs = 15000,
106
+ ): Promise<NebulaApiInvokeResult<TData>> {
107
+ return Miniapp.invokeHostApi<TData>(
108
+ apiName,
109
+ payload as Record<string, unknown>,
110
+ version,
111
+ timeoutMs,
112
+ );
113
+ }
114
+
115
+ export function addHostApiEventListener<TPayload = unknown>(
116
+ apiName: string,
117
+ channel: string,
118
+ listener: HostEventListener<TPayload>,
119
+ matcher?: (message: HostApiEventMessage<TPayload>) => boolean,
120
+ ): () => void {
121
+ return Miniapp.onHostMessage(event => {
122
+ const { message } = event;
123
+ if (!isRecord(message) || !isHostApiEventMessage(message)) {
124
+ return;
125
+ }
126
+
127
+ if (message.apiName !== apiName || message.channel !== channel) {
128
+ return;
129
+ }
130
+
131
+ const typedMessage = message as HostApiEventMessage<TPayload>;
132
+
133
+ if (matcher && !matcher(typedMessage)) {
134
+ return;
135
+ }
136
+
137
+ listener((typedMessage.payload ?? null) as TPayload);
138
+ });
139
+ }
140
+
141
+ export async function subscribeToHostEvent<TPayload = unknown>(
142
+ apiName: string,
143
+ payload: object,
144
+ onEvent: HostEventListener<TPayload>,
145
+ options?: {
146
+ version?: string;
147
+ timeoutMs?: number;
148
+ unsubscribePayload?: object;
149
+ },
150
+ ): Promise<HostSubscriptionHandle> {
151
+ const version = options?.version ?? '1.0';
152
+ const timeoutMs = options?.timeoutMs ?? 15000;
153
+ const result = await invokeHostApi<{
154
+ subscriptionId: string;
155
+ }>(`${apiName}.subscribe`, payload, version, timeoutMs);
156
+
157
+ const stopListening = addHostApiEventListener<TPayload>(
158
+ apiName,
159
+ 'subscription',
160
+ onEvent,
161
+ message => message.subscriptionId === result.subscriptionId,
162
+ );
163
+
164
+ return {
165
+ subscriptionId: result.subscriptionId,
166
+ unsubscribe: async () => {
167
+ stopListening();
168
+ await invokeHostApi(
169
+ `${apiName}.unsubscribe`,
170
+ {
171
+ subscriptionId: result.subscriptionId,
172
+ ...(options?.unsubscribePayload ?? {}),
173
+ },
174
+ version,
175
+ timeoutMs,
176
+ );
177
+ },
178
+ };
179
+ }
180
+
181
+ class HostTaskImpl<TData, TProgress, THeaders> implements HostTask<
182
+ TData,
183
+ TProgress,
184
+ THeaders
185
+ > {
186
+ private readonly promise: Promise<TData>;
187
+ private readonly aborter: () => Promise<void>;
188
+ private readonly progressListeners = new Set<
189
+ HostTaskProgressListener<TProgress>
190
+ >();
191
+ private readonly headersListeners = new Set<
192
+ HostTaskHeadersListener<THeaders>
193
+ >();
194
+ private readonly cleanup: () => void;
195
+
196
+ constructor(
197
+ promise: Promise<TData>,
198
+ aborter: () => Promise<void>,
199
+ cleanup: () => void,
200
+ ) {
201
+ this.promise = promise;
202
+ this.aborter = aborter;
203
+ this.cleanup = cleanup;
204
+ }
205
+
206
+ abort(): Promise<void> {
207
+ this.cleanup();
208
+ return this.aborter();
209
+ }
210
+
211
+ onProgressUpdate(listener: HostTaskProgressListener<TProgress>): void {
212
+ this.progressListeners.add(listener);
213
+ }
214
+
215
+ offProgressUpdate(listener: HostTaskProgressListener<TProgress>): void {
216
+ this.progressListeners.delete(listener);
217
+ }
218
+
219
+ onHeadersReceived(listener: HostTaskHeadersListener<THeaders>): void {
220
+ this.headersListeners.add(listener);
221
+ }
222
+
223
+ offHeadersReceived(listener: HostTaskHeadersListener<THeaders>): void {
224
+ this.headersListeners.delete(listener);
225
+ }
226
+
227
+ emitProgress(payload: TProgress): void {
228
+ this.progressListeners.forEach(listener => listener(payload));
229
+ }
230
+
231
+ emitHeaders(payload: THeaders): void {
232
+ this.headersListeners.forEach(listener => listener(payload));
233
+ }
234
+
235
+ then<TResult1 = TData, TResult2 = never>(
236
+ onfulfilled?:
237
+ ((value: TData) => TResult1 | PromiseLike<TResult1>) | undefined | null,
238
+ onrejected?:
239
+ | ((reason: unknown) => TResult2 | PromiseLike<TResult2>)
240
+ | undefined
241
+ | null,
242
+ ): Promise<TResult1 | TResult2> {
243
+ return this.promise.then(onfulfilled, onrejected);
244
+ }
245
+
246
+ catch<TResult = never>(
247
+ onrejected?:
248
+ ((reason: unknown) => TResult | PromiseLike<TResult>) | undefined | null,
249
+ ): Promise<TData | TResult> {
250
+ return this.promise.catch(onrejected);
251
+ }
252
+ }
253
+
254
+ export function createHostTask<TData, TProgress, THeaders>(
255
+ apiName: string,
256
+ payload: object,
257
+ options?: {
258
+ version?: string;
259
+ timeoutMs?: number;
260
+ },
261
+ ): HostTask<TData, TProgress, THeaders> {
262
+ const version = options?.version ?? '1.0';
263
+ const timeoutMs = options?.timeoutMs ?? 15000;
264
+ let stopResultListener = () => {};
265
+ let stopProgressListener = () => {};
266
+ let stopHeadersListener = () => {};
267
+ let startedTaskId: string | null = null;
268
+
269
+ function cleanup() {
270
+ stopResultListener();
271
+ stopProgressListener();
272
+ stopHeadersListener();
273
+ }
274
+
275
+ const startTask = invokeHostApi<{ taskId: string }>(
276
+ `${apiName}.start`,
277
+ payload,
278
+ version,
279
+ timeoutMs,
280
+ );
281
+ const promise = startTask.then(
282
+ ({ taskId }) =>
283
+ new Promise<TData>((resolve, reject) => {
284
+ startedTaskId = taskId;
285
+
286
+ stopResultListener = addHostApiEventListener<
287
+ NebulaApiInvokeResult<TData> | TData
288
+ >(
289
+ apiName,
290
+ 'task.result',
291
+ resultPayload => {
292
+ cleanup();
293
+ if (
294
+ isRecord(resultPayload) &&
295
+ typeof resultPayload.ok === 'boolean'
296
+ ) {
297
+ const result = resultPayload as NebulaApiInvokeResult<TData>;
298
+ if (result.ok) {
299
+ resolve(result.data);
300
+ return;
301
+ }
302
+ reject(createHostApiError(apiName, result.error));
303
+ return;
304
+ }
305
+ resolve(resultPayload as TData);
306
+ },
307
+ message => message.taskId === taskId,
308
+ );
309
+
310
+ stopProgressListener = addHostApiEventListener<TProgress>(
311
+ apiName,
312
+ 'task.progress',
313
+ progressPayload => {
314
+ task.emitProgress(progressPayload);
315
+ },
316
+ message => message.taskId === taskId,
317
+ );
318
+
319
+ stopHeadersListener = addHostApiEventListener<THeaders>(
320
+ apiName,
321
+ 'task.headers',
322
+ headersPayload => {
323
+ task.emitHeaders(headersPayload);
324
+ },
325
+ message => message.taskId === taskId,
326
+ );
327
+ }),
328
+ );
329
+
330
+ const task = new HostTaskImpl<TData, TProgress, THeaders>(
331
+ promise,
332
+ async () => {
333
+ cleanup();
334
+ const taskId =
335
+ startedTaskId ??
336
+ (await startTask.then(
337
+ result => result.taskId,
338
+ () => null,
339
+ ));
340
+ if (!taskId) {
341
+ return;
342
+ }
343
+ await invokeHostApi(
344
+ `${apiName}.abort`,
345
+ {
346
+ taskId,
347
+ },
348
+ version,
349
+ timeoutMs,
350
+ );
351
+ },
352
+ cleanup,
353
+ );
354
+
355
+ return task;
356
+ }
@@ -0,0 +1,20 @@
1
+ import { ScanCodeError } from './types';
2
+ import type {
3
+ ScanCodeCapabilityName,
4
+ ScanCodeCapabilityVersion,
5
+ ScanCodeErrorCode,
6
+ } from './types';
7
+
8
+ export const SCAN_CODE_CAPABILITY_NAME: ScanCodeCapabilityName = 'scanCode';
9
+ export const SCAN_CODE_CAPABILITY_VERSION: ScanCodeCapabilityVersion = '1.0';
10
+
11
+ export const SCAN_CODE_DEFAULT_TYPES = ['qr', 'ean-13', 'code-128'] as const;
12
+
13
+ export const SCAN_CODE_MINIMUM_HOST_BRIDGE_VERSION = '1.0';
14
+
15
+ export function createScanCodeError(
16
+ code: ScanCodeErrorCode,
17
+ message: string,
18
+ ): ScanCodeError {
19
+ return new ScanCodeError(code, message);
20
+ }
Binary file
Binary file