@snap/camera-kit 1.0.1 → 1.2.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/README.md +1 -1
- package/dist/CameraKit.d.ts +17 -6
- package/dist/CameraKit.d.ts.map +1 -1
- package/dist/CameraKit.js +26 -4
- package/dist/CameraKit.js.map +1 -1
- package/dist/RootServices.d.ts +6 -2
- package/dist/RootServices.d.ts.map +1 -1
- package/dist/RootServices.js.map +1 -1
- package/dist/bootstrapCameraKit.d.ts.map +1 -1
- package/dist/bootstrapCameraKit.js +6 -2
- package/dist/bootstrapCameraKit.js.map +1 -1
- package/dist/clients/remoteApiSpecsClient.d.ts +10 -0
- package/dist/clients/remoteApiSpecsClient.d.ts.map +1 -0
- package/dist/clients/remoteApiSpecsClient.js +6 -0
- package/dist/clients/remoteApiSpecsClient.js.map +1 -0
- package/dist/common/typeguards.d.ts +3 -0
- package/dist/common/typeguards.d.ts.map +1 -1
- package/dist/common/typeguards.js +12 -0
- package/dist/common/typeguards.js.map +1 -1
- package/dist/configuration.d.ts +115 -0
- package/dist/configuration.d.ts.map +1 -1
- package/dist/configuration.js +1 -0
- package/dist/configuration.js.map +1 -1
- package/dist/environment.js +1 -1
- package/dist/environment.js.map +1 -1
- package/dist/extensions/extensionRequestContext.d.ts +6 -0
- package/dist/extensions/extensionRequestContext.d.ts.map +1 -1
- package/dist/extensions/extensionRequestContext.js +3 -2
- package/dist/extensions/extensionRequestContext.js.map +1 -1
- package/dist/geo/geoDataProvider.d.ts +32 -0
- package/dist/geo/geoDataProvider.d.ts.map +1 -0
- package/dist/geo/geoDataProvider.js +25 -0
- package/dist/geo/geoDataProvider.js.map +1 -0
- package/dist/geo/registerGeoDataProvider.d.ts +11 -0
- package/dist/geo/registerGeoDataProvider.d.ts.map +1 -0
- package/dist/geo/registerGeoDataProvider.js +22 -0
- package/dist/geo/registerGeoDataProvider.js.map +1 -0
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/lens-core-module/generated-types.d.ts +28 -0
- package/dist/lens-core-module/generated-types.d.ts.map +1 -1
- package/dist/lens-core-module/generated-types.js.map +1 -1
- package/dist/lens-core-module/lensCore.d.ts.map +1 -1
- package/dist/lens-core-module/lensCore.js +1 -0
- package/dist/lens-core-module/lensCore.js.map +1 -1
- package/dist/lensCoreWasmVersions.js +3 -3
- package/dist/lensCoreWasmVersions.js.map +1 -1
- package/dist/platform/platformInfo.d.ts.map +1 -1
- package/dist/platform/platformInfo.js +1 -1
- package/dist/platform/platformInfo.js.map +1 -1
- package/dist/remote-configuration/cofHandler.js.map +1 -1
- package/dist/remote-configuration/remoteConfiguration.d.ts +4 -0
- package/dist/remote-configuration/remoteConfiguration.d.ts.map +1 -1
- package/dist/remote-configuration/remoteConfiguration.js +10 -0
- package/dist/remote-configuration/remoteConfiguration.js.map +1 -1
- package/dist/session/CameraKitSession.d.ts +9 -9
- package/dist/session/CameraKitSession.d.ts.map +1 -1
- package/dist/session/CameraKitSession.js +4 -2
- package/dist/session/CameraKitSession.js.map +1 -1
- package/dist/session/LensKeyboard.d.ts +75 -31
- package/dist/session/LensKeyboard.d.ts.map +1 -1
- package/dist/session/LensKeyboard.js +60 -38
- package/dist/session/LensKeyboard.js.map +1 -1
- package/dist/uri-handlers/UriHandlers.d.ts.map +1 -0
- package/dist/uri-handlers/UriHandlers.js.map +1 -0
- package/dist/uri-handlers/internal-handlers/httpUriHandler.d.ts +42 -0
- package/dist/uri-handlers/internal-handlers/httpUriHandler.d.ts.map +1 -0
- package/dist/uri-handlers/internal-handlers/httpUriHandler.js +149 -0
- package/dist/uri-handlers/internal-handlers/httpUriHandler.js.map +1 -0
- package/dist/uri-handlers/internal-handlers/httpValidators.d.ts +9 -0
- package/dist/uri-handlers/internal-handlers/httpValidators.d.ts.map +1 -0
- package/dist/uri-handlers/internal-handlers/httpValidators.js +115 -0
- package/dist/uri-handlers/internal-handlers/httpValidators.js.map +1 -0
- package/dist/{extensions/RemoteApiServices.d.ts → uri-handlers/internal-handlers/remoteApiUriHandler.d.ts} +8 -8
- package/dist/uri-handlers/internal-handlers/remoteApiUriHandler.d.ts.map +1 -0
- package/dist/uri-handlers/internal-handlers/remoteApiUriHandler.js +121 -0
- package/dist/uri-handlers/internal-handlers/remoteApiUriHandler.js.map +1 -0
- package/dist/{extensions → uri-handlers}/uriHandlersRegister.d.ts +6 -4
- package/dist/uri-handlers/uriHandlersRegister.d.ts.map +1 -0
- package/dist/{extensions → uri-handlers}/uriHandlersRegister.js +13 -3
- package/dist/uri-handlers/uriHandlersRegister.js.map +1 -0
- package/dist/uri-handlers/uriRequestProcessor.d.ts +37 -0
- package/dist/uri-handlers/uriRequestProcessor.d.ts.map +1 -0
- package/dist/uri-handlers/uriRequestProcessor.js +69 -0
- package/dist/uri-handlers/uriRequestProcessor.js.map +1 -0
- package/docs/html/assets/hierarchy.js +1 -0
- package/docs/html/assets/highlight.css +9 -2
- package/docs/html/assets/icons.js +18 -0
- package/docs/html/assets/icons.svg +1 -0
- package/docs/html/assets/main.js +5 -4
- package/docs/html/assets/navigation.js +1 -1
- package/docs/html/assets/search.js +1 -1
- package/docs/html/assets/style.css +1422 -1226
- package/docs/html/classes/CameraKit.html +18 -16
- package/docs/html/classes/CameraKitSession.html +79 -51
- package/docs/html/classes/CameraKitSource.html +18 -18
- package/docs/html/classes/LensPerformanceMeasurement.html +11 -11
- package/docs/html/classes/LensPerformanceMetrics.html +8 -7
- package/docs/html/classes/LensRepository.html +25 -23
- package/docs/html/classes/Transform2D.html +9 -9
- package/docs/html/classes/TypedCustomEvent.html +5 -4
- package/docs/html/classes/TypedEventTarget.html +6 -6
- package/docs/html/enums/Lens_CameraFacing.html +5 -5
- package/docs/html/functions/bootstrapCameraKit.html +11 -10
- package/docs/html/functions/createExtension.html +7 -6
- package/docs/html/functions/createImageSource.html +5 -5
- package/docs/html/functions/createMediaStreamSource.html +5 -5
- package/docs/html/functions/createVideoSource.html +5 -5
- package/docs/html/functions/estimateLensPerformance.html +2 -2
- package/docs/html/functions/filePickerFactory.html +2 -2
- package/docs/html/functions/getExtensionRequestContext.html +3 -0
- package/docs/html/functions/lensSourcesFactory.html +5 -4
- package/docs/html/functions/remoteApiServicesFactory.html +1 -1
- package/docs/html/hierarchy.html +1 -1
- package/docs/html/index.html +111 -88
- package/docs/html/interfaces/BitmojiUserInfo.html +3 -3
- package/docs/html/interfaces/CameraKitBootstrapConfiguration.html +40 -21
- package/docs/html/interfaces/CameraKitDeviceOptions.html +7 -7
- package/docs/html/interfaces/CameraKitSourceInfo.html +7 -7
- package/docs/html/interfaces/CameraKitSourceSubscriber.html +4 -4
- package/docs/html/interfaces/ComputedFrameMetrics.html +6 -6
- package/docs/html/interfaces/CreateSessionOptions.html +7 -7
- package/docs/html/interfaces/EstimatedLensPerformance.html +5 -5
- package/docs/html/interfaces/Font.html +6 -0
- package/docs/html/interfaces/FriendUserInfo.html +4 -4
- package/docs/html/interfaces/FunctionSourceOptions.html +4 -4
- package/docs/html/interfaces/Keyboard.html +29 -0
- package/docs/html/interfaces/KeyboardActiveEvent.html +12 -0
- package/docs/html/interfaces/Lens.html +21 -21
- package/docs/html/interfaces/LensCreator.html +3 -3
- package/docs/html/interfaces/LensHttpRequest.html +16 -0
- package/docs/html/interfaces/LensLaunchData.html +6 -6
- package/docs/html/interfaces/LensSource.html +5 -5
- package/docs/html/interfaces/LensUserData.html +10 -10
- package/docs/html/interfaces/LoadAssetRequest.html +10 -10
- package/docs/html/interfaces/MediaStreamSourceOptions.html +11 -11
- package/docs/html/interfaces/Preview.html +4 -4
- package/docs/html/interfaces/RemoteApiRequest.html +10 -10
- package/docs/html/interfaces/RemoteApiResponse.html +8 -8
- package/docs/html/interfaces/RemoteApiService.html +9 -9
- package/docs/html/interfaces/Snapcode.html +6 -6
- package/docs/html/interfaces/UriCancelRequest.html +3 -3
- package/docs/html/interfaces/UriRequest.html +7 -7
- package/docs/html/interfaces/UriResponse.html +6 -6
- package/docs/html/interfaces/VideoSourceOptions.html +9 -9
- package/docs/html/modules.html +1 -99
- package/docs/html/types/ArgumentValidationError.html +2 -2
- package/docs/html/types/AssetLoader.html +4 -4
- package/docs/html/types/AssetResponse.html +1 -1
- package/docs/html/types/AssetTiming.html +2 -2
- package/docs/html/types/BenchmarkError.html +1 -1
- package/docs/html/types/BootstrapError.html +2 -2
- package/docs/html/types/CacheKeyNotFoundError.html +1 -1
- package/docs/html/types/CameraKitSessionEventListener.html +2 -2
- package/docs/html/types/CameraKitSessionEvents.html +4 -3
- package/docs/html/types/CameraKitSourceError.html +1 -1
- package/docs/html/types/ConfigurationError.html +2 -2
- package/docs/html/types/FetchHandler.html +1 -1
- package/docs/html/types/FilePicker.html +5 -5
- package/docs/html/types/FilePickerOptions.html +2 -2
- package/docs/html/types/FilePickerResult.html +2 -2
- package/docs/html/types/KeyboardEventListener.html +2 -0
- package/docs/html/types/KeyboardEvents.html +2 -2
- package/docs/html/types/LegalError.html +1 -1
- package/docs/html/types/LensAbortError.html +6 -5
- package/docs/html/types/LensAssetError.html +2 -2
- package/docs/html/types/LensContentValidationError.html +1 -1
- package/docs/html/types/LensError.html +1 -1
- package/docs/html/types/LensExecutionError.html +6 -5
- package/docs/html/types/LensHttpHandler.html +9 -0
- package/docs/html/types/LensImagePickerError.html +2 -2
- package/docs/html/types/LensLaunchParams.html +2 -2
- package/docs/html/types/LensMetricsEvents.html +2 -2
- package/docs/html/types/LensPerformanceCluster.html +1 -1
- package/docs/html/types/LensView.html +3 -3
- package/docs/html/types/LensWait.html +2 -2
- package/docs/html/types/Matrix.html +2 -2
- package/docs/html/types/PersistentStoreError.html +2 -2
- package/docs/html/types/PlatformNotSupportedError.html +3 -3
- package/docs/html/types/PublicContainer.html +2 -2
- package/docs/html/types/PublicServices.html +2 -2
- package/docs/html/types/RemoteApiCancelRequestHandler.html +2 -2
- package/docs/html/types/RemoteApiRequestHandler.html +2 -2
- package/docs/html/types/RemoteApiServices.html +1 -1
- package/docs/html/types/RemoteApiStatus.html +2 -2
- package/docs/html/types/RenderTarget.html +3 -3
- package/docs/html/types/Uri.html +1 -1
- package/docs/html/types/WebGLError.html +1 -1
- package/docs/html/types/Zodiac.html +1 -1
- package/docs/html/variables/extensionRequestContext.html +3 -2
- package/docs/md/README.md +5 -3
- package/docs/md/classes/CameraKit.md +26 -37
- package/docs/md/classes/CameraKitSession.md +150 -108
- package/docs/md/classes/CameraKitSource.md +46 -37
- package/docs/md/classes/LensPerformanceMeasurement.md +18 -26
- package/docs/md/classes/LensPerformanceMetrics.md +8 -10
- package/docs/md/classes/LensRepository.md +66 -45
- package/docs/md/classes/Transform2D.md +19 -26
- package/docs/md/classes/TypedCustomEvent.md +24 -32
- package/docs/md/classes/TypedEventTarget.md +43 -54
- package/docs/md/enumerations/Lens_CameraFacing.md +31 -0
- package/docs/md/functions/bootstrapCameraKit.md +66 -0
- package/docs/md/functions/createExtension.md +50 -0
- package/docs/md/functions/createImageSource.md +30 -0
- package/docs/md/functions/createMediaStreamSource.md +30 -0
- package/docs/md/functions/createVideoSource.md +31 -0
- package/docs/md/functions/estimateLensPerformance.md +18 -0
- package/docs/md/functions/filePickerFactory.md +22 -0
- package/docs/md/functions/getExtensionRequestContext.md +21 -0
- package/docs/md/functions/lensSourcesFactory.md +37 -0
- package/docs/md/functions/remoteApiServicesFactory.md +19 -0
- package/docs/md/globals.md +124 -0
- package/docs/md/interfaces/BitmojiUserInfo.md +9 -12
- package/docs/md/interfaces/CameraKitBootstrapConfiguration.md +99 -40
- package/docs/md/interfaces/CameraKitDeviceOptions.md +11 -17
- package/docs/md/interfaces/CameraKitSourceInfo.md +14 -20
- package/docs/md/interfaces/CameraKitSourceSubscriber.md +23 -28
- package/docs/md/interfaces/ComputedFrameMetrics.md +13 -19
- package/docs/md/interfaces/CreateSessionOptions.md +10 -13
- package/docs/md/interfaces/EstimatedLensPerformance.md +10 -14
- package/docs/md/interfaces/Font.md +25 -0
- package/docs/md/interfaces/FriendUserInfo.md +12 -16
- package/docs/md/interfaces/FunctionSourceOptions.md +6 -8
- package/docs/md/interfaces/Keyboard.md +137 -0
- package/docs/md/interfaces/KeyboardActiveEvent.md +46 -0
- package/docs/md/interfaces/Lens.md +26 -37
- package/docs/md/interfaces/LensCreator.md +6 -8
- package/docs/md/interfaces/LensHttpRequest.md +60 -0
- package/docs/md/interfaces/LensLaunchData.md +13 -17
- package/docs/md/interfaces/LensSource.md +26 -27
- package/docs/md/interfaces/LensUserData.md +30 -40
- package/docs/md/interfaces/LoadAssetRequest.md +13 -18
- package/docs/md/interfaces/MediaStreamSourceOptions.md +15 -22
- package/docs/md/interfaces/Preview.md +6 -8
- package/docs/md/interfaces/RemoteApiRequest.md +12 -17
- package/docs/md/interfaces/RemoteApiResponse.md +10 -14
- package/docs/md/interfaces/RemoteApiService.md +20 -19
- package/docs/md/interfaces/Snapcode.md +8 -11
- package/docs/md/interfaces/UriCancelRequest.md +7 -10
- package/docs/md/interfaces/UriRequest.md +15 -22
- package/docs/md/interfaces/UriResponse.md +14 -20
- package/docs/md/interfaces/VideoSourceOptions.md +13 -19
- package/docs/md/type-aliases/ArgumentValidationError.md +11 -0
- package/docs/md/type-aliases/AssetLoader.md +26 -0
- package/docs/md/type-aliases/AssetResponse.md +9 -0
- package/docs/md/type-aliases/AssetTiming.md +18 -0
- package/docs/md/type-aliases/BenchmarkError.md +9 -0
- package/docs/md/type-aliases/BootstrapError.md +12 -0
- package/docs/md/type-aliases/CacheKeyNotFoundError.md +9 -0
- package/docs/md/type-aliases/CameraKitSessionEventListener.md +11 -0
- package/docs/md/type-aliases/CameraKitSessionEvents.md +17 -0
- package/docs/md/type-aliases/CameraKitSourceError.md +9 -0
- package/docs/md/type-aliases/ConfigurationError.md +11 -0
- package/docs/md/type-aliases/FetchHandler.md +27 -0
- package/docs/md/type-aliases/FilePicker.md +32 -0
- package/docs/md/type-aliases/FilePickerOptions.md +11 -0
- package/docs/md/type-aliases/FilePickerResult.md +11 -0
- package/docs/md/type-aliases/KeyboardEventListener.md +11 -0
- package/docs/md/type-aliases/KeyboardEvents.md +11 -0
- package/docs/md/type-aliases/LegalError.md +9 -0
- package/docs/md/type-aliases/LensAbortError.md +22 -0
- package/docs/md/type-aliases/LensAssetError.md +11 -0
- package/docs/md/type-aliases/LensContentValidationError.md +9 -0
- package/docs/md/type-aliases/LensError.md +9 -0
- package/docs/md/type-aliases/LensExecutionError.md +23 -0
- package/docs/md/type-aliases/LensHttpHandler.md +41 -0
- package/docs/md/type-aliases/LensImagePickerError.md +12 -0
- package/docs/md/type-aliases/LensLaunchParams.md +11 -0
- package/docs/md/type-aliases/LensMetricsEvents.md +13 -0
- package/docs/md/type-aliases/LensPerformanceCluster.md +9 -0
- package/docs/md/type-aliases/LensView.md +21 -0
- package/docs/md/type-aliases/LensWait.md +13 -0
- package/docs/md/type-aliases/Matrix.md +12 -0
- package/docs/md/type-aliases/PersistentStoreError.md +11 -0
- package/docs/md/type-aliases/PlatformNotSupportedError.md +13 -0
- package/docs/md/type-aliases/PublicContainer.md +12 -0
- package/docs/md/type-aliases/PublicServices.md +11 -0
- package/docs/md/type-aliases/RemoteApiCancelRequestHandler.md +15 -0
- package/docs/md/type-aliases/RemoteApiRequestHandler.md +24 -0
- package/docs/md/type-aliases/RemoteApiServices.md +9 -0
- package/docs/md/type-aliases/RemoteApiStatus.md +11 -0
- package/docs/md/type-aliases/RenderTarget.md +14 -0
- package/docs/md/type-aliases/Uri.md +9 -0
- package/docs/md/type-aliases/WebGLError.md +9 -0
- package/docs/md/type-aliases/Zodiac.md +9 -0
- package/docs/md/variables/extensionRequestContext.md +15 -0
- package/package.json +5 -5
- package/dist/extensions/RemoteApiServices.d.ts.map +0 -1
- package/dist/extensions/RemoteApiServices.js +0 -159
- package/dist/extensions/RemoteApiServices.js.map +0 -1
- package/dist/extensions/UriHandlers.d.ts.map +0 -1
- package/dist/extensions/UriHandlers.js.map +0 -1
- package/dist/extensions/uriHandlersRegister.d.ts.map +0 -1
- package/dist/extensions/uriHandlersRegister.js.map +0 -1
- package/docs/html/types/Keyboard.html +0 -26
- package/docs/md/.nojekyll +0 -1
- package/docs/md/enums/Lens_CameraFacing.md +0 -36
- package/docs/md/modules.md +0 -904
- /package/dist/{extensions → uri-handlers}/UriHandlers.d.ts +0 -0
- /package/dist/{extensions → uri-handlers}/UriHandlers.js +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { RemoteApiSpecsClient } from "../../clients/remoteApiSpecsClient";
|
|
2
|
+
import type { Lens } from "../../lens/Lens";
|
|
3
|
+
import type { LensState } from "../../session/lensState";
|
|
4
|
+
import type { SessionState } from "../../session/sessionState";
|
|
5
|
+
import type { LensHttpHandler } from "../../configuration";
|
|
6
|
+
import type { UriHandler, UriRequest, UriResponse } from "../UriHandlers";
|
|
7
|
+
import type { RemoteApiSpec } from "../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec";
|
|
8
|
+
/**
|
|
9
|
+
*
|
|
10
|
+
* @internal
|
|
11
|
+
*
|
|
12
|
+
* @param lensState
|
|
13
|
+
* @param sessionState
|
|
14
|
+
* @param remoteApiSpecsClient
|
|
15
|
+
* @param clientLentHttpRequestHandler
|
|
16
|
+
* @returns
|
|
17
|
+
*/
|
|
18
|
+
export declare function createHttpUriHandler(lensState: LensState, sessionState: SessionState, remoteApiSpecsClient: RemoteApiSpecsClient, customLentFetchHandler: LensHttpHandler | undefined): UriHandler;
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @internal
|
|
22
|
+
*
|
|
23
|
+
* @param request
|
|
24
|
+
* @param lens
|
|
25
|
+
* @param reply
|
|
26
|
+
* @param setCancellationHandler
|
|
27
|
+
* @param allowlist
|
|
28
|
+
* @param clientLensHttpRequestHandler
|
|
29
|
+
*/
|
|
30
|
+
export declare function handleHttpUriRequest(request: UriRequest, lens: Lens, reply: (response: UriResponse) => void, setCancellationHandler: (fn: () => void) => void, allowlist: RemoteApiSpec[], customLensHttpHandler: LensHttpHandler | undefined): Promise<void>;
|
|
31
|
+
/**
|
|
32
|
+
* @internal
|
|
33
|
+
*/
|
|
34
|
+
export declare function mapLensToFetchRequest({ uri, method, metadata, data }: UriRequest): {
|
|
35
|
+
url: string;
|
|
36
|
+
init: RequestInit;
|
|
37
|
+
};
|
|
38
|
+
/**
|
|
39
|
+
* @internal
|
|
40
|
+
*/
|
|
41
|
+
export declare function mapFetchToLensResponse(response: Response): Promise<UriResponse>;
|
|
42
|
+
//# sourceMappingURL=httpUriHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpUriHandler.d.ts","sourceRoot":"","sources":["../../../src/uri-handlers/internal-handlers/httpUriHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC/E,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAEzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAE/D,OAAO,KAAK,EAAmC,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAC5F,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE1E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,+DAA+D,CAAC;AA2BnG;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAChC,SAAS,EAAE,SAAS,EACpB,YAAY,EAAE,YAAY,EAC1B,oBAAoB,EAAE,oBAAoB,EAC1C,sBAAsB,EAAE,eAAe,GAAG,SAAS,GACpD,UAAU,CAmBZ;AAQD;;;;;;;;;;GAUG;AACH,wBAAsB,oBAAoB,CACtC,OAAO,EAAE,UAAU,EACnB,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,CAAC,QAAQ,EAAE,WAAW,KAAK,IAAI,EACtC,sBAAsB,EAAE,CAAC,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,EAChD,SAAS,EAAE,aAAa,EAAE,EAC1B,qBAAqB,EAAE,eAAe,GAAG,SAAS,iBAgFrD;AAcD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,WAAW,CAAA;CAAE,CAcrH;AAED;;GAEG;AACH,wBAAsB,sBAAsB,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,WAAW,CAAC,CAmBrF"}
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import { __awaiter } from "tslib";
|
|
2
|
+
import { getLogger } from "../../logger/logger";
|
|
3
|
+
import { namedError } from "../../namedErrors";
|
|
4
|
+
import { createUriRequestProcessor } from "../uriRequestProcessor";
|
|
5
|
+
import { isPromise } from "../../common/typeguards";
|
|
6
|
+
import { requestValidationErrorName, validateRequest } from "./httpValidators";
|
|
7
|
+
const logger = getLogger("lensHttpHandler");
|
|
8
|
+
const lensHttpHandlerErrorName = "LensHttpHandlerError";
|
|
9
|
+
const lensHttpHandlerError = namedError(lensHttpHandlerErrorName);
|
|
10
|
+
const allowedResponseHeaders = [
|
|
11
|
+
"Accept-Ranges",
|
|
12
|
+
"Cache-Control",
|
|
13
|
+
"Content-Language",
|
|
14
|
+
"Content-Length",
|
|
15
|
+
"Content-Type",
|
|
16
|
+
"Date",
|
|
17
|
+
"ETag",
|
|
18
|
+
"Expires",
|
|
19
|
+
"Last-Modified",
|
|
20
|
+
"Location",
|
|
21
|
+
];
|
|
22
|
+
const requestHeadersToExclude = ["x-sc-lenses-remote-api-spec-id"];
|
|
23
|
+
export function createHttpUriHandler(lensState, sessionState, remoteApiSpecsClient, customLentFetchHandler) {
|
|
24
|
+
let allowlistPromise = undefined;
|
|
25
|
+
return createUriRequestProcessor({
|
|
26
|
+
uri: ["http://", "https://"],
|
|
27
|
+
lensState,
|
|
28
|
+
sessionState,
|
|
29
|
+
processRequest({ request, lens, reply, setCancellationHandler }) {
|
|
30
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
31
|
+
allowlistPromise = allowlistPromise !== null && allowlistPromise !== void 0 ? allowlistPromise : getAllowlist(remoteApiSpecsClient);
|
|
32
|
+
const allowlist = yield allowlistPromise;
|
|
33
|
+
handleHttpUriRequest(request, lens, reply, setCancellationHandler, allowlist, customLentFetchHandler);
|
|
34
|
+
});
|
|
35
|
+
},
|
|
36
|
+
processInternalError(error) {
|
|
37
|
+
logger.error(error);
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
function getAllowlist(remoteApiSpecsClient) {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
44
|
+
const result = yield remoteApiSpecsClient.getRemoteApiSpecs({});
|
|
45
|
+
if (!result.ok)
|
|
46
|
+
throw new Error("Failed getting Remote API specs.", { cause: result.unwrapErr() });
|
|
47
|
+
return (_b = (_a = result.unwrap().message) === null || _a === void 0 ? void 0 : _a.remoteApiSpecs) !== null && _b !== void 0 ? _b : [];
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function handleHttpUriRequest(request, lens, reply, setCancellationHandler, allowlist, customLensHttpHandler) {
|
|
51
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
52
|
+
try {
|
|
53
|
+
validateRequest(request, allowlist);
|
|
54
|
+
const { url, init } = mapLensToFetchRequest(request);
|
|
55
|
+
const abortController = new AbortController();
|
|
56
|
+
init.signal = abortController.signal;
|
|
57
|
+
setCancellationHandler(() => abortController.abort());
|
|
58
|
+
let response;
|
|
59
|
+
if (customLensHttpHandler) {
|
|
60
|
+
const handlerName = "lensHttpHandler";
|
|
61
|
+
try {
|
|
62
|
+
const { uri, identifier, method, metadata, data } = request;
|
|
63
|
+
const responsePromise = customLensHttpHandler(url, init, {
|
|
64
|
+
url: uri,
|
|
65
|
+
identifier,
|
|
66
|
+
method,
|
|
67
|
+
data,
|
|
68
|
+
headers: metadata,
|
|
69
|
+
lens,
|
|
70
|
+
});
|
|
71
|
+
if (!isPromise(responsePromise)) {
|
|
72
|
+
throw lensHttpHandlerError(`The '${handlerName}' callback provided to Camera Kit must return a Promise.`);
|
|
73
|
+
}
|
|
74
|
+
response = yield responsePromise;
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
error =
|
|
78
|
+
error instanceof Error && error.name === lensHttpHandlerErrorName
|
|
79
|
+
? error
|
|
80
|
+
: lensHttpHandlerError(`The '${handlerName}' callback provided to Camera Kit configuration failed.`, error);
|
|
81
|
+
throw error;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
response = yield fetch(url, init);
|
|
86
|
+
}
|
|
87
|
+
reply(yield mapFetchToLensResponse(response));
|
|
88
|
+
}
|
|
89
|
+
catch (error) {
|
|
90
|
+
if (error instanceof Error && error.name === lensHttpHandlerErrorName) {
|
|
91
|
+
logger.warn(error);
|
|
92
|
+
reply(getErrorResponse("LensHttpHandlerError", `The lens HTTP request handler provided to Camera Kit failed.`));
|
|
93
|
+
}
|
|
94
|
+
else if (error instanceof Error && error.name === requestValidationErrorName) {
|
|
95
|
+
logger.warn(error);
|
|
96
|
+
reply(getErrorResponse("RequestValidationError", error.message));
|
|
97
|
+
}
|
|
98
|
+
else {
|
|
99
|
+
logger.error(error);
|
|
100
|
+
reply(getErrorResponse("UnknownError", "An unknown error occurred."));
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
function getErrorResponse(errorType, message) {
|
|
106
|
+
return {
|
|
107
|
+
code: 400,
|
|
108
|
+
description: "",
|
|
109
|
+
contentType: "text/plain",
|
|
110
|
+
metadata: {
|
|
111
|
+
"x-camera-kit-error-type": errorType,
|
|
112
|
+
},
|
|
113
|
+
data: new TextEncoder().encode(message),
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
export function mapLensToFetchRequest({ uri, method, metadata, data }) {
|
|
117
|
+
const headers = new Headers(metadata);
|
|
118
|
+
for (const header of requestHeadersToExclude) {
|
|
119
|
+
headers.delete(header);
|
|
120
|
+
}
|
|
121
|
+
return {
|
|
122
|
+
url: uri,
|
|
123
|
+
init: {
|
|
124
|
+
headers: Object.fromEntries(headers.entries()),
|
|
125
|
+
body: method !== "GET" && method !== "HEAD" && method !== undefined ? data : undefined,
|
|
126
|
+
method,
|
|
127
|
+
},
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
export function mapFetchToLensResponse(response) {
|
|
131
|
+
var _a;
|
|
132
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
133
|
+
const metadata = {};
|
|
134
|
+
for (const allowedHeader of allowedResponseHeaders) {
|
|
135
|
+
const value = response.headers.get(allowedHeader);
|
|
136
|
+
if (value) {
|
|
137
|
+
metadata[allowedHeader.toLowerCase()] = value;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
code: response.status,
|
|
142
|
+
description: "",
|
|
143
|
+
contentType: ((_a = response.headers.get("Content-Type")) !== null && _a !== void 0 ? _a : ""),
|
|
144
|
+
metadata,
|
|
145
|
+
data: yield response.arrayBuffer(),
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
//# sourceMappingURL=httpUriHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpUriHandler.js","sourceRoot":"","sources":["../../../src/uri-handlers/internal-handlers/httpUriHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import type { RemoteApiSpecsClient } from \"../../clients/remoteApiSpecsClient\";\nimport type { Lens } from \"../../lens/Lens\";\nimport type { LensState } from \"../../session/lensState\";\nimport { getLogger } from \"../../logger/logger\";\nimport type { SessionState } from \"../../session/sessionState\";\nimport { namedError } from \"../../namedErrors\";\nimport type { CameraKitBootstrapConfiguration, LensHttpHandler } from \"../../configuration\";\nimport type { UriHandler, UriRequest, UriResponse } from \"../UriHandlers\";\nimport { createUriRequestProcessor } from \"../uriRequestProcessor\";\nimport type { RemoteApiSpec } from \"../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec\";\nimport { isPromise } from \"../../common/typeguards\";\nimport type { ContentType } from \"../../lens-core-module/generated-types\";\nimport { requestValidationErrorName, validateRequest } from \"./httpValidators\";\n\nconst logger = getLogger(\"lensHttpHandler\");\n\nconst lensHttpHandlerErrorName = \"LensHttpHandlerError\";\nconst lensHttpHandlerError = namedError(lensHttpHandlerErrorName);\n\ntype LensHttpRequestErrorType = \"UnknownError\" | \"LensHttpHandlerError\" | \"RequestValidationError\";\n\nconst allowedResponseHeaders = [\n \"Accept-Ranges\",\n \"Cache-Control\",\n \"Content-Language\",\n \"Content-Length\",\n \"Content-Type\",\n \"Date\",\n \"ETag\",\n \"Expires\",\n \"Last-Modified\",\n \"Location\",\n];\n\nconst requestHeadersToExclude = [\"x-sc-lenses-remote-api-spec-id\"];\n\n/**\n *\n * @internal\n *\n * @param lensState\n * @param sessionState\n * @param remoteApiSpecsClient\n * @param clientLentHttpRequestHandler\n * @returns\n */\nexport function createHttpUriHandler(\n lensState: LensState,\n sessionState: SessionState,\n remoteApiSpecsClient: RemoteApiSpecsClient,\n customLentFetchHandler: LensHttpHandler | undefined\n): UriHandler {\n let allowlistPromise: Promise<RemoteApiSpec[]> | undefined = undefined;\n\n return createUriRequestProcessor({\n uri: [\"http://\", \"https://\"],\n lensState,\n sessionState,\n async processRequest({ request, lens, reply, setCancellationHandler }) {\n allowlistPromise = allowlistPromise ?? getAllowlist(remoteApiSpecsClient);\n const allowlist = await allowlistPromise;\n handleHttpUriRequest(request, lens, reply, setCancellationHandler, allowlist, customLentFetchHandler);\n },\n processInternalError(error: Error) {\n // The expectation is that if an error occurs, it happens in our own implementation,\n // because app callbacks are wrapped with try..catch blocks.\n // Therefore, we would like to report this error.\n logger.error(error);\n },\n });\n}\n\nasync function getAllowlist(remoteApiSpecsClient: RemoteApiSpecsClient) {\n const result = await remoteApiSpecsClient.getRemoteApiSpecs({});\n if (!result.ok) throw new Error(\"Failed getting Remote API specs.\", { cause: result.unwrapErr() });\n return result.unwrap().message?.remoteApiSpecs ?? [];\n}\n\n/**\n *\n * @internal\n *\n * @param request\n * @param lens\n * @param reply\n * @param setCancellationHandler\n * @param allowlist\n * @param clientLensHttpRequestHandler\n */\nexport async function handleHttpUriRequest(\n request: UriRequest,\n lens: Lens,\n reply: (response: UriResponse) => void,\n setCancellationHandler: (fn: () => void) => void,\n allowlist: RemoteApiSpec[],\n customLensHttpHandler: LensHttpHandler | undefined\n) {\n try {\n validateRequest(request, allowlist);\n const { url, init } = mapLensToFetchRequest(request);\n\n // abort controller to abort fetch request when lens sends cancellation request\n const abortController = new AbortController();\n init.signal = abortController.signal;\n setCancellationHandler(() => abortController.abort());\n\n let response: Response;\n if (customLensHttpHandler) {\n const handlerName = \"lensHttpHandler\" satisfies keyof CameraKitBootstrapConfiguration;\n try {\n const { uri, identifier, method, metadata, data } = request;\n const responsePromise = customLensHttpHandler(url, init, {\n url: uri,\n identifier,\n method,\n data,\n headers: metadata,\n lens,\n });\n if (!isPromise(responsePromise)) {\n throw lensHttpHandlerError(\n `The '${handlerName}' callback provided to Camera Kit must return a Promise.`\n );\n }\n response = await responsePromise;\n } catch (error) {\n // NOTE: This error message will be displayed in browser only\n error =\n error instanceof Error && error.name === lensHttpHandlerErrorName\n ? error\n : lensHttpHandlerError(\n `The '${handlerName}' callback provided to Camera Kit configuration failed.`,\n error\n );\n throw error;\n }\n } else {\n response = await fetch(url, init);\n }\n\n reply(await mapFetchToLensResponse(response));\n } catch (error) {\n if (error instanceof Error && error.name === lensHttpHandlerErrorName) {\n // We do not report errors generated in partners's app code\n logger.warn(error);\n reply(\n getErrorResponse(\n \"LensHttpHandlerError\",\n // In case of an error in partner provided callback,\n // we just send a generic message to lens, which is common for all Camera Kit SDKs.\n `The lens HTTP request handler provided to Camera Kit failed.`\n )\n );\n } else if (error instanceof Error && error.name === requestValidationErrorName) {\n // We do not report validation error caused by lens code\n logger.warn(error);\n reply(\n getErrorResponse(\n \"RequestValidationError\",\n // NOTE: Validation errors sent to lens should be consistent with the other Camera Kit SDKs\n error.message\n )\n );\n } else {\n // We report error to our backend only in case of unknown error\n logger.error(error);\n reply(\n getErrorResponse(\n \"UnknownError\",\n // NOTE: we don't want to expose error details to lens\n \"An unknown error occurred.\"\n )\n );\n }\n }\n}\n\nfunction getErrorResponse(errorType: LensHttpRequestErrorType, message: string): UriResponse {\n return {\n code: 400,\n description: \"\",\n contentType: \"text/plain\",\n metadata: {\n \"x-camera-kit-error-type\": errorType,\n },\n data: new TextEncoder().encode(message),\n };\n}\n\n/**\n * @internal\n */\nexport function mapLensToFetchRequest({ uri, method, metadata, data }: UriRequest): { url: string; init: RequestInit } {\n const headers = new Headers(metadata);\n // remove internal headers that LensCore adds\n for (const header of requestHeadersToExclude) {\n headers.delete(header);\n }\n return {\n url: uri,\n init: {\n headers: Object.fromEntries(headers.entries()),\n body: method !== \"GET\" && (method as any) !== \"HEAD\" && method !== undefined ? data : undefined,\n method,\n },\n };\n}\n\n/**\n * @internal\n */\nexport async function mapFetchToLensResponse(response: Response): Promise<UriResponse> {\n const metadata: Record<string, string> = {};\n for (const allowedHeader of allowedResponseHeaders) {\n const value = response.headers.get(allowedHeader);\n if (value) {\n metadata[allowedHeader.toLowerCase()] = value;\n }\n }\n return {\n code: response.status,\n description: \"\",\n // Safety: At the time of writing any contentType value provided in the response object will be ignored:\n // eslint-disable-next-line max-len\n // https://github.sc-corp.net/Snapchat/LensCore/blob/722629250973cdf1064baef85d9360229f9dff76/Src/Scenarium/Primitives/RemoteServiceModule.cpp#L517-L533\n // But we still try to provide it with the correct value for consistency with mobile SDKs.\n contentType: (response.headers.get(\"Content-Type\") ?? \"\") as ContentType,\n metadata,\n data: await response.arrayBuffer(),\n };\n}\n"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { RemoteApiSpec, RemoteParameter } from "../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec";
|
|
2
|
+
import type { UriRequest } from "../UriHandlers";
|
|
3
|
+
export declare const requestValidationErrorName = "RequestValidationError";
|
|
4
|
+
export declare const requestValidationError: (message: string, cause?: unknown) => never;
|
|
5
|
+
export declare function validateRequest(request: UriRequest, specs: RemoteApiSpec[]): void;
|
|
6
|
+
export declare function validatePath(path: string, parameters: RemoteParameter[]): void;
|
|
7
|
+
export declare function validateHeaders(headers: Record<string, string>, parameters: RemoteParameter[]): void;
|
|
8
|
+
export declare function validateQuery(uri: string, parameters: RemoteParameter[]): void;
|
|
9
|
+
//# sourceMappingURL=httpValidators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpValidators.d.ts","sourceRoot":"","sources":["../../../src/uri-handlers/internal-handlers/httpValidators.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,+DAA+D,CAAC;AAIpH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAEjD,eAAO,MAAM,0BAA0B,2BAA2B,CAAC;AACnE,eAAO,MAAM,sBAAsB,6CAAyC,CAAC;AAE7E,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,QA2B1E;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,QA8CvE;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,EAAE,eAAe,EAAE,QA4B7F;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,QAgCvE"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isEmptyString } from "../../common/typeguards";
|
|
2
|
+
import { RemoteEndpoint_HttpRequestMethod } from "../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec";
|
|
3
|
+
import { RemoteParameter_ParameterLocation } from "../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec";
|
|
4
|
+
import { namedError } from "../../namedErrors";
|
|
5
|
+
export const requestValidationErrorName = "RequestValidationError";
|
|
6
|
+
export const requestValidationError = namedError(requestValidationErrorName);
|
|
7
|
+
export function validateRequest(request, specs) {
|
|
8
|
+
var _a, _b, _c;
|
|
9
|
+
for (const spec of specs) {
|
|
10
|
+
const url = `${spec.tlsRequired ? "https://" : "http://"}${spec.host}`;
|
|
11
|
+
if (!request.uri.startsWith(url))
|
|
12
|
+
continue;
|
|
13
|
+
const path = ((_a = request.uri.split(url)[1]) !== null && _a !== void 0 ? _a : "").replace(/^\//, "").replace(/\/$/, "");
|
|
14
|
+
for (const endpoint of spec.endpoints) {
|
|
15
|
+
const endpointPath = endpoint.path.replace(/^\//, "").replace(/\/$/, "");
|
|
16
|
+
if (!path.startsWith(endpointPath))
|
|
17
|
+
continue;
|
|
18
|
+
const method = (_b = RemoteEndpoint_HttpRequestMethod[request.method]) !== null && _b !== void 0 ? _b : RemoteEndpoint_HttpRequestMethod.UNRECOGNIZED;
|
|
19
|
+
if (!endpoint.methods.includes(method))
|
|
20
|
+
continue;
|
|
21
|
+
validatePath((_c = path.split(endpointPath)[1]) !== null && _c !== void 0 ? _c : "", endpoint.parameters);
|
|
22
|
+
validateHeaders(request.metadata, endpoint.parameters);
|
|
23
|
+
validateQuery(request.uri, endpoint.parameters);
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
throw requestValidationError("The request does not match any of the Remote API specifications.");
|
|
28
|
+
}
|
|
29
|
+
export function validatePath(path, parameters) {
|
|
30
|
+
const pathComponents = path.split("/").filter(Boolean);
|
|
31
|
+
let paramIndex = 0;
|
|
32
|
+
for (const param of parameters) {
|
|
33
|
+
if (param.location !== RemoteParameter_ParameterLocation.PATH)
|
|
34
|
+
continue;
|
|
35
|
+
const paramNameComponent = pathComponents[paramIndex];
|
|
36
|
+
const paramValueComponent = pathComponents[paramIndex + 1];
|
|
37
|
+
if (param.constant) {
|
|
38
|
+
if (paramNameComponent === param.name && paramValueComponent === param.defaultValue) {
|
|
39
|
+
paramIndex += 2;
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
throw requestValidationError(`Expected constant parameter '${param.name}' with value '${param.defaultValue}' ` +
|
|
43
|
+
`at position ${paramIndex}, but found '${paramNameComponent}' and '${paramValueComponent}'.`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else if (param.optional) {
|
|
47
|
+
if (paramNameComponent === param.name) {
|
|
48
|
+
paramIndex += 2;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
if (paramNameComponent === param.name && paramValueComponent !== undefined) {
|
|
53
|
+
paramIndex += 2;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
throw requestValidationError(`Expected parameter '${param.name}' with a value at position ${paramIndex}, ` +
|
|
57
|
+
`but found '${paramNameComponent}' and '${paramValueComponent}'.`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (paramIndex !== pathComponents.length) {
|
|
62
|
+
const invalidPath = pathComponents.slice(paramIndex).join("/");
|
|
63
|
+
throw requestValidationError(`Unexpected extra path components starting at position ${paramIndex}: '${invalidPath}'.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function validateHeaders(headers, parameters) {
|
|
67
|
+
for (const param of parameters) {
|
|
68
|
+
if (param.location !== RemoteParameter_ParameterLocation.HEADER)
|
|
69
|
+
continue;
|
|
70
|
+
const headerValue = headers[param.name];
|
|
71
|
+
if (param.constant) {
|
|
72
|
+
if (headerValue !== param.defaultValue) {
|
|
73
|
+
throw requestValidationError(`Expected constant header '${param.name}' with value '${param.defaultValue}', ` +
|
|
74
|
+
`but found '${headerValue !== null && headerValue !== void 0 ? headerValue : "undefined"}'.`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
else if (param.optional) {
|
|
78
|
+
if (headerValue != undefined && isEmptyString(headerValue)) {
|
|
79
|
+
throw requestValidationError(`Header '${param.name}' is present but empty. If provided, it should not be empty.`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
if (headerValue == undefined || isEmptyString(headerValue)) {
|
|
84
|
+
throw requestValidationError(`Required header '${param.name}' is missing or empty.`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
export function validateQuery(uri, parameters) {
|
|
90
|
+
const url = new URL(uri);
|
|
91
|
+
const queryParams = new URLSearchParams(url.search);
|
|
92
|
+
for (const param of parameters) {
|
|
93
|
+
if (param.location !== RemoteParameter_ParameterLocation.QUERY)
|
|
94
|
+
continue;
|
|
95
|
+
const paramValue = queryParams.get(param.name);
|
|
96
|
+
if (param.constant) {
|
|
97
|
+
if (paramValue !== param.defaultValue) {
|
|
98
|
+
throw requestValidationError(`Expected constant query parameter '${param.name}' with value '${param.defaultValue}', ` +
|
|
99
|
+
`but found '${paramValue !== null && paramValue !== void 0 ? paramValue : "undefined"}'.`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
else if (param.optional) {
|
|
103
|
+
if (paramValue != undefined && isEmptyString(paramValue)) {
|
|
104
|
+
throw requestValidationError(`Optional query parameter '${param.name}' is present but empty. ` +
|
|
105
|
+
`If provided, it should not be empty.`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
if (paramValue == undefined || isEmptyString(paramValue)) {
|
|
110
|
+
throw requestValidationError(`Required query parameter '${param.name}' is missing or empty.`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=httpValidators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"httpValidators.js","sourceRoot":"","sources":["../../../src/uri-handlers/internal-handlers/httpValidators.ts"],"names":[],"mappings":"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","sourcesContent":["import { isEmptyString } from \"../../common/typeguards\";\nimport type { RemoteApiSpec, RemoteParameter } from \"../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec\";\nimport { RemoteEndpoint_HttpRequestMethod } from \"../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec\";\nimport { RemoteParameter_ParameterLocation } from \"../../generated-proto/pb_schema/camera_kit/v3/remote_api_spec\";\nimport { namedError } from \"../../namedErrors\";\nimport type { UriRequest } from \"../UriHandlers\";\n\nexport const requestValidationErrorName = \"RequestValidationError\";\nexport const requestValidationError = namedError(requestValidationErrorName);\n\nexport function validateRequest(request: UriRequest, specs: RemoteApiSpec[]) {\n // 1. Given url, method and headers and spec:\n for (const spec of specs) {\n const url = `${spec.tlsRequired ? \"https://\" : \"http://\"}${spec.host}`;\n // 2. Check url starts with schema + the host. If yes trim that part and split by /\n if (!request.uri.startsWith(url)) continue;\n\n // 3. Split the rest by / and go for each part together with the path parameters.\n const path = (request.uri.split(url)[1] ?? \"\").replace(/^\\//, \"\").replace(/\\/$/, \"\");\n for (const endpoint of spec.endpoints) {\n const endpointPath = endpoint.path.replace(/^\\//, \"\").replace(/\\/$/, \"\");\n if (!path.startsWith(endpointPath)) continue;\n\n const method =\n RemoteEndpoint_HttpRequestMethod[request.method] ?? RemoteEndpoint_HttpRequestMethod.UNRECOGNIZED;\n if (!endpoint.methods.includes(method)) continue;\n\n validatePath(path.split(endpointPath)[1] ?? \"\", endpoint.parameters);\n validateHeaders(request.metadata, endpoint.parameters);\n validateQuery(request.uri, endpoint.parameters);\n // The request matches the current endpoint\n return;\n }\n }\n\n // The request does not match any of the endpoints\n throw requestValidationError(\"The request does not match any of the Remote API specifications.\");\n}\n\nexport function validatePath(path: string, parameters: RemoteParameter[]) {\n const pathComponents = path.split(\"/\").filter(Boolean);\n\n let paramIndex = 0;\n\n for (const param of parameters) {\n if (param.location !== RemoteParameter_ParameterLocation.PATH) continue;\n\n const paramNameComponent = pathComponents[paramIndex];\n const paramValueComponent = pathComponents[paramIndex + 1];\n\n if (param.constant) {\n // For constant parameters, the value must match the defaultValue\n if (paramNameComponent === param.name && paramValueComponent === param.defaultValue) {\n paramIndex += 2; // Move to the next parameter pair\n } else {\n throw requestValidationError(\n `Expected constant parameter '${param.name}' with value '${param.defaultValue}' ` +\n `at position ${paramIndex}, but found '${paramNameComponent}' and '${paramValueComponent}'.`\n );\n }\n } else if (param.optional) {\n if (paramNameComponent === param.name) {\n paramIndex += 2; // Move to the next parameter pair if optional parameter exists\n }\n // If optional and not present, continue without incrementing paramIndex\n } else {\n // For regular parameters, we just need to ensure a name/value pair exists\n if (paramNameComponent === param.name && paramValueComponent !== undefined) {\n paramIndex += 2; // Move to the next parameter pair\n } else {\n throw requestValidationError(\n `Expected parameter '${param.name}' with a value at position ${paramIndex}, ` +\n `but found '${paramNameComponent}' and '${paramValueComponent}'.`\n );\n }\n }\n }\n\n // After processing all parameters, there should be no extra path components\n if (paramIndex !== pathComponents.length) {\n const invalidPath = pathComponents.slice(paramIndex).join(\"/\");\n throw requestValidationError(\n `Unexpected extra path components starting at position ${paramIndex}: '${invalidPath}'.`\n );\n }\n}\n\nexport function validateHeaders(headers: Record<string, string>, parameters: RemoteParameter[]) {\n for (const param of parameters) {\n if (param.location !== RemoteParameter_ParameterLocation.HEADER) continue;\n\n const headerValue = headers[param.name];\n\n if (param.constant) {\n // For constant parameters, the header must exist and match defaultValue\n if (headerValue !== param.defaultValue) {\n throw requestValidationError(\n `Expected constant header '${param.name}' with value '${param.defaultValue}', ` +\n `but found '${headerValue ?? \"undefined\"}'.`\n );\n }\n } else if (param.optional) {\n // If optional, we only validate if the header exists\n if (headerValue != undefined && isEmptyString(headerValue)) {\n throw requestValidationError(\n `Header '${param.name}' is present but empty. If provided, it should not be empty.`\n );\n }\n } else {\n // For regular parameters, the header must exist and have a non-empty value\n if (headerValue == undefined || isEmptyString(headerValue)) {\n throw requestValidationError(`Required header '${param.name}' is missing or empty.`);\n }\n }\n }\n}\n\nexport function validateQuery(uri: string, parameters: RemoteParameter[]) {\n const url = new URL(uri);\n const queryParams = new URLSearchParams(url.search);\n for (const param of parameters) {\n if (param.location !== RemoteParameter_ParameterLocation.QUERY) continue;\n\n const paramValue = queryParams.get(param.name);\n\n if (param.constant) {\n // For constant parameters, the query parameter must exist and match defaultValue\n if (paramValue !== param.defaultValue) {\n throw requestValidationError(\n `Expected constant query parameter '${param.name}' with value '${param.defaultValue}', ` +\n `but found '${paramValue ?? \"undefined\"}'.`\n );\n }\n } else if (param.optional) {\n // If optional, validate only if the query parameter exists\n if (paramValue != undefined && isEmptyString(paramValue)) {\n throw requestValidationError(\n `Optional query parameter '${param.name}' is present but empty. ` +\n `If provided, it should not be empty.`\n );\n }\n } else {\n // For regular parameters, the query parameter must exist and have a non-empty value\n if (paramValue == undefined || isEmptyString(paramValue)) {\n throw requestValidationError(`Required query parameter '${param.name}' is missing or empty.`);\n }\n }\n }\n // All query parameters are valid\n}\n"]}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import type { LensRepository } from "
|
|
2
|
-
import type { Lens } from "
|
|
3
|
-
import type { LensState } from "
|
|
4
|
-
import type { SessionState } from "
|
|
5
|
-
import type { MetricsClient } from "
|
|
6
|
-
import type { UriHandler } from "
|
|
1
|
+
import type { LensRepository } from "../../lens/LensRepository";
|
|
2
|
+
import type { Lens } from "../../lens/Lens";
|
|
3
|
+
import type { LensState } from "../../session/lensState";
|
|
4
|
+
import type { SessionState } from "../../session/sessionState";
|
|
5
|
+
import type { MetricsClient } from "../../clients/metricsClient";
|
|
6
|
+
import type { UriHandler } from "../UriHandlers";
|
|
7
7
|
/**
|
|
8
8
|
* Status of a Remote API response.
|
|
9
9
|
*/
|
|
@@ -84,5 +84,5 @@ export declare const remoteApiServicesFactory: {
|
|
|
84
84
|
* Provides a URI handler that searches for a match within the provided services to handle Remote API requests,
|
|
85
85
|
* i.e., those whose URI starts with 'app://remote-api/performApiRequest'.
|
|
86
86
|
*/
|
|
87
|
-
export declare function
|
|
88
|
-
//# sourceMappingURL=
|
|
87
|
+
export declare function createRemoteApiUriHandler(registeredServices: RemoteApiService[], sessionState: SessionState, lensState: LensState, lensRepository: LensRepository, metrics: MetricsClient): UriHandler;
|
|
88
|
+
//# sourceMappingURL=remoteApiUriHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remoteApiUriHandler.d.ts","sourceRoot":"","sources":["../../../src/uri-handlers/internal-handlers/remoteApiUriHandler.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAG/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAIjE,OAAO,KAAK,EAAE,UAAU,EAAe,MAAM,gBAAgB,CAAC;AAyC9D;;GAEG;AACH,MAAM,MAAM,eAAe,GACrB,SAAS,GACT,YAAY,GACZ,YAAY,GACZ,cAAc,GACd,UAAU,GACV,SAAS,GACT,iBAAiB,GACjB,aAAa,GACb,WAAW,GACX,YAAY,CAAC;AAEnB;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACnC;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAC9B;;OAEG;IACH,MAAM,EAAE,eAAe,CAAC;IACxB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;CACrB;AAED;;GAEG;AACH,MAAM,MAAM,6BAA6B,GAAG,MAAM,IAAI,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,MAAM,uBAAuB,GAAG,CAClC,KAAK,EAAE,CAAC,QAAQ,EAAE,iBAAiB,KAAK,IAAI,KAC3C,6BAA6B,GAAG,IAAI,CAAC;AAE1C;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC7B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,iBAAiB,CAAC,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,GAAG,uBAAuB,GAAG,SAAS,CAAC;CACjG;AAED,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,EAAE,CAAC;AAEnD,eAAO,MAAM,wBAAwB;;;;CAGnC,CAAC;AAEH;;;GAGG;AACH,wBAAgB,yBAAyB,CACrC,kBAAkB,EAAE,gBAAgB,EAAE,EACtC,YAAY,EAAE,YAAY,EAC1B,SAAS,EAAE,SAAS,EACpB,cAAc,EAAE,cAAc,EAC9B,OAAO,EAAE,aAAa,GACvB,UAAU,CAiHZ"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { Injectable } from "@snap/ts-inject";
|
|
2
|
+
import { RemoteApiInfo } from "../../generated-proto/pb_schema/camera_kit/v3/features/remote_api_info";
|
|
3
|
+
import { ResponseCode, responseCodeToNumber, } from "../../generated-proto/pb_schema/lenses/remote_api/remote_api_service";
|
|
4
|
+
import { getLogger } from "../../logger/logger";
|
|
5
|
+
import { Count } from "../../metrics/operational/Count";
|
|
6
|
+
import { joinMetricNames } from "../../metrics/operational/Metric";
|
|
7
|
+
import { createUriRequestProcessor } from "../uriRequestProcessor";
|
|
8
|
+
import { extractSchemeAndRoute } from "../UriHandlers";
|
|
9
|
+
const logger = getLogger("RemoteApiServices");
|
|
10
|
+
const uriResponseOkCode = 200;
|
|
11
|
+
const apiResponseStatusHeader = ":sc_lens_api_status";
|
|
12
|
+
const apiBinaryContentType = "application/octet-stream";
|
|
13
|
+
const remoteApiInfoProtobufTypeUrl = "type.googleapis.com/com.snap.camerakit.v3.features.RemoteApiInfo";
|
|
14
|
+
const remoteApiUploadImageSpecId = "af3f69c8-2e62-441f-8b1c-d3956f7b336c";
|
|
15
|
+
const statusToResponseCodeMap = {
|
|
16
|
+
success: ResponseCode.SUCCESS,
|
|
17
|
+
redirected: ResponseCode.REDIRECTED,
|
|
18
|
+
badRequest: ResponseCode.BAD_REQUEST,
|
|
19
|
+
accessDenied: ResponseCode.ACCESS_DENIED,
|
|
20
|
+
notFound: ResponseCode.NOT_FOUND,
|
|
21
|
+
timeout: ResponseCode.TIMEOUT,
|
|
22
|
+
requestTooLarge: ResponseCode.REQUEST_TOO_LARGE,
|
|
23
|
+
serverError: ResponseCode.SERVER_ERROR,
|
|
24
|
+
cancelled: ResponseCode.CANCELLED,
|
|
25
|
+
proxyError: ResponseCode.PROXY_ERROR,
|
|
26
|
+
};
|
|
27
|
+
export const remoteApiServicesFactory = Injectable("remoteApiServices", () => {
|
|
28
|
+
const remoteApiServices = [];
|
|
29
|
+
return remoteApiServices;
|
|
30
|
+
});
|
|
31
|
+
export function createRemoteApiUriHandler(registeredServices, sessionState, lensState, lensRepository, metrics) {
|
|
32
|
+
const registeredServiceMap = new Map();
|
|
33
|
+
for (const service of registeredServices) {
|
|
34
|
+
const existingServices = registeredServiceMap.get(service.apiSpecId) || [];
|
|
35
|
+
registeredServiceMap.set(service.apiSpecId, [...existingServices, service]);
|
|
36
|
+
}
|
|
37
|
+
return createUriRequestProcessor({
|
|
38
|
+
uri: "app://remote-api/performApiRequest",
|
|
39
|
+
lensState,
|
|
40
|
+
sessionState,
|
|
41
|
+
createLensRequestState(_request, lens) {
|
|
42
|
+
var _a, _b;
|
|
43
|
+
return {
|
|
44
|
+
supportedSpecIds: new Set([
|
|
45
|
+
...((_b = (_a = lensRepository.getLensMetadata(lens.id)) === null || _a === void 0 ? void 0 : _a.featureMetadata) !== null && _b !== void 0 ? _b : [])
|
|
46
|
+
.filter((feature) => feature.typeUrl === remoteApiInfoProtobufTypeUrl)
|
|
47
|
+
.flatMap((any) => RemoteApiInfo.decode(any.value).apiSpecIds),
|
|
48
|
+
remoteApiUploadImageSpecId,
|
|
49
|
+
]),
|
|
50
|
+
};
|
|
51
|
+
},
|
|
52
|
+
processRequest({ request, reply, lens, setCancellationHandler, state }) {
|
|
53
|
+
var _a;
|
|
54
|
+
const { route } = extractSchemeAndRoute(request.uri);
|
|
55
|
+
const [specId, endpointIdWithQuery] = route.split("/").slice(2);
|
|
56
|
+
const [endpointId] = endpointIdWithQuery.split("?");
|
|
57
|
+
if (!(state === null || state === void 0 ? void 0 : state.supportedSpecIds.has(specId)))
|
|
58
|
+
return;
|
|
59
|
+
if (!registeredServiceMap.has(specId))
|
|
60
|
+
return;
|
|
61
|
+
const dimensions = { specId };
|
|
62
|
+
const reportSingleCount = (name) => {
|
|
63
|
+
metrics.setOperationalMetrics(Count.count(joinMetricNames(["lens", "remote-api", name]), 1, dimensions));
|
|
64
|
+
};
|
|
65
|
+
reportSingleCount("requests");
|
|
66
|
+
const remoteApiRequest = {
|
|
67
|
+
apiSpecId: specId,
|
|
68
|
+
body: request.data,
|
|
69
|
+
endpointId,
|
|
70
|
+
parameters: request.metadata,
|
|
71
|
+
};
|
|
72
|
+
for (const service of (_a = registeredServiceMap.get(specId)) !== null && _a !== void 0 ? _a : []) {
|
|
73
|
+
let requestHandler = undefined;
|
|
74
|
+
try {
|
|
75
|
+
requestHandler = service.getRequestHandler(remoteApiRequest, lens);
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
logger.warn("Client's Remote API request handler factory threw an error.", error);
|
|
79
|
+
}
|
|
80
|
+
if (requestHandler) {
|
|
81
|
+
reportSingleCount("handled-requests");
|
|
82
|
+
let cancellationHandler = undefined;
|
|
83
|
+
try {
|
|
84
|
+
cancellationHandler = requestHandler((response) => {
|
|
85
|
+
var _a;
|
|
86
|
+
reportSingleCount("responses");
|
|
87
|
+
const responseCode = (_a = statusToResponseCodeMap[response.status]) !== null && _a !== void 0 ? _a : ResponseCode.UNRECOGNIZED;
|
|
88
|
+
const uriResponse = {
|
|
89
|
+
code: uriResponseOkCode,
|
|
90
|
+
description: "",
|
|
91
|
+
contentType: apiBinaryContentType,
|
|
92
|
+
data: response.body,
|
|
93
|
+
metadata: Object.assign(Object.assign({}, response.metadata), { [apiResponseStatusHeader]: responseCodeToNumber(responseCode).toString() }),
|
|
94
|
+
};
|
|
95
|
+
reply(uriResponse);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
logger.warn("Client's Remote API request handler threw an error.", error);
|
|
100
|
+
}
|
|
101
|
+
if (typeof cancellationHandler === "function") {
|
|
102
|
+
setCancellationHandler(() => {
|
|
103
|
+
try {
|
|
104
|
+
cancellationHandler();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
logger.warn("Client's Remote API request cancellation handler threw an error.", error);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
processInternalError(error) {
|
|
116
|
+
logger.error(error);
|
|
117
|
+
metrics.setOperationalMetrics(Count.count(joinMetricNames(["lens", "remote-api", "errors"]), 1));
|
|
118
|
+
},
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=remoteApiUriHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"remoteApiUriHandler.js","sourceRoot":"","sources":["../../../src/uri-handlers/internal-handlers/remoteApiUriHandler.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable } from \"@snap/ts-inject\";\nimport { RemoteApiInfo } from \"../../generated-proto/pb_schema/camera_kit/v3/features/remote_api_info\";\nimport {\n ResponseCode,\n responseCodeToNumber,\n} from \"../../generated-proto/pb_schema/lenses/remote_api/remote_api_service\";\nimport type { LensRepository } from \"../../lens/LensRepository\";\nimport type { Lens } from \"../../lens/Lens\";\nimport type { LensState } from \"../../session/lensState\";\nimport type { SessionState } from \"../../session/sessionState\";\nimport { getLogger } from \"../../logger/logger\";\nimport type { EnumToPublicStringLiteralMap, ExcludeKeys } from \"../../common/types\";\nimport type { MetricsClient } from \"../../clients/metricsClient\";\nimport { Count } from \"../../metrics/operational/Count\";\nimport { joinMetricNames } from \"../../metrics/operational/Metric\";\nimport { createUriRequestProcessor } from \"../uriRequestProcessor\";\nimport type { UriHandler, UriResponse } from \"../UriHandlers\";\nimport { extractSchemeAndRoute } from \"../UriHandlers\";\n\n// NOTE: There's potential for overloads when reporting metrics if reporting is triggered on each frame,\n// (i.e., when the lens sends Remote API requests every frame).\n// As of now, this isn't a concern because src/metrics/operational/operationalMetricsReporter.ts aggregates\n// \"count\" metrics into a single metric within a batch, and the Remote API service currently\n// reports only \"count\" metrics. For instance, if 30 metrics with the same name are generated per second,\n// given the current bundle size of 100 operational metrics, there will be one metrics report approximately\n// every 3.3 seconds.\n// In the future, if we opt to report \"histogram\" or other metric types, they must be approached with caution:\n// either the operationalMetricsReporter should be enhanced to aggregate such metrics,\n// or the Remote API service should manage it directly.\n// Mobiles ticket: https://jira.sc-corp.net/browse/CAMKIT-3092\n\nconst logger = getLogger(\"RemoteApiServices\");\n\nconst uriResponseOkCode = 200;\nconst apiResponseStatusHeader = \":sc_lens_api_status\";\nconst apiBinaryContentType = \"application/octet-stream\";\nconst remoteApiInfoProtobufTypeUrl = \"type.googleapis.com/com.snap.camerakit.v3.features.RemoteApiInfo\";\nconst remoteApiUploadImageSpecId = \"af3f69c8-2e62-441f-8b1c-d3956f7b336c\";\n\nconst statusToResponseCodeMap: ExcludeKeys<\n EnumToPublicStringLiteralMap<typeof ResponseCode>,\n \"responseCodeUnset\" | \"unrecognized\"\n> = {\n success: ResponseCode.SUCCESS,\n redirected: ResponseCode.REDIRECTED,\n badRequest: ResponseCode.BAD_REQUEST,\n accessDenied: ResponseCode.ACCESS_DENIED,\n notFound: ResponseCode.NOT_FOUND,\n timeout: ResponseCode.TIMEOUT,\n requestTooLarge: ResponseCode.REQUEST_TOO_LARGE,\n serverError: ResponseCode.SERVER_ERROR,\n cancelled: ResponseCode.CANCELLED,\n proxyError: ResponseCode.PROXY_ERROR,\n // NOTE: This rule helps keep the public-facing RemoteApiStatus type consistent with the proto.\n // We prefer using a separate type for TypeDoc purposes.\n} satisfies Record<RemoteApiStatus, ResponseCode>;\n\n/**\n * Status of a Remote API response.\n */\nexport type RemoteApiStatus =\n | \"success\"\n | \"redirected\"\n | \"badRequest\"\n | \"accessDenied\"\n | \"notFound\"\n | \"timeout\"\n | \"requestTooLarge\"\n | \"serverError\"\n | \"cancelled\"\n | \"proxyError\";\n\n/**\n * Remote API request sent by a lens.\n */\nexport interface RemoteApiRequest {\n /**\n * Unique id of the remote API service specification.\n */\n apiSpecId: string;\n /**\n * Unique id of the remote API service endpoint requested by this request.\n */\n endpointId: string;\n /**\n * A map of named parameters associated with the request.\n */\n parameters: Record<string, string>;\n /**\n * Additional binary request payload.\n */\n body: ArrayBuffer;\n}\n\n/**\n * Remote API response to a request sent by a lens.\n */\nexport interface RemoteApiResponse {\n /**\n * Status of the response\n */\n status: RemoteApiStatus;\n /**\n * A map of named metadata associated with the response.\n */\n metadata: Record<string, string>;\n /**\n * Additional binary request payload.\n */\n body: ArrayBuffer;\n}\n\n/**\n * Represents a Remote API request cancellation handler function.\n */\nexport type RemoteApiCancelRequestHandler = () => void;\n\n/**\n * Represents a Remote API request handler function.\n * It is provided with a reply callback that must be invoked to send a response back to the lens.\n * The reply callback can be invoked multiple times if needed.\n * Additionally, the handler can return a cancellation callback, which is triggered when the lens cancels the request.\n */\nexport type RemoteApiRequestHandler = (\n reply: (response: RemoteApiResponse) => void\n) => RemoteApiCancelRequestHandler | void;\n\n/**\n * Service to handle a lens Remote API request.\n */\nexport interface RemoteApiService {\n /**\n * Remote API spec ID(s).\n */\n apiSpecId: string;\n\n /**\n * This method is called by Camera Kit when a lens triggers a Remote API request with a corresponding spec ID.\n * If the service can handle the request, the method returns a request handler; otherwise, it returns nothing.\n * @param request Remote API request object.\n * @param lens Lens that triggers the request.\n * @returns A request handler if applicable.\n */\n getRequestHandler(request: RemoteApiRequest, lens: Lens): RemoteApiRequestHandler | undefined;\n}\n\nexport type RemoteApiServices = RemoteApiService[];\n\nexport const remoteApiServicesFactory = Injectable(\"remoteApiServices\", () => {\n const remoteApiServices: RemoteApiServices = [];\n return remoteApiServices;\n});\n\n/**\n * Provides a URI handler that searches for a match within the provided services to handle Remote API requests,\n * i.e., those whose URI starts with 'app://remote-api/performApiRequest'.\n */\nexport function createRemoteApiUriHandler(\n registeredServices: RemoteApiService[],\n sessionState: SessionState,\n lensState: LensState,\n lensRepository: LensRepository,\n metrics: MetricsClient\n): UriHandler {\n // Groups services by spec ID for faster lookups.\n const registeredServiceMap = new Map<string, RemoteApiService[]>();\n for (const service of registeredServices) {\n const existingServices = registeredServiceMap.get(service.apiSpecId) || [];\n registeredServiceMap.set(service.apiSpecId, [...existingServices, service]);\n }\n\n return createUriRequestProcessor({\n uri: \"app://remote-api/performApiRequest\",\n lensState,\n sessionState,\n createLensRequestState(_request, lens) {\n return {\n supportedSpecIds: new Set([\n // Parse lens metadata to obtain supported Remote API specs.\n ...(lensRepository.getLensMetadata(lens.id)?.featureMetadata ?? [])\n .filter((feature) => feature.typeUrl === remoteApiInfoProtobufTypeUrl)\n .flatMap((any) => RemoteApiInfo.decode(any.value).apiSpecIds),\n // Also add remoteApiUploadImageSpecId as this spec should be available for all lenses.\n // See https://jira.sc-corp.net/browse/CAMKIT-6245.\n remoteApiUploadImageSpecId,\n ]),\n };\n },\n processRequest({ request, reply, lens, setCancellationHandler, state }) {\n // Extracts the spec ID and endpoint ID from the provided Remote API request URI.\n // The given URI is expected to conform to the following specification:\n // eslint-disable-next-line max-len\n // https://docs.google.com/document/d/18fbGYDhD2N_aMTe4ZLY4QKeCSoMeJuklG28TutDzLZc/edit#bookmark=id.p2y39gwgbm4g\n const { route } = extractSchemeAndRoute(request.uri);\n const [specId, endpointIdWithQuery] = route.split(\"/\").slice(2);\n const [endpointId] = endpointIdWithQuery.split(\"?\");\n\n // only handle requests for API spec ID that current lens supports\n if (!state?.supportedSpecIds.has(specId)) return;\n\n // only handle requests if we have a registered service for it\n if (!registeredServiceMap.has(specId)) return;\n\n const dimensions = { specId };\n const reportSingleCount = (name: string) => {\n metrics.setOperationalMetrics(\n Count.count(joinMetricNames([\"lens\", \"remote-api\", name]), 1, dimensions)\n );\n };\n\n reportSingleCount(\"requests\");\n\n const remoteApiRequest: RemoteApiRequest = {\n apiSpecId: specId,\n body: request.data,\n endpointId,\n parameters: request.metadata,\n };\n\n // Looks for the first Remote API request handler.\n for (const service of registeredServiceMap.get(specId) ?? []) {\n let requestHandler: RemoteApiRequestHandler | undefined = undefined;\n try {\n requestHandler = service.getRequestHandler(remoteApiRequest, lens);\n } catch (error) {\n logger.warn(\"Client's Remote API request handler factory threw an error.\", error);\n }\n\n if (requestHandler) {\n reportSingleCount(\"handled-requests\");\n\n let cancellationHandler: RemoteApiCancelRequestHandler | void = undefined;\n try {\n // Calls client's Remote API handler to process the request.\n cancellationHandler = requestHandler((response) => {\n reportSingleCount(\"responses\");\n\n const responseCode = statusToResponseCodeMap[response.status] ?? ResponseCode.UNRECOGNIZED;\n const uriResponse: UriResponse = {\n code: uriResponseOkCode,\n description: \"\",\n contentType: apiBinaryContentType,\n data: response.body,\n metadata: {\n ...response.metadata,\n [apiResponseStatusHeader]: responseCodeToNumber(responseCode).toString(),\n },\n };\n reply(uriResponse);\n });\n } catch (error) {\n logger.warn(\"Client's Remote API request handler threw an error.\", error);\n }\n\n if (typeof cancellationHandler === \"function\") {\n setCancellationHandler(() => {\n try {\n cancellationHandler!();\n } catch (error) {\n logger.warn(\"Client's Remote API request cancellation handler threw an error.\", error);\n }\n });\n }\n\n break;\n }\n }\n },\n processInternalError(error) {\n // The expectation is that if an error occurs, it happens in our own implementation,\n // because app callbacks are wrapped with try..catch blocks.\n // Therefore, we would like to report this error.\n logger.error(error);\n metrics.setOperationalMetrics(Count.count(joinMetricNames([\"lens\", \"remote-api\", \"errors\"]), 1));\n },\n });\n}\n"]}
|
|
@@ -2,21 +2,23 @@ import type { MetricsClient } from "../clients/metricsClient";
|
|
|
2
2
|
import type { LensKeyboard } from "../session/LensKeyboard";
|
|
3
3
|
import type { LensRepository } from "../lens/LensRepository";
|
|
4
4
|
import type { LensCore } from "../lens-core-module/lensCore";
|
|
5
|
-
import type {
|
|
5
|
+
import type { CameraKitConfiguration } from "../configuration";
|
|
6
|
+
import type { RemoteApiSpecsClient } from "../clients/remoteApiSpecsClient";
|
|
6
7
|
import type { UriHandlers } from "./UriHandlers";
|
|
8
|
+
import type { RemoteApiServices } from "./internal-handlers/remoteApiUriHandler";
|
|
7
9
|
/**
|
|
8
10
|
* Registers URI handlers within LensCore.
|
|
9
11
|
* @internal
|
|
10
12
|
*/
|
|
11
13
|
export declare const registerUriHandlers: {
|
|
12
|
-
(args_0:
|
|
14
|
+
(args_0: CameraKitConfiguration, args_1: LensCore, args_2: import("@snap/state-management").StateMachine<import("@snap/state-management").Action<"applyLens", {
|
|
13
15
|
lens: import("..").Lens;
|
|
14
16
|
launchData?: import("..").LensLaunchData | undefined;
|
|
15
17
|
}> | import("@snap/state-management").Action<"downloadComplete", import("..").Lens> | import("@snap/state-management").Action<"turnedOn", import("..").Lens> | import("@snap/state-management").Action<"resourcesLoaded", import("..").Lens> | import("@snap/state-management").Action<"firstFrameProcessed", import("..").Lens> | import("@snap/state-management").Action<"applyLensComplete", import("..").Lens> | import("@snap/state-management").Action<"applyLensFailed", {
|
|
16
18
|
error: import("../session/lensState").LensErrors;
|
|
17
19
|
lens: import("..").Lens;
|
|
18
|
-
}> | import("@snap/state-management").Action<"applyLensAborted", import("..").Lens> | import("@snap/state-management").Action<"removeLens", undefined> | import("@snap/state-management").Action<"turnedOff", import("..").Lens> | import("@snap/state-management").Action<"removeLensComplete", undefined> | import("@snap/state-management").Action<"removeLensFailed", Error>, import("@snap/state-management").State<"noLensApplied", undefined> | import("@snap/state-management").State<"applyingLens", import("..").Lens> | import("@snap/state-management").State<"lensApplied", import("..").Lens>>,
|
|
20
|
+
}> | import("@snap/state-management").Action<"applyLensAborted", import("..").Lens> | import("@snap/state-management").Action<"removeLens", undefined> | import("@snap/state-management").Action<"turnedOff", import("..").Lens> | import("@snap/state-management").Action<"removeLensComplete", undefined> | import("@snap/state-management").Action<"removeLensFailed", Error>, import("@snap/state-management").State<"noLensApplied", undefined> | import("@snap/state-management").State<"applyingLens", import("..").Lens> | import("@snap/state-management").State<"lensApplied", import("..").Lens>>, args_3: UriHandlers, args_4: LensKeyboard, args_5: RemoteApiServices, args_6: LensRepository, args_7: import("@snap/state-management").StateMachine<import("@snap/state-management").Action<"suspend", import("../session/CameraKitSession").CameraKitSession> | import("@snap/state-management").Action<"resume", import("../session/CameraKitSession").CameraKitSession> | import("@snap/state-management").Action<"destroy", undefined>, import("@snap/state-management").State<"inactive", undefined> | import("@snap/state-management").State<"active", import("../session/CameraKitSession").CameraKitSession> | import("@snap/state-management").State<"destroyed", undefined>>, args_8: MetricsClient, args_9: RemoteApiSpecsClient): void;
|
|
19
21
|
token: "registerUriHandlers";
|
|
20
|
-
dependencies: readonly ["lensCore", "lensState", "UriHandlers", "lensKeyboard", "remoteApiServices", "LensRepository", "sessionState", "metricsClient"];
|
|
22
|
+
dependencies: readonly ["configuration", "lensCore", "lensState", "UriHandlers", "lensKeyboard", "remoteApiServices", "LensRepository", "sessionState", "metricsClient", "remoteApiSpecsClient"];
|
|
21
23
|
};
|
|
22
24
|
//# sourceMappingURL=uriHandlersRegister.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"uriHandlersRegister.d.ts","sourceRoot":"","sources":["../../src/uri-handlers/uriHandlersRegister.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAI5D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAC7D,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAG5E,OAAO,KAAK,EAAE,WAAW,EAAe,MAAM,eAAe,CAAC;AAE9D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yCAAyC,CAAC;AAKjF;;;GAGG;AACH,eAAO,MAAM,mBAAmB;;;;;;;;;;CAsF/B,CAAC"}
|