@snap/camera-kit 0.7.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/LICENSE.md +6247 -0
- package/README.md +166 -0
- package/docs/html/.nojekyll +1 -0
- package/docs/html/assets/highlight.css +106 -0
- package/docs/html/assets/main.js +54 -0
- package/docs/html/assets/search.js +1 -0
- package/docs/html/assets/style.css +1225 -0
- package/docs/html/assets/widgets.png +0 -0
- package/docs/html/assets/widgets@2x.png +0 -0
- package/docs/html/classes/CameraKit.html +121 -0
- package/docs/html/classes/CameraKitSession.html +347 -0
- package/docs/html/classes/CameraKitSource.html +152 -0
- package/docs/html/classes/LensPerformanceMeasurement.html +115 -0
- package/docs/html/classes/LensPerformanceMetrics.html +76 -0
- package/docs/html/classes/LensRepository.html +171 -0
- package/docs/html/classes/LensSources.html +82 -0
- package/docs/html/classes/Transform2D.html +99 -0
- package/docs/html/classes/TypedCustomEvent.html +109 -0
- package/docs/html/classes/TypedEventTarget.html +146 -0
- package/docs/html/functions/Injectable.html +193 -0
- package/docs/html/functions/bootstrapCameraKit.html +158 -0
- package/docs/html/functions/createExtension.html +127 -0
- package/docs/html/functions/createImageSource.html +123 -0
- package/docs/html/functions/createMediaStreamSource.html +123 -0
- package/docs/html/functions/createUserMediaSource.html +127 -0
- package/docs/html/functions/createVideoSource.html +124 -0
- package/docs/html/functions/estimateLensPerformance.html +116 -0
- package/docs/html/functions/getRequiredBootstrapURLs.html +124 -0
- package/docs/html/functions/lensSourcesFactory.html +116 -0
- package/docs/html/functions/uriHandlersFactory.html +118 -0
- package/docs/html/index.html +208 -0
- package/docs/html/interfaces/CameraKitBootstrapConfiguration.html +132 -0
- package/docs/html/interfaces/CameraKitSourceSubscriber.html +121 -0
- package/docs/html/interfaces/ComputedFrameMetrics.html +70 -0
- package/docs/html/interfaces/CreateSessionOptions.html +77 -0
- package/docs/html/interfaces/EstimatedLensPerformance.html +78 -0
- package/docs/html/interfaces/Lens.html +115 -0
- package/docs/html/interfaces/LensSource.html +113 -0
- package/docs/html/interfaces/MediaStreamSourceOptions.html +65 -0
- package/docs/html/interfaces/UriCancelRequest.html +65 -0
- package/docs/html/interfaces/UriHandler.html +128 -0
- package/docs/html/interfaces/UriRequest.html +80 -0
- package/docs/html/interfaces/UriResponse.html +80 -0
- package/docs/html/interfaces/VideoSourceOptions.html +60 -0
- package/docs/html/modules.html +198 -0
- package/docs/html/types/AssetLoader.html +126 -0
- package/docs/html/types/AssetTiming.html +116 -0
- package/docs/html/types/BenchmarkError.html +107 -0
- package/docs/html/types/BootstrapError.html +110 -0
- package/docs/html/types/CacheKeyNotFoundError.html +107 -0
- package/docs/html/types/CameraKitDeviceInfo.html +114 -0
- package/docs/html/types/CameraKitSessionEventListener.html +109 -0
- package/docs/html/types/CameraKitSessionEvents.html +118 -0
- package/docs/html/types/CameraKitSourceError.html +107 -0
- package/docs/html/types/CameraKitSourceInfo.html +107 -0
- package/docs/html/types/CameraKitSourceOptions.html +113 -0
- package/docs/html/types/ConfigurationError.html +109 -0
- package/docs/html/types/Keyboard.html +196 -0
- package/docs/html/types/KeyboardEvents.html +109 -0
- package/docs/html/types/LegalError.html +107 -0
- package/docs/html/types/LensAssetError.html +109 -0
- package/docs/html/types/LensContentValidationError.html +107 -0
- package/docs/html/types/LensError.html +107 -0
- package/docs/html/types/LensExecutionError.html +114 -0
- package/docs/html/types/LensImagePickerError.html +110 -0
- package/docs/html/types/LensLaunchParams.html +109 -0
- package/docs/html/types/LensMetricsEvents.html +110 -0
- package/docs/html/types/LensPerformanceCluster.html +107 -0
- package/docs/html/types/LensView.html +119 -0
- package/docs/html/types/LensWait.html +111 -0
- package/docs/html/types/PersistentStoreError.html +109 -0
- package/docs/html/types/PlatformNotSupportedError.html +110 -0
- package/docs/html/types/PublicContainer.html +110 -0
- package/docs/html/types/RenderTarget.html +111 -0
- package/docs/html/types/Uri.html +107 -0
- package/docs/html/types/UriHandlers.html +109 -0
- package/docs/html/types/WebGLError.html +107 -0
- package/docs/html/variables/extensionRequestContext.html +109 -0
- package/docs/md/.nojekyll +1 -0
- package/docs/md/README.md +168 -0
- package/docs/md/classes/CameraKit.md +94 -0
- package/docs/md/classes/CameraKitSession.md +359 -0
- package/docs/md/classes/CameraKitSource.md +110 -0
- package/docs/md/classes/LensPerformanceMeasurement.md +77 -0
- package/docs/md/classes/LensPerformanceMetrics.md +37 -0
- package/docs/md/classes/LensRepository.md +145 -0
- package/docs/md/classes/LensSources.md +29 -0
- package/docs/md/classes/Transform2D.md +55 -0
- package/docs/md/classes/TypedCustomEvent.md +65 -0
- package/docs/md/classes/TypedEventTarget.md +103 -0
- package/docs/md/interfaces/CameraKitBootstrapConfiguration.md +106 -0
- package/docs/md/interfaces/CameraKitSourceSubscriber.md +55 -0
- package/docs/md/interfaces/ComputedFrameMetrics.md +29 -0
- package/docs/md/interfaces/CreateSessionOptions.md +35 -0
- package/docs/md/interfaces/EstimatedLensPerformance.md +38 -0
- package/docs/md/interfaces/Lens.md +84 -0
- package/docs/md/interfaces/LensSource.md +68 -0
- package/docs/md/interfaces/MediaStreamSourceOptions.md +22 -0
- package/docs/md/interfaces/UriCancelRequest.md +22 -0
- package/docs/md/interfaces/UriHandler.md +63 -0
- package/docs/md/interfaces/UriRequest.md +43 -0
- package/docs/md/interfaces/UriResponse.md +43 -0
- package/docs/md/interfaces/VideoSourceOptions.md +15 -0
- package/docs/md/modules.md +827 -0
- package/lib/CameraKit.d.ts +170 -0
- package/lib/CameraKit.js +145 -0
- package/lib/CameraKit.js.map +1 -0
- package/lib/__tests__/data.d.ts +9 -0
- package/lib/__tests__/data.js +50 -0
- package/lib/__tests__/data.js.map +1 -0
- package/lib/__tests__/deferred.d.ts +16 -0
- package/lib/__tests__/deferred.js +29 -0
- package/lib/__tests__/deferred.js.map +1 -0
- package/lib/__tests__/jest.matchers.d.ts +17 -0
- package/lib/__tests__/jest.matchers.js +67 -0
- package/lib/__tests__/jest.matchers.js.map +1 -0
- package/lib/assertPlatformSupported.d.ts +4 -0
- package/lib/assertPlatformSupported.js +10 -0
- package/lib/assertPlatformSupported.js.map +1 -0
- package/lib/benchmark/benchmarkGflops.d.ts +16 -0
- package/lib/benchmark/benchmarkGflops.js +129 -0
- package/lib/benchmark/benchmarkGflops.js.map +1 -0
- package/lib/benchmark/estimateLensPerformanceCluster.d.ts +33 -0
- package/lib/benchmark/estimateLensPerformanceCluster.js +48 -0
- package/lib/benchmark/estimateLensPerformanceCluster.js.map +1 -0
- package/lib/benchmark/webglUtils.d.ts +7 -0
- package/lib/benchmark/webglUtils.js +87 -0
- package/lib/benchmark/webglUtils.js.map +1 -0
- package/lib/bootstrapCameraKit.d.ts +96 -0
- package/lib/bootstrapCameraKit.js +204 -0
- package/lib/bootstrapCameraKit.js.map +1 -0
- package/lib/common/__mocks__/loadScript.d.ts +1 -0
- package/lib/common/__mocks__/loadScript.js +10 -0
- package/lib/common/__mocks__/loadScript.js.map +1 -0
- package/lib/common/assertions.d.ts +27 -0
- package/lib/common/assertions.js +39 -0
- package/lib/common/assertions.js.map +1 -0
- package/lib/common/cameraKitUserAgent.d.ts +34 -0
- package/lib/common/cameraKitUserAgent.js +216 -0
- package/lib/common/cameraKitUserAgent.js.map +1 -0
- package/lib/common/copyDefinedProperties.d.ts +13 -0
- package/lib/common/copyDefinedProperties.js +16 -0
- package/lib/common/copyDefinedProperties.js.map +1 -0
- package/lib/common/entries.d.ts +3 -0
- package/lib/common/entries.js +3 -0
- package/lib/common/entries.js.map +1 -0
- package/lib/common/errorHelpers.d.ts +10 -0
- package/lib/common/errorHelpers.js +24 -0
- package/lib/common/errorHelpers.js.map +1 -0
- package/lib/common/getFilename.d.ts +1 -0
- package/lib/common/getFilename.js +4 -0
- package/lib/common/getFilename.js.map +1 -0
- package/lib/common/index.d.ts +2 -0
- package/lib/common/index.js +3 -0
- package/lib/common/index.js.map +1 -0
- package/lib/common/loadScript.d.ts +1 -0
- package/lib/common/loadScript.js +11 -0
- package/lib/common/loadScript.js.map +1 -0
- package/lib/common/locale.d.ts +2 -0
- package/lib/common/locale.js +11 -0
- package/lib/common/locale.js.map +1 -0
- package/lib/common/localization.d.ts +43 -0
- package/lib/common/localization.js +43 -0
- package/lib/common/localization.js.map +1 -0
- package/lib/common/memoize.d.ts +8 -0
- package/lib/common/memoize.js +15 -0
- package/lib/common/memoize.js.map +1 -0
- package/lib/common/pageVisibility.d.ts +20 -0
- package/lib/common/pageVisibility.js +62 -0
- package/lib/common/pageVisibility.js.map +1 -0
- package/lib/common/time.d.ts +1 -0
- package/lib/common/time.js +2 -0
- package/lib/common/time.js.map +1 -0
- package/lib/common/typeguards.d.ts +53 -0
- package/lib/common/typeguards.js +92 -0
- package/lib/common/typeguards.js.map +1 -0
- package/lib/common/types.d.ts +10 -0
- package/lib/common/types.js +2 -0
- package/lib/common/types.js.map +1 -0
- package/lib/common/validate.d.ts +14 -0
- package/lib/common/validate.js +104 -0
- package/lib/common/validate.js.map +1 -0
- package/lib/configuration.d.ts +92 -0
- package/lib/configuration.js +36 -0
- package/lib/configuration.js.map +1 -0
- package/lib/configurationOverrides.d.ts +12 -0
- package/lib/configurationOverrides.js +41 -0
- package/lib/configurationOverrides.js.map +1 -0
- package/lib/dependency-injection/Container.d.ts +177 -0
- package/lib/dependency-injection/Container.js +160 -0
- package/lib/dependency-injection/Container.js.map +1 -0
- package/lib/dependency-injection/Injectable.d.ts +39 -0
- package/lib/dependency-injection/Injectable.js +18 -0
- package/lib/dependency-injection/Injectable.js.map +1 -0
- package/lib/dependency-injection/PartialContainer.d.ts +81 -0
- package/lib/dependency-injection/PartialContainer.js +85 -0
- package/lib/dependency-injection/PartialContainer.js.map +1 -0
- package/lib/dependency-injection/RootServices.d.ts +62 -0
- package/lib/dependency-injection/RootServices.js +2 -0
- package/lib/dependency-injection/RootServices.js.map +1 -0
- package/lib/dependency-injection/types.d.ts +56 -0
- package/lib/dependency-injection/types.js +2 -0
- package/lib/dependency-injection/types.js.map +1 -0
- package/lib/environment.json +1 -0
- package/lib/events/TypedCustomEvent.d.ts +10 -0
- package/lib/events/TypedCustomEvent.js +11 -0
- package/lib/events/TypedCustomEvent.js.map +1 -0
- package/lib/events/TypedEventTarget.d.ts +25 -0
- package/lib/events/TypedEventTarget.js +57 -0
- package/lib/events/TypedEventTarget.js.map +1 -0
- package/lib/events/scan.d.ts +15 -0
- package/lib/events/scan.js +46 -0
- package/lib/events/scan.js.map +1 -0
- package/lib/extensions/LensSources.d.ts +58 -0
- package/lib/extensions/LensSources.js +50 -0
- package/lib/extensions/LensSources.js.map +1 -0
- package/lib/extensions/UriHandlers.d.ts +54 -0
- package/lib/extensions/UriHandlers.js +93 -0
- package/lib/extensions/UriHandlers.js.map +1 -0
- package/lib/extensions/extensionRequestContext.d.ts +4 -0
- package/lib/extensions/extensionRequestContext.js +14 -0
- package/lib/extensions/extensionRequestContext.js.map +1 -0
- package/lib/generated-proto/blizzard/cameraKitEvents.d.ts +5603 -0
- package/lib/generated-proto/blizzard/cameraKitEvents.js +522 -0
- package/lib/generated-proto/blizzard/cameraKitEvents.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/business_events.d.ts +98 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/business_events.js +260 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/business_events.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/export.d.ts +543 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/export.js +429 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/export.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/legal_prompt.d.ts +100 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/legal_prompt.js +164 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/legal_prompt.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/lens.d.ts +395 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/lens.js +644 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/lens.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/operational_metrics.d.ts +185 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/operational_metrics.js +172 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/operational_metrics.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/ranking.d.ts +86 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/ranking.js +234 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/ranking.js.map +1 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/service.d.ts +854 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/service.js +629 -0
- package/lib/generated-proto/pb_schema/camera_kit/v3/service.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark.d.ts +86 -0
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark.js +185 -0
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark_name.d.ts +95 -0
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark_name.js +104 -0
- package/lib/generated-proto/pb_schema/cdp/cof/benchmark_name.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/circumstance_service.d.ts +10212 -0
- package/lib/generated-proto/pb_schema/cdp/cof/circumstance_service.js +1300 -0
- package/lib/generated-proto/pb_schema/cdp/cof/circumstance_service.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_request.d.ts +401 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_request.js +525 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_request.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_response.d.ts +1287 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_response.js +135 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_response.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_result.d.ts +4208 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_result.js +1053 -0
- package/lib/generated-proto/pb_schema/cdp/cof/config_result.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/debug_info.d.ts +102 -0
- package/lib/generated-proto/pb_schema/cdp/cof/debug_info.js +165 -0
- package/lib/generated-proto/pb_schema/cdp/cof/debug_info.js.map +1 -0
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.d.ts +8 -0
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.js +17 -0
- package/lib/generated-proto/pb_schema/cdp/cof/namespace.js.map +1 -0
- package/lib/generated-proto/pb_schema/common/ruid.d.ts +75 -0
- package/lib/generated-proto/pb_schema/common/ruid.js +96 -0
- package/lib/generated-proto/pb_schema/common/ruid.js.map +1 -0
- package/lib/generated-proto/pb_schema/common/value.d.ts +131 -0
- package/lib/generated-proto/pb_schema/common/value.js +204 -0
- package/lib/generated-proto/pb_schema/common/value.js.map +1 -0
- package/lib/generated-proto/pb_schema/google/api/annotations.d.ts +1 -0
- package/lib/generated-proto/pb_schema/google/api/annotations.js +9 -0
- package/lib/generated-proto/pb_schema/google/api/annotations.js.map +1 -0
- package/lib/generated-proto/pb_schema/google/api/http.d.ts +3636 -0
- package/lib/generated-proto/pb_schema/google/api/http.js +271 -0
- package/lib/generated-proto/pb_schema/google/api/http.js.map +1 -0
- package/lib/generated-proto/pb_schema/google/protobuf/any.d.ts +139 -0
- package/lib/generated-proto/pb_schema/google/protobuf/any.js +94 -0
- package/lib/generated-proto/pb_schema/google/protobuf/any.js.map +1 -0
- package/lib/generated-proto/pb_schema/google/protobuf/descriptor.d.ts +50968 -0
- package/lib/generated-proto/pb_schema/google/protobuf/descriptor.js +2962 -0
- package/lib/generated-proto/pb_schema/google/protobuf/descriptor.js.map +1 -0
- package/lib/generated-proto/pb_schema/google/protobuf/timestamp.d.ts +98 -0
- package/lib/generated-proto/pb_schema/google/protobuf/timestamp.js +82 -0
- package/lib/generated-proto/pb_schema/google/protobuf/timestamp.js.map +1 -0
- package/lib/generated-proto/pb_schema/google/protobuf/wrappers.d.ts +173 -0
- package/lib/generated-proto/pb_schema/google/protobuf/wrappers.js +332 -0
- package/lib/generated-proto/pb_schema/google/protobuf/wrappers.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/geocircle.d.ts +42 -0
- package/lib/generated-proto/pb_schema/lenses/geocircle.js +52 -0
- package/lib/generated-proto/pb_schema/lenses/geocircle.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/geopoint.d.ts +32 -0
- package/lib/generated-proto/pb_schema/lenses/geopoint.js +50 -0
- package/lib/generated-proto/pb_schema/lenses/geopoint.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/launch_params.d.ts +29 -0
- package/lib/generated-proto/pb_schema/lenses/launch_params.js +43 -0
- package/lib/generated-proto/pb_schema/lenses/launch_params.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/launchdata.d.ts +365 -0
- package/lib/generated-proto/pb_schema/lenses/launchdata.js +216 -0
- package/lib/generated-proto/pb_schema/lenses/launchdata.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/lures.d.ts +113 -0
- package/lib/generated-proto/pb_schema/lenses/lures.js +64 -0
- package/lib/generated-proto/pb_schema/lenses/lures.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/persistent_store.d.ts +29 -0
- package/lib/generated-proto/pb_schema/lenses/persistent_store.js +43 -0
- package/lib/generated-proto/pb_schema/lenses/persistent_store.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/snappable.d.ts +921 -0
- package/lib/generated-proto/pb_schema/lenses/snappable.js +954 -0
- package/lib/generated-proto/pb_schema/lenses/snappable.js.map +1 -0
- package/lib/generated-proto/pb_schema/lenses/user_data.d.ts +247 -0
- package/lib/generated-proto/pb_schema/lenses/user_data.js +362 -0
- package/lib/generated-proto/pb_schema/lenses/user_data.js.map +1 -0
- package/lib/handlers/HandlerChainBuilder.d.ts +95 -0
- package/lib/handlers/HandlerChainBuilder.js +187 -0
- package/lib/handlers/HandlerChainBuilder.js.map +1 -0
- package/lib/handlers/arrayBufferParsingHandler.d.ts +10 -0
- package/lib/handlers/arrayBufferParsingHandler.js +18 -0
- package/lib/handlers/arrayBufferParsingHandler.js.map +1 -0
- package/lib/handlers/batchingHandler.d.ts +25 -0
- package/lib/handlers/batchingHandler.js +79 -0
- package/lib/handlers/batchingHandler.js.map +1 -0
- package/lib/handlers/cameraKitServiceFetchHandlerFactory.d.ts +12 -0
- package/lib/handlers/cameraKitServiceFetchHandlerFactory.js +19 -0
- package/lib/handlers/cameraKitServiceFetchHandlerFactory.js.map +1 -0
- package/lib/handlers/debugHandler.d.ts +8 -0
- package/lib/handlers/debugHandler.js +27 -0
- package/lib/handlers/debugHandler.js.map +1 -0
- package/lib/handlers/defaultFetchHandler.d.ts +15 -0
- package/lib/handlers/defaultFetchHandler.js +29 -0
- package/lib/handlers/defaultFetchHandler.js.map +1 -0
- package/lib/handlers/headersModifyingFetchHandler.d.ts +8 -0
- package/lib/handlers/headersModifyingFetchHandler.js +13 -0
- package/lib/handlers/headersModifyingFetchHandler.js.map +1 -0
- package/lib/handlers/index.d.ts +2 -0
- package/lib/handlers/index.js +3 -0
- package/lib/handlers/index.js.map +1 -0
- package/lib/handlers/mappingHandler.d.ts +15 -0
- package/lib/handlers/mappingHandler.js +65 -0
- package/lib/handlers/mappingHandler.js.map +1 -0
- package/lib/handlers/noCorsRetryingFetchHandler.d.ts +48 -0
- package/lib/handlers/noCorsRetryingFetchHandler.js +94 -0
- package/lib/handlers/noCorsRetryingFetchHandler.js.map +1 -0
- package/lib/handlers/persistingHandler.d.ts +14 -0
- package/lib/handlers/persistingHandler.js +71 -0
- package/lib/handlers/persistingHandler.js.map +1 -0
- package/lib/handlers/rateLimitingHandler.d.ts +20 -0
- package/lib/handlers/rateLimitingHandler.js +43 -0
- package/lib/handlers/rateLimitingHandler.js.map +1 -0
- package/lib/handlers/requestStateEmittingHandler.d.ts +29 -0
- package/lib/handlers/requestStateEmittingHandler.js +43 -0
- package/lib/handlers/requestStateEmittingHandler.js.map +1 -0
- package/lib/handlers/responseCachingHandler.d.ts +27 -0
- package/lib/handlers/responseCachingHandler.js +94 -0
- package/lib/handlers/responseCachingHandler.js.map +1 -0
- package/lib/handlers/retryingHandler.d.ts +37 -0
- package/lib/handlers/retryingHandler.js +73 -0
- package/lib/handlers/retryingHandler.js.map +1 -0
- package/lib/handlers/timeoutHandler.d.ts +18 -0
- package/lib/handlers/timeoutHandler.js +30 -0
- package/lib/handlers/timeoutHandler.js.map +1 -0
- package/lib/index.d.ts +33 -0
- package/lib/index.js +32 -0
- package/lib/index.js.map +1 -0
- package/lib/legal/legalPrompt.d.ts +17 -0
- package/lib/legal/legalPrompt.js +144 -0
- package/lib/legal/legalPrompt.js.map +1 -0
- package/lib/legal/legalState.d.ts +50 -0
- package/lib/legal/legalState.js +149 -0
- package/lib/legal/legalState.js.map +1 -0
- package/lib/lens/Lens.d.ts +71 -0
- package/lib/lens/Lens.js +63 -0
- package/lib/lens/Lens.js.map +1 -0
- package/lib/lens/LensLaunchParams.d.ts +19 -0
- package/lib/lens/LensLaunchParams.js +38 -0
- package/lib/lens/LensLaunchParams.js.map +1 -0
- package/lib/lens/LensPersistenceStore.d.ts +7 -0
- package/lib/lens/LensPersistenceStore.js +20 -0
- package/lib/lens/LensPersistenceStore.js.map +1 -0
- package/lib/lens/LensRepository.d.ts +134 -0
- package/lib/lens/LensRepository.js +239 -0
- package/lib/lens/LensRepository.js.map +1 -0
- package/lib/lens/assets/LensAssetRepository.d.ts +66 -0
- package/lib/lens/assets/LensAssetRepository.js +179 -0
- package/lib/lens/assets/LensAssetRepository.js.map +1 -0
- package/lib/lens/assets/LensAssetsProvider.d.ts +21 -0
- package/lib/lens/assets/LensAssetsProvider.js +41 -0
- package/lib/lens/assets/LensAssetsProvider.js.map +1 -0
- package/lib/lens/assets/deviceDependentAssetLoader.d.ts +11 -0
- package/lib/lens/assets/deviceDependentAssetLoader.js +58 -0
- package/lib/lens/assets/deviceDependentAssetLoader.js.map +1 -0
- package/lib/lens/assets/remoteMediaAssetLoaderFactory.d.ts +10 -0
- package/lib/lens/assets/remoteMediaAssetLoaderFactory.js +26 -0
- package/lib/lens/assets/remoteMediaAssetLoaderFactory.js.map +1 -0
- package/lib/lens/assets/staticAssetLoader.d.ts +10 -0
- package/lib/lens/assets/staticAssetLoader.js +24 -0
- package/lib/lens/assets/staticAssetLoader.js.map +1 -0
- package/lib/lens/index.d.ts +7 -0
- package/lib/lens/index.js +7 -0
- package/lib/lens/index.js.map +1 -0
- package/lib/lens/lensEnvelopeUtil.d.ts +5 -0
- package/lib/lens/lensEnvelopeUtil.js +19 -0
- package/lib/lens/lensEnvelopeUtil.js.map +1 -0
- package/lib/lens/lensHttpUtil.d.ts +4 -0
- package/lib/lens/lensHttpUtil.js +30 -0
- package/lib/lens/lensHttpUtil.js.map +1 -0
- package/lib/lens-client-interface/exif.d.ts +20 -0
- package/lib/lens-client-interface/exif.js +61 -0
- package/lib/lens-client-interface/exif.js.map +1 -0
- package/lib/lens-client-interface/imagePicker.d.ts +7 -0
- package/lib/lens-client-interface/imagePicker.js +128 -0
- package/lib/lens-client-interface/imagePicker.js.map +1 -0
- package/lib/lens-client-interface/lensClientInterface.d.ts +13 -0
- package/lib/lens-client-interface/lensClientInterface.js +30 -0
- package/lib/lens-client-interface/lensClientInterface.js.map +1 -0
- package/lib/lens-core-module/generated-types.d.ts +426 -0
- package/lib/lens-core-module/generated-types.js +2 -0
- package/lib/lens-core-module/generated-types.js.map +1 -0
- package/lib/lens-core-module/index.d.ts +2 -0
- package/lib/lens-core-module/index.js +3 -0
- package/lib/lens-core-module/index.js.map +1 -0
- package/lib/lens-core-module/loader/index.d.ts +1 -0
- package/lib/lens-core-module/loader/index.js +2 -0
- package/lib/lens-core-module/loader/index.js.map +1 -0
- package/lib/lens-core-module/loader/lensCoreFactory.d.ts +30 -0
- package/lib/lens-core-module/loader/lensCoreFactory.js +121 -0
- package/lib/lens-core-module/loader/lensCoreFactory.js.map +1 -0
- package/lib/lensCoreWasmVersions.json +5 -0
- package/lib/logger/errorLoggingDecorator.d.ts +9 -0
- package/lib/logger/errorLoggingDecorator.js +32 -0
- package/lib/logger/errorLoggingDecorator.js.map +1 -0
- package/lib/logger/logEntries.d.ts +15 -0
- package/lib/logger/logEntries.js +14 -0
- package/lib/logger/logEntries.js.map +1 -0
- package/lib/logger/logger.d.ts +35 -0
- package/lib/logger/logger.js +48 -0
- package/lib/logger/logger.js.map +1 -0
- package/lib/logger/registerLogEntriesSubscriber.d.ts +14 -0
- package/lib/logger/registerLogEntriesSubscriber.js +23 -0
- package/lib/logger/registerLogEntriesSubscriber.js.map +1 -0
- package/lib/media-sources/CameraKitSource.d.ts +88 -0
- package/lib/media-sources/CameraKitSource.js +140 -0
- package/lib/media-sources/CameraKitSource.js.map +1 -0
- package/lib/media-sources/FunctionSource.d.ts +30 -0
- package/lib/media-sources/FunctionSource.js +132 -0
- package/lib/media-sources/FunctionSource.js.map +1 -0
- package/lib/media-sources/ImageSource.d.ts +13 -0
- package/lib/media-sources/ImageSource.js +28 -0
- package/lib/media-sources/ImageSource.js.map +1 -0
- package/lib/media-sources/MediaStreamSource.d.ts +41 -0
- package/lib/media-sources/MediaStreamSource.js +146 -0
- package/lib/media-sources/MediaStreamSource.js.map +1 -0
- package/lib/media-sources/VideoSource.d.ts +21 -0
- package/lib/media-sources/VideoSource.js +38 -0
- package/lib/media-sources/VideoSource.js.map +1 -0
- package/lib/metrics/businessEventsReporter.d.ts +37 -0
- package/lib/metrics/businessEventsReporter.js +160 -0
- package/lib/metrics/businessEventsReporter.js.map +1 -0
- package/lib/metrics/metricsEventTarget.d.ts +41 -0
- package/lib/metrics/metricsEventTarget.js +11 -0
- package/lib/metrics/metricsEventTarget.js.map +1 -0
- package/lib/metrics/metricsHandler.d.ts +9 -0
- package/lib/metrics/metricsHandler.js +13 -0
- package/lib/metrics/metricsHandler.js.map +1 -0
- package/lib/metrics/operationalMetricsReporter.d.ts +52 -0
- package/lib/metrics/operationalMetricsReporter.js +108 -0
- package/lib/metrics/operationalMetricsReporter.js.map +1 -0
- package/lib/metrics/reporters/reportBenchmarks.d.ts +10 -0
- package/lib/metrics/reporters/reportBenchmarks.js +29 -0
- package/lib/metrics/reporters/reportBenchmarks.js.map +1 -0
- package/lib/metrics/reporters/reportGlobalException.d.ts +19 -0
- package/lib/metrics/reporters/reportGlobalException.js +68 -0
- package/lib/metrics/reporters/reportGlobalException.js.map +1 -0
- package/lib/metrics/reporters/reportHttpMetrics.d.ts +17 -0
- package/lib/metrics/reporters/reportHttpMetrics.js +92 -0
- package/lib/metrics/reporters/reportHttpMetrics.js.map +1 -0
- package/lib/metrics/reporters/reportLegalState.d.ts +15 -0
- package/lib/metrics/reporters/reportLegalState.js +34 -0
- package/lib/metrics/reporters/reportLegalState.js.map +1 -0
- package/lib/metrics/reporters/reportLensAndAssetDownload.d.ts +38 -0
- package/lib/metrics/reporters/reportLensAndAssetDownload.js +88 -0
- package/lib/metrics/reporters/reportLensAndAssetDownload.js.map +1 -0
- package/lib/metrics/reporters/reportLensValidationFailed.d.ts +20 -0
- package/lib/metrics/reporters/reportLensValidationFailed.js +24 -0
- package/lib/metrics/reporters/reportLensValidationFailed.js.map +1 -0
- package/lib/metrics/reporters/reportLensView.d.ts +36 -0
- package/lib/metrics/reporters/reportLensView.js +101 -0
- package/lib/metrics/reporters/reportLensView.js.map +1 -0
- package/lib/metrics/reporters/reportLensWait.d.ts +33 -0
- package/lib/metrics/reporters/reportLensWait.js +56 -0
- package/lib/metrics/reporters/reportLensWait.js.map +1 -0
- package/lib/metrics/reporters/reportSessionException.d.ts +17 -0
- package/lib/metrics/reporters/reportSessionException.js +12 -0
- package/lib/metrics/reporters/reportSessionException.js.map +1 -0
- package/lib/metrics/reporters/reportUserSession.d.ts +14 -0
- package/lib/metrics/reporters/reportUserSession.js +67 -0
- package/lib/metrics/reporters/reportUserSession.js.map +1 -0
- package/lib/metrics/reporters/reporters.d.ts +44 -0
- package/lib/metrics/reporters/reporters.js +33 -0
- package/lib/metrics/reporters/reporters.js.map +1 -0
- package/lib/namedErrors.d.ts +107 -0
- package/lib/namedErrors.js +56 -0
- package/lib/namedErrors.js.map +1 -0
- package/lib/persistence/ExpiringPersistence.d.ts +20 -0
- package/lib/persistence/ExpiringPersistence.js +58 -0
- package/lib/persistence/ExpiringPersistence.js.map +1 -0
- package/lib/persistence/IndexedDBPersistence.d.ts +47 -0
- package/lib/persistence/IndexedDBPersistence.js +180 -0
- package/lib/persistence/IndexedDBPersistence.js.map +1 -0
- package/lib/persistence/Persistence.d.ts +25 -0
- package/lib/persistence/Persistence.js +10 -0
- package/lib/persistence/Persistence.js.map +1 -0
- package/lib/remote-configuration/cofHandler.d.ts +21 -0
- package/lib/remote-configuration/cofHandler.js +75 -0
- package/lib/remote-configuration/cofHandler.js.map +1 -0
- package/lib/remote-configuration/remoteConfiguration.d.ts +13 -0
- package/lib/remote-configuration/remoteConfiguration.js +43 -0
- package/lib/remote-configuration/remoteConfiguration.js.map +1 -0
- package/lib/session/CameraKitSession.d.ts +252 -0
- package/lib/session/CameraKitSession.js +439 -0
- package/lib/session/CameraKitSession.js.map +1 -0
- package/lib/session/CameraKitSessionEvents.d.ts +33 -0
- package/lib/session/CameraKitSessionEvents.js +21 -0
- package/lib/session/CameraKitSessionEvents.js.map +1 -0
- package/lib/session/LensKeyboard.d.ts +89 -0
- package/lib/session/LensKeyboard.js +95 -0
- package/lib/session/LensKeyboard.js.map +1 -0
- package/lib/session/LensPerformanceMeasurement.d.ts +55 -0
- package/lib/session/LensPerformanceMeasurement.js +91 -0
- package/lib/session/LensPerformanceMeasurement.js.map +1 -0
- package/lib/session/LensPerformanceMetrics.d.ts +31 -0
- package/lib/session/LensPerformanceMetrics.js +58 -0
- package/lib/session/LensPerformanceMetrics.js.map +1 -0
- package/lib/session/index.d.ts +1 -0
- package/lib/session/index.js +2 -0
- package/lib/session/index.js.map +1 -0
- package/lib/session/lensState.d.ts +29 -0
- package/lib/session/lensState.js +160 -0
- package/lib/session/lensState.js.map +1 -0
- package/lib/session/sessionState.d.ts +10 -0
- package/lib/session/sessionState.js +12 -0
- package/lib/session/sessionState.js.map +1 -0
- package/lib/transforms/Transform2D.d.ts +17 -0
- package/lib/transforms/Transform2D.js +18 -0
- package/lib/transforms/Transform2D.js.map +1 -0
- package/lib/transforms/index.d.ts +1 -0
- package/lib/transforms/index.js +2 -0
- package/lib/transforms/index.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { copyDefinedProperties } from "./common/copyDefinedProperties";
|
|
2
|
+
import { getConfigurationOverrides } from "./configurationOverrides";
|
|
3
|
+
import { Injectable } from "./dependency-injection/Injectable";
|
|
4
|
+
/**
|
|
5
|
+
* Defaults are provided for runtime configuration and any optional bootstrap configuration properties which require
|
|
6
|
+
* defaults.
|
|
7
|
+
*/
|
|
8
|
+
const defaultConfiguration = {
|
|
9
|
+
// If the applications doesn't provide performance data (e.g. via estimateLensPerformance), we'll use 0 to indicate
|
|
10
|
+
// no performance estimation occurred. This is indicative of typical performance-targeting logic, which often
|
|
11
|
+
// defaults to the lowest-tier experience in the absense of performance cluster data.
|
|
12
|
+
lensPerformance: { cluster: 0, benchmarks: [], webglRendererInfo: "unknown" },
|
|
13
|
+
logger: "noop",
|
|
14
|
+
logLevel: "info",
|
|
15
|
+
shouldUseWorker: true,
|
|
16
|
+
};
|
|
17
|
+
/** @internal */
|
|
18
|
+
export const configurationToken = "configuration";
|
|
19
|
+
/** @internal */
|
|
20
|
+
export const createCameraKitConfigurationFactory = (configuration) => {
|
|
21
|
+
// always leave debug mode warning about overrides in console
|
|
22
|
+
const overrides = getConfigurationOverrides();
|
|
23
|
+
if (overrides) {
|
|
24
|
+
console.warn("Configuration overrides applied", overrides);
|
|
25
|
+
}
|
|
26
|
+
return Injectable(configurationToken, () => {
|
|
27
|
+
// We'll ensure that we handle errors on any Promises passed as config values, otherwise we either must
|
|
28
|
+
// handle them separately wherever they're used, or rejections would go unhandled.
|
|
29
|
+
const safeConfig = Object.assign(Object.assign({}, configuration), { lensPerformance: configuration.lensPerformance instanceof Promise
|
|
30
|
+
? // Safety: defaultConfiguration.lensPerformance is defined (it's hardcoded above).
|
|
31
|
+
configuration.lensPerformance.catch(() => defaultConfiguration.lensPerformance)
|
|
32
|
+
: configuration.lensPerformance });
|
|
33
|
+
return Object.assign(Object.assign(Object.assign({}, defaultConfiguration), copyDefinedProperties(safeConfig)), copyDefinedProperties(overrides !== null && overrides !== void 0 ? overrides : {}));
|
|
34
|
+
});
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=configuration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configuration.js","sourceRoot":"","sources":["../src/configuration.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,yBAAyB,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,UAAU,EAAE,MAAM,mCAAmC,CAAC;AAU/D;;;GAGG;AACH,MAAM,oBAAoB,GAAmF;IACzG,mHAAmH;IACnH,6GAA6G;IAC7G,qFAAqF;IACrF,eAAe,EAAE,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,iBAAiB,EAAE,SAAS,EAAE;IAC7E,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,MAAM;IAChB,eAAe,EAAE,IAAI;CACxB,CAAC;AAwFF,gBAAgB;AAChB,MAAM,CAAC,MAAM,kBAAkB,GAAG,eAAe,CAAC;AAElD,gBAAgB;AAChB,MAAM,CAAC,MAAM,mCAAmC,GAAG,CAAC,aAA8C,EAAE,EAAE;IAClG,6DAA6D;IAC7D,MAAM,SAAS,GAAG,yBAAyB,EAAE,CAAC;IAC9C,IAAI,SAAS,EAAE;QACX,OAAO,CAAC,IAAI,CAAC,iCAAiC,EAAE,SAAS,CAAC,CAAC;KAC9D;IACD,OAAO,UAAU,CACb,kBAAkB,EAClB,GAA2B,EAAE;QACzB,uGAAuG;QACvG,kFAAkF;QAClF,MAAM,UAAU,mCACT,aAAa,KAChB,eAAe,EACX,aAAa,CAAC,eAAe,YAAY,OAAO;gBAC5C,CAAC,CAAC,kFAAkF;oBAClF,aAAa,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,oBAAoB,CAAC,eAAgB,CAAC;gBAClF,CAAC,CAAC,aAAa,CAAC,eAAe,GAC1C,CAAC;QACF,qDACO,oBAAoB,GACpB,qBAAqB,CAAC,UAAU,CAAC,GACjC,qBAAqB,CAAC,SAAS,aAAT,SAAS,cAAT,SAAS,GAAI,EAAE,CAAC,EAC3C;IACN,CAAC,CACJ,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { EstimatedLensPerformance } from \"./benchmark/estimateLensPerformanceCluster\";\nimport { copyDefinedProperties } from \"./common/copyDefinedProperties\";\nimport { getConfigurationOverrides } from \"./configurationOverrides\";\nimport { Injectable } from \"./dependency-injection/Injectable\";\nimport { LogLevelName } from \"./logger/logger\";\n\n/**\n * From T, pick the set of properties whose values are optional. Create a new type containing only those properties.\n */\ntype PickOptionals<T> = {\n [K in keyof T as T[K] extends Exclude<T[K], undefined> ? never : K]: T[K];\n};\n\n/**\n * Defaults are provided for runtime configuration and any optional bootstrap configuration properties which require\n * defaults.\n */\nconst defaultConfiguration: CameraKitRuntimeConfiguration & PickOptionals<CameraKitBootstrapConfiguration> = {\n // If the applications doesn't provide performance data (e.g. via estimateLensPerformance), we'll use 0 to indicate\n // no performance estimation occurred. This is indicative of typical performance-targeting logic, which often\n // defaults to the lowest-tier experience in the absense of performance cluster data.\n lensPerformance: { cluster: 0, benchmarks: [], webglRendererInfo: \"unknown\" },\n logger: \"noop\",\n logLevel: \"info\",\n shouldUseWorker: true,\n};\n\ninterface CameraKitRuntimeConfiguration {\n lensPerformance: EstimatedLensPerformance | Promise<EstimatedLensPerformance>;\n logger: \"noop\" | \"console\";\n logLevel: LogLevelName;\n shouldUseWorker: boolean;\n}\n\n/**\n * Configuration which must be provided when calling {@link bootstrapCameraKit}. These values are used to create various\n * CameraKit components.\n *\n * @category Bootstrapping and Configuration\n */\nexport interface CameraKitBootstrapConfiguration {\n /**\n * Long-lived token granting your application access to CameraKit APIs. This is found in the SnapKit Dev Portal,\n * where it's called the API Token.\n */\n apiToken: string;\n\n /**\n * Determine where to print CameraKit log messages. By default no logs will be printed.\n *\n * CameraKit emits log messages to help diagnose and root cause issues that may occur during the development of a\n * host application. The printing of these can be controlled via the following\n * options:\n * - `noop`: log messages are ignored.\n * - `console`: log messages are printed to console.\n */\n logger?: \"noop\" | \"console\";\n\n /**\n * Log only if a logged entry level is greater than or equal to this level. Here is the order of levels:\n * error > warn > log = info > debug. Default value is \"info\".\n */\n logLevel?: LogLevelName;\n\n /**\n * Some lenses may decide to modify their behavior based on the performance of the current environment. If you are\n * using such lenses, providing an estimation of lens performance may lead to better user experience (especially on\n * low-performance devices).\n *\n * Running the {@link estimateLensPerformance} function will run benchmarks and estimate an appropriate lens\n * performance cluster (i.e. a performance rating) based on the current environment.\n *\n * Lower cluster = worse expected performance capability.\n *\n * @example\n * ```ts\n * import { bootstrapCameraKit, estimateLensPerformance } from '@snap/camera-kit`\n *\n * const cameraKit = await bootstrapCameraKit({\n * apiToken: '...',\n * lensPerformance: estimateLensPerformance(),\n * })\n * ```\n */\n lensPerformance?: EstimatedLensPerformance | Promise<EstimatedLensPerformance>;\n\n /**\n * In recommended production deployments, the WebAssembly assets required by CameraKit will be downloaded from an\n * optimized CDN. But sometimes (e.g. during development or within a CI pipeline), it may be necessary to download\n * these assets from somewhere else.\n *\n * This configuration option allows the application to specify URLs to be used for both the WebAssembly and JS glue\n * file that are used to run and interact with CameraKit's rendering engine.\n */\n lensCoreOverrideUrls?: { wasm: string; js: string };\n\n /**\n * In recommended production deployments, the WebAssembly assets required by CameraKit will be downloaded from an\n * optimized CDN. But sometimes during development or within a CI pipeline, it may be necessary to download these\n * assets from somewhere else. With a provided `wasmEndpointOverride`, asset URLs will be automatically generated\n * based on this root endpoint.\n */\n wasmEndpointOverride?: string;\n}\n\n/**\n * This type represents the result of merging user-supplied config with default config -- as such, it has no nullable\n * fields, making it a more convenient type for other components to use.\n *\n * @internal\n */\nexport type CameraKitConfiguration = CameraKitRuntimeConfiguration & CameraKitBootstrapConfiguration;\n\n/** @internal */\nexport const configurationToken = \"configuration\";\n\n/** @internal */\nexport const createCameraKitConfigurationFactory = (configuration: CameraKitBootstrapConfiguration) => {\n // always leave debug mode warning about overrides in console\n const overrides = getConfigurationOverrides();\n if (overrides) {\n console.warn(\"Configuration overrides applied\", overrides);\n }\n return Injectable(\n configurationToken,\n (): CameraKitConfiguration => {\n // We'll ensure that we handle errors on any Promises passed as config values, otherwise we either must\n // handle them separately wherever they're used, or rejections would go unhandled.\n const safeConfig: CameraKitBootstrapConfiguration = {\n ...configuration,\n lensPerformance:\n configuration.lensPerformance instanceof Promise\n ? // Safety: defaultConfiguration.lensPerformance is defined (it's hardcoded above).\n configuration.lensPerformance.catch(() => defaultConfiguration.lensPerformance!)\n : configuration.lensPerformance,\n };\n return {\n ...defaultConfiguration,\n ...copyDefinedProperties(safeConfig),\n ...copyDefinedProperties(overrides ?? {}),\n };\n }\n );\n};\n"]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { CameraKitBootstrapConfiguration } from "./configuration";
|
|
2
|
+
/**
|
|
3
|
+
* Configuration overrides that are stored in session storage.
|
|
4
|
+
*/
|
|
5
|
+
declare type StoredOverrides = Pick<CameraKitBootstrapConfiguration, "wasmEndpointOverride" | "logger" | "logLevel">;
|
|
6
|
+
/**
|
|
7
|
+
* Checks whether there are configuration overrides stored, and if yes, returns them.
|
|
8
|
+
*
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function getConfigurationOverrides(): StoredOverrides | undefined;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prefix of override key on window object.
|
|
3
|
+
*/
|
|
4
|
+
const windowFieldPrefix = "__snap_camkit_override__";
|
|
5
|
+
const configPropertiesToOverride = ["wasmEndpointOverride", "logger", "logLevel"];
|
|
6
|
+
configPropertiesToOverride.forEach((fieldToOverride) => {
|
|
7
|
+
defineWindowField(fieldToOverride);
|
|
8
|
+
});
|
|
9
|
+
function defineWindowField(propertyToOverride) {
|
|
10
|
+
if (typeof window === "undefined")
|
|
11
|
+
return;
|
|
12
|
+
Object.defineProperty(window, `${windowFieldPrefix}${propertyToOverride}`, {
|
|
13
|
+
get() {
|
|
14
|
+
var _a;
|
|
15
|
+
return (_a = getConfigurationOverrides()) === null || _a === void 0 ? void 0 : _a[propertyToOverride];
|
|
16
|
+
},
|
|
17
|
+
set(value) {
|
|
18
|
+
var _a;
|
|
19
|
+
const storedOverrdies = (_a = getConfigurationOverrides()) !== null && _a !== void 0 ? _a : {};
|
|
20
|
+
storedOverrdies[propertyToOverride] = value;
|
|
21
|
+
if (Object.values(storedOverrdies).every((value) => typeof value === "undefined")) {
|
|
22
|
+
sessionStorage.removeItem(windowFieldPrefix);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
sessionStorage.setItem(windowFieldPrefix, JSON.stringify(storedOverrdies));
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
enumerable: false,
|
|
29
|
+
configurable: true,
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Checks whether there are configuration overrides stored, and if yes, returns them.
|
|
34
|
+
*
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
export function getConfigurationOverrides() {
|
|
38
|
+
const overridesString = sessionStorage.getItem(windowFieldPrefix);
|
|
39
|
+
return overridesString && JSON.parse(overridesString);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=configurationOverrides.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configurationOverrides.js","sourceRoot":"","sources":["../src/configurationOverrides.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,iBAAiB,GAAG,0BAA0B,CAAC;AAOrD,MAAM,0BAA0B,GAAiC,CAAC,sBAAsB,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;AAEhH,0BAA0B,CAAC,OAAO,CAAC,CAAC,eAAe,EAAE,EAAE;IACnD,iBAAiB,CAAC,eAAe,CAAC,CAAC;AACvC,CAAC,CAAC,CAAC;AAEH,SAAS,iBAAiB,CAAC,kBAAyC;IAChE,IAAI,OAAO,MAAM,KAAK,WAAW;QAAE,OAAO;IAE1C,MAAM,CAAC,cAAc,CAAC,MAAM,EAAE,GAAG,iBAAiB,GAAG,kBAAkB,EAAE,EAAE;QACvE,GAAG;;YACC,OAAO,MAAA,yBAAyB,EAAE,0CAAG,kBAAkB,CAAC,CAAC;QAC7D,CAAC;QACD,GAAG,CAAC,KAAU;;YACV,MAAM,eAAe,GAAG,MAAA,yBAAyB,EAAE,mCAAI,EAAE,CAAC;YAC1D,eAAe,CAAC,kBAAkB,CAAC,GAAG,KAAK,CAAC;YAC5C,IAAI,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,WAAW,CAAC,EAAE;gBAC/E,cAAc,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC;aAChD;iBAAM;gBACH,cAAc,CAAC,OAAO,CAAC,iBAAiB,EAAE,IAAI,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC;aAC9E;QACL,CAAC;QACD,UAAU,EAAE,KAAK;QACjB,YAAY,EAAE,IAAI;KACrB,CAAC,CAAC;AACP,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,yBAAyB;IACrC,MAAM,eAAe,GAAG,cAAc,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAClE,OAAO,eAAe,IAAI,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;AAC1D,CAAC","sourcesContent":["import { CameraKitBootstrapConfiguration } from \"./configuration\";\n\n/**\n * Prefix of override key on window object.\n */\nconst windowFieldPrefix = \"__snap_camkit_override__\";\n\n/**\n * Configuration overrides that are stored in session storage.\n */\ntype StoredOverrides = Pick<CameraKitBootstrapConfiguration, \"wasmEndpointOverride\" | \"logger\" | \"logLevel\">;\n\nconst configPropertiesToOverride: Array<keyof StoredOverrides> = [\"wasmEndpointOverride\", \"logger\", \"logLevel\"];\n\nconfigPropertiesToOverride.forEach((fieldToOverride) => {\n defineWindowField(fieldToOverride);\n});\n\nfunction defineWindowField(propertyToOverride: keyof StoredOverrides) {\n if (typeof window === \"undefined\") return;\n\n Object.defineProperty(window, `${windowFieldPrefix}${propertyToOverride}`, {\n get() {\n return getConfigurationOverrides()?.[propertyToOverride];\n },\n set(value: any) {\n const storedOverrdies = getConfigurationOverrides() ?? {};\n storedOverrdies[propertyToOverride] = value;\n if (Object.values(storedOverrdies).every((value) => typeof value === \"undefined\")) {\n sessionStorage.removeItem(windowFieldPrefix);\n } else {\n sessionStorage.setItem(windowFieldPrefix, JSON.stringify(storedOverrdies));\n }\n },\n enumerable: false,\n configurable: true,\n });\n}\n\n/**\n * Checks whether there are configuration overrides stored, and if yes, returns them.\n *\n * @internal\n */\nexport function getConfigurationOverrides(): StoredOverrides | undefined {\n const overridesString = sessionStorage.getItem(windowFieldPrefix);\n return overridesString && JSON.parse(overridesString);\n}\n"]}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { Memoized } from "../common/memoize";
|
|
2
|
+
import { PartialContainer } from "./PartialContainer";
|
|
3
|
+
import { AddService, InjectableFunction, ValidTokens } from "./types";
|
|
4
|
+
declare type UnsafePartialContainer<Services> = Container<Partial<Services>>;
|
|
5
|
+
declare type MaybeMemoizedFactories<Services> = {
|
|
6
|
+
[K in keyof Services]: ((c: UnsafePartialContainer<Services>) => Services[K]) | Memoized<(c: UnsafePartialContainer<Services>) => Services[K]>;
|
|
7
|
+
};
|
|
8
|
+
export declare type Factories<Services> = {
|
|
9
|
+
[K in keyof Services]: Memoized<(c: UnsafePartialContainer<Services>) => Services[K]>;
|
|
10
|
+
};
|
|
11
|
+
export declare const CONTAINER = "$container";
|
|
12
|
+
export declare type ContainerToken = typeof CONTAINER;
|
|
13
|
+
/**
|
|
14
|
+
* A Container of values, indexed each by a unique token, which can be used throughout CameraKit. This is how CameraKit
|
|
15
|
+
* implements simple dependency injection.
|
|
16
|
+
*
|
|
17
|
+
* Dependency injection is a way to decouple the *use* of a dependency from the *creation* of that dependency. This
|
|
18
|
+
* improves modularity and re-usability, since components only care about the *interfaces* of dependencies (since that
|
|
19
|
+
* determines their use) and not about their concrete creation. New implementations of a particular dependency may be
|
|
20
|
+
* provided without the need to change any of the consumers of that dependency.
|
|
21
|
+
*
|
|
22
|
+
* There are a few commonly-used terms used when talking about dependency injection:
|
|
23
|
+
*
|
|
24
|
+
* - Container (or Injector): Maintains a registry of all available Services and understands how to create them.
|
|
25
|
+
* - Service: Anything that can be provided by the Container is called a Service – this can be a value of any type.
|
|
26
|
+
* - Token: Each Service is associated with a unique name, or Token. In order to obtain a Service from the Container,
|
|
27
|
+
* the consumer must provide the Token corresponding to that Service.
|
|
28
|
+
* - InjectableFunction: Services are created by InjectableFunctions. When adding a Service to a Container, the
|
|
29
|
+
* Service provider gives the Container a InjectableFunction which, when called will return the Service. These
|
|
30
|
+
* InjectableFunctions may themselves use other Services, which will be passed to them as arguments.
|
|
31
|
+
*
|
|
32
|
+
* Services are, by default, singletons – that is, each call to `get()` a particular Service will return a reference
|
|
33
|
+
* to the same value. In other words, InjectableFunctions are only invoked once. If multiple instances of a Service are
|
|
34
|
+
* desired, a new Container can be created using the `copy([Token])` method – passing a Token to this method forces the
|
|
35
|
+
* new Container to recreate the corresponding Service (the InjectableFunction will be invoked again). We say that the
|
|
36
|
+
* Service is then "scoped" to the new Container.
|
|
37
|
+
*
|
|
38
|
+
*
|
|
39
|
+
* One common downside of many dependency injection implementations is that the dependency graph formed by the various
|
|
40
|
+
* Services can only be validated at runtime. That is, if a dependency is missing or a circular dependency is found, the
|
|
41
|
+
* developer must wait until runtime to discover the error. These errors can often be confusing and hard to debug.
|
|
42
|
+
*
|
|
43
|
+
* This implementation eliminates this issue by moving these sorts of errors to compile time. If an unknown dependency
|
|
44
|
+
* is used in a InjectableFunction, for example, the code simply won't compile.
|
|
45
|
+
*
|
|
46
|
+
* To achieve this, we do lose the ability to implicitly define the dependency graph, as is common with many dependency
|
|
47
|
+
* injection frameworks that employ decorators to define Services and their dependencies. Instead, the dependency graph
|
|
48
|
+
* must be constructed explicitly, step-by-step, via successive calls to the `provide()` method. This is a suitable
|
|
49
|
+
* trade-off for CameraKit, as there are a relatively small number of Services.
|
|
50
|
+
*
|
|
51
|
+
* Here's a simple example of Container usage:
|
|
52
|
+
* ```ts
|
|
53
|
+
* const fooFactory = Injectable('Foo', () => new Foo())
|
|
54
|
+
* const barFactory = Injectable('Bar', ['Foo'] as const, (foo: Foo) => new Bar(foo))
|
|
55
|
+
* const container = Container.empy()
|
|
56
|
+
* .provide(fooFactory)
|
|
57
|
+
* .provide(barFactory)
|
|
58
|
+
*
|
|
59
|
+
* const bar: Bar = container.get('Bar')
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
/** @internal */
|
|
63
|
+
export declare class Container<Services = {}> {
|
|
64
|
+
private readonly factories;
|
|
65
|
+
constructor(factories: MaybeMemoizedFactories<Services>);
|
|
66
|
+
/**
|
|
67
|
+
* Create a new [Container] by providing a [PartialContainer] that has no dependencies.
|
|
68
|
+
*/
|
|
69
|
+
static provides<Services>(container: PartialContainer<Services, {}> | Container<Services>): Container<Services>;
|
|
70
|
+
/**
|
|
71
|
+
* Create a new [Container] by providing a Service that has no dependencies.
|
|
72
|
+
*/
|
|
73
|
+
static provides<Token extends string, Service>(fn: InjectableFunction<{}, [], Token, Service>): Container<AddService<{}, Token, Service>>;
|
|
74
|
+
/**
|
|
75
|
+
* Create a copy of this Container, optionally providing a list of Services which will be scoped to the copy.
|
|
76
|
+
*
|
|
77
|
+
* This can be useful, for example, if different parts of an application wish to use the same Service interface, but
|
|
78
|
+
* do not want to share a reference to same Service instance.
|
|
79
|
+
*
|
|
80
|
+
* Say we have a Service which manages a list of Users. Our application wishes to display two lists of Users, which
|
|
81
|
+
* may be edited independently. In this case it may be desirable to create a Container for each list component, with
|
|
82
|
+
* the UserList Service scoped to those Containers – that way, each list component gets a unique copy of the
|
|
83
|
+
* UserList Service that can be edited independently of the other.
|
|
84
|
+
*
|
|
85
|
+
* @param scopedServices A list of Tokens identifying Services which will be scoped to the new Container – that is,
|
|
86
|
+
* if those Services had already been created by the source Container, they will be re-created by their Factory
|
|
87
|
+
* functions when provided by the new Container.
|
|
88
|
+
* @returns A new copy of this Container, sharing all of this Container's Services. Services corresponding to any
|
|
89
|
+
* Tokens passed to this method will be re-created by the new Container (i.e. they become "scoped" to the new
|
|
90
|
+
* Container).
|
|
91
|
+
*/
|
|
92
|
+
copy<Tokens extends readonly (keyof Services)[]>(scopedServices?: Tokens): Container<Services>;
|
|
93
|
+
/**
|
|
94
|
+
* Gets a reference to this Container.
|
|
95
|
+
*
|
|
96
|
+
* @param token The CONTAINER token.
|
|
97
|
+
* @returns This Container.
|
|
98
|
+
*/
|
|
99
|
+
get(token: ContainerToken): this;
|
|
100
|
+
/**
|
|
101
|
+
* Get a specific Service provided by this Container.
|
|
102
|
+
*
|
|
103
|
+
* @param token A unique string corresponding to a Service
|
|
104
|
+
* @returns A Service corresponding to the given Token.
|
|
105
|
+
*/
|
|
106
|
+
get<Token extends keyof Services>(token: Token): Services[Token];
|
|
107
|
+
/**
|
|
108
|
+
* Run the services in this [PartialContainer]. "Run" simply means that [Container::get] will be called for each
|
|
109
|
+
* Service, which invokes that Service's factory function, creating the Service.
|
|
110
|
+
*
|
|
111
|
+
* This may be useful e.g. if services need to initialize themselves, since generally a Service factory is only
|
|
112
|
+
* invoked when the Service is needed.
|
|
113
|
+
*
|
|
114
|
+
* Note this method cannot be used to add services to a Container. – that is, calling this method does not provide
|
|
115
|
+
* the services in a new Container.
|
|
116
|
+
*
|
|
117
|
+
* @param container Optionally provide a [PartialContainer], which will be used as a filter – the only services
|
|
118
|
+
* from *this* container that will run are those with a token that is also present in this PartialContainer.
|
|
119
|
+
* @returns No mutation is done to the Container, it is returned as-is (convenient for chaining).
|
|
120
|
+
*/
|
|
121
|
+
run<AdditionalServices, Dependencies, FulfilledDependencies extends Dependencies>(this: Container<FulfilledDependencies>, container: PartialContainer<AdditionalServices, Dependencies>): this;
|
|
122
|
+
/**
|
|
123
|
+
* Run the given Service. "Run" simply means that [Container::get] will be called for this Service, which invokes
|
|
124
|
+
* the Service's factory function, creating the Service.
|
|
125
|
+
*
|
|
126
|
+
* This may be useful e.g. if services need to initialize themselves, since generally a Service factory is only
|
|
127
|
+
* invoked when the Service is needed.
|
|
128
|
+
*
|
|
129
|
+
* Note this method cannot be used to add services to a Container. – that is, calling this method does not provide
|
|
130
|
+
* the services in a new Container.
|
|
131
|
+
*
|
|
132
|
+
* @param fn Optionally provide an [InjectableFunction], which will be used as a filter – the only services
|
|
133
|
+
* from *this* container that will run are those with a token that is also present in this PartialContainer.
|
|
134
|
+
* @returns No mutation is done to the Container, it is returned as-is (convenient for chaining).
|
|
135
|
+
*/
|
|
136
|
+
run<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service>(fn: InjectableFunction<Services, Tokens, Token, Service>): this;
|
|
137
|
+
/**
|
|
138
|
+
* Create a new Container from this Container with additional services from a given [PartialContainer].
|
|
139
|
+
*
|
|
140
|
+
* Services in the provided PartialContainer take precedence if there are service token conflicts.
|
|
141
|
+
*
|
|
142
|
+
* Services from the provided PartialContainer become scoped to the new Container – that is, if PartialContainer A
|
|
143
|
+
* is provided to Container X and Container Y, each resultant Container will contain its own copy of the services
|
|
144
|
+
* from PartialContainer A.
|
|
145
|
+
*
|
|
146
|
+
* @param container A [PartialContainer] providing additional services.
|
|
147
|
+
*/
|
|
148
|
+
provides<AdditionalServices, Dependencies, FulfilledDependencies extends Dependencies>(this: Container<FulfilledDependencies>, container: PartialContainer<AdditionalServices, Dependencies>): Container<Services & AdditionalServices>;
|
|
149
|
+
/**
|
|
150
|
+
* Creates a new Container from this Container with additional services from another Container.
|
|
151
|
+
*
|
|
152
|
+
* Services in the provided PartialContainer take precedence if there are service token conflicts.
|
|
153
|
+
*
|
|
154
|
+
* Services from the provided Container become scoped to both Containers (the one from which they were provided
|
|
155
|
+
* and the new Container returned by this method) - that is, if Container A is provided to Container B,
|
|
156
|
+
* they will share the same instances of any Services provided by Container A.
|
|
157
|
+
* If Container B should re-create new instances of the Services from Container A,
|
|
158
|
+
* Container A must first be copied before providing it here.
|
|
159
|
+
*
|
|
160
|
+
* @param container A [Container] providing additional services.
|
|
161
|
+
*/
|
|
162
|
+
provides<AdditionalServices>(container: Container<AdditionalServices>): Container<Services & AdditionalServices>;
|
|
163
|
+
/**
|
|
164
|
+
* Create a new Container which provides a Service created by the given [InjectableFunction].
|
|
165
|
+
*
|
|
166
|
+
* The InjectableFunction contains metadata specifying the Token by which the created Service will be known, as well
|
|
167
|
+
* as an ordered list of Tokens to be resolved and provided to the InjectableFunction as arguments.
|
|
168
|
+
*
|
|
169
|
+
* If any of these required dependencies are missing from the Container (or if there is a mismatch between the types
|
|
170
|
+
* of those dependencies and the arguments of the InjectableFunction), a compiler error will be raised.
|
|
171
|
+
*
|
|
172
|
+
* @param fn A factory function, taking dependencies as arguments, which returns the Service.
|
|
173
|
+
*/
|
|
174
|
+
provides<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service>(fn: InjectableFunction<Services, Tokens, Token, Service>): Container<AddService<Services, Token, Service>>;
|
|
175
|
+
private providesService;
|
|
176
|
+
}
|
|
177
|
+
export {};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { isMemoized, memoize } from "../common/memoize";
|
|
2
|
+
import { PartialContainer } from "./PartialContainer";
|
|
3
|
+
export const CONTAINER = "$container";
|
|
4
|
+
/**
|
|
5
|
+
* A Container of values, indexed each by a unique token, which can be used throughout CameraKit. This is how CameraKit
|
|
6
|
+
* implements simple dependency injection.
|
|
7
|
+
*
|
|
8
|
+
* Dependency injection is a way to decouple the *use* of a dependency from the *creation* of that dependency. This
|
|
9
|
+
* improves modularity and re-usability, since components only care about the *interfaces* of dependencies (since that
|
|
10
|
+
* determines their use) and not about their concrete creation. New implementations of a particular dependency may be
|
|
11
|
+
* provided without the need to change any of the consumers of that dependency.
|
|
12
|
+
*
|
|
13
|
+
* There are a few commonly-used terms used when talking about dependency injection:
|
|
14
|
+
*
|
|
15
|
+
* - Container (or Injector): Maintains a registry of all available Services and understands how to create them.
|
|
16
|
+
* - Service: Anything that can be provided by the Container is called a Service – this can be a value of any type.
|
|
17
|
+
* - Token: Each Service is associated with a unique name, or Token. In order to obtain a Service from the Container,
|
|
18
|
+
* the consumer must provide the Token corresponding to that Service.
|
|
19
|
+
* - InjectableFunction: Services are created by InjectableFunctions. When adding a Service to a Container, the
|
|
20
|
+
* Service provider gives the Container a InjectableFunction which, when called will return the Service. These
|
|
21
|
+
* InjectableFunctions may themselves use other Services, which will be passed to them as arguments.
|
|
22
|
+
*
|
|
23
|
+
* Services are, by default, singletons – that is, each call to `get()` a particular Service will return a reference
|
|
24
|
+
* to the same value. In other words, InjectableFunctions are only invoked once. If multiple instances of a Service are
|
|
25
|
+
* desired, a new Container can be created using the `copy([Token])` method – passing a Token to this method forces the
|
|
26
|
+
* new Container to recreate the corresponding Service (the InjectableFunction will be invoked again). We say that the
|
|
27
|
+
* Service is then "scoped" to the new Container.
|
|
28
|
+
*
|
|
29
|
+
*
|
|
30
|
+
* One common downside of many dependency injection implementations is that the dependency graph formed by the various
|
|
31
|
+
* Services can only be validated at runtime. That is, if a dependency is missing or a circular dependency is found, the
|
|
32
|
+
* developer must wait until runtime to discover the error. These errors can often be confusing and hard to debug.
|
|
33
|
+
*
|
|
34
|
+
* This implementation eliminates this issue by moving these sorts of errors to compile time. If an unknown dependency
|
|
35
|
+
* is used in a InjectableFunction, for example, the code simply won't compile.
|
|
36
|
+
*
|
|
37
|
+
* To achieve this, we do lose the ability to implicitly define the dependency graph, as is common with many dependency
|
|
38
|
+
* injection frameworks that employ decorators to define Services and their dependencies. Instead, the dependency graph
|
|
39
|
+
* must be constructed explicitly, step-by-step, via successive calls to the `provide()` method. This is a suitable
|
|
40
|
+
* trade-off for CameraKit, as there are a relatively small number of Services.
|
|
41
|
+
*
|
|
42
|
+
* Here's a simple example of Container usage:
|
|
43
|
+
* ```ts
|
|
44
|
+
* const fooFactory = Injectable('Foo', () => new Foo())
|
|
45
|
+
* const barFactory = Injectable('Bar', ['Foo'] as const, (foo: Foo) => new Bar(foo))
|
|
46
|
+
* const container = Container.empy()
|
|
47
|
+
* .provide(fooFactory)
|
|
48
|
+
* .provide(barFactory)
|
|
49
|
+
*
|
|
50
|
+
* const bar: Bar = container.get('Bar')
|
|
51
|
+
* ```
|
|
52
|
+
*/
|
|
53
|
+
/** @internal */
|
|
54
|
+
export class Container {
|
|
55
|
+
constructor(factories) {
|
|
56
|
+
this.factories = {};
|
|
57
|
+
for (const k in factories) {
|
|
58
|
+
const fn = factories[k];
|
|
59
|
+
if (isMemoized(fn))
|
|
60
|
+
this.factories[k] = fn;
|
|
61
|
+
else
|
|
62
|
+
this.factories[k] = memoize(fn);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
static provides(fnOrContainer) {
|
|
66
|
+
// Although the `provides` method has overloads that match both members of the union type separately, it does
|
|
67
|
+
// not match the union type itself, so the compiler forces us to branch and handle each type within the union
|
|
68
|
+
// separately. (Maybe in the future the compiler will decide to infer this, but for now this is necessary.)
|
|
69
|
+
if (fnOrContainer instanceof PartialContainer)
|
|
70
|
+
return new Container({}).provides(fnOrContainer);
|
|
71
|
+
if (fnOrContainer instanceof Container)
|
|
72
|
+
return new Container({}).provides(fnOrContainer);
|
|
73
|
+
return new Container({}).provides(fnOrContainer);
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a copy of this Container, optionally providing a list of Services which will be scoped to the copy.
|
|
77
|
+
*
|
|
78
|
+
* This can be useful, for example, if different parts of an application wish to use the same Service interface, but
|
|
79
|
+
* do not want to share a reference to same Service instance.
|
|
80
|
+
*
|
|
81
|
+
* Say we have a Service which manages a list of Users. Our application wishes to display two lists of Users, which
|
|
82
|
+
* may be edited independently. In this case it may be desirable to create a Container for each list component, with
|
|
83
|
+
* the UserList Service scoped to those Containers – that way, each list component gets a unique copy of the
|
|
84
|
+
* UserList Service that can be edited independently of the other.
|
|
85
|
+
*
|
|
86
|
+
* @param scopedServices A list of Tokens identifying Services which will be scoped to the new Container – that is,
|
|
87
|
+
* if those Services had already been created by the source Container, they will be re-created by their Factory
|
|
88
|
+
* functions when provided by the new Container.
|
|
89
|
+
* @returns A new copy of this Container, sharing all of this Container's Services. Services corresponding to any
|
|
90
|
+
* Tokens passed to this method will be re-created by the new Container (i.e. they become "scoped" to the new
|
|
91
|
+
* Container).
|
|
92
|
+
*/
|
|
93
|
+
copy(scopedServices) {
|
|
94
|
+
const factories = Object.assign({}, this.factories);
|
|
95
|
+
// We "un-memoize" scoped Service InjectableFunctions so they will create a new copy of their Service when
|
|
96
|
+
// provided by the new Container – we re-memoize them so the new Container will itself only create one Service
|
|
97
|
+
// instance.
|
|
98
|
+
(scopedServices || []).forEach((token) => {
|
|
99
|
+
factories[token] = this.factories[token].delegate;
|
|
100
|
+
});
|
|
101
|
+
return new Container(factories);
|
|
102
|
+
}
|
|
103
|
+
get(token) {
|
|
104
|
+
if (token === CONTAINER)
|
|
105
|
+
return this;
|
|
106
|
+
const factory = this.factories[token];
|
|
107
|
+
if (!factory) {
|
|
108
|
+
throw new Error(`[Container::get] Could not find Service for Token "${token}". This should've caused a ` +
|
|
109
|
+
"compile-time error. If the Token is 'undefined', check all your calls to the Injectable " +
|
|
110
|
+
"function. Make sure you define dependencies using string literals or string constants that are " +
|
|
111
|
+
"definitely initialized before the call to Injectable.");
|
|
112
|
+
}
|
|
113
|
+
return factory(this);
|
|
114
|
+
}
|
|
115
|
+
run(fnOrContainer) {
|
|
116
|
+
if (fnOrContainer instanceof PartialContainer) {
|
|
117
|
+
const runnableContainer = this.provides(fnOrContainer);
|
|
118
|
+
for (const token of fnOrContainer.getTokens()) {
|
|
119
|
+
runnableContainer.get(token);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this.provides(fnOrContainer).get(fnOrContainer.token);
|
|
124
|
+
}
|
|
125
|
+
return this;
|
|
126
|
+
}
|
|
127
|
+
provides(fnOrContainer) {
|
|
128
|
+
if (fnOrContainer instanceof PartialContainer || fnOrContainer instanceof Container) {
|
|
129
|
+
const factories = fnOrContainer instanceof PartialContainer ? fnOrContainer.getFactories(this) : fnOrContainer.factories;
|
|
130
|
+
// Safety: `this.factories` and `factories` are both properly type checked, so merging them produces
|
|
131
|
+
// a Factories object with keys from both Services and AdditionalServices. The compiler is unable to
|
|
132
|
+
// infer that Factories<A> & Factories<B> == Factories<A & B>, so the cast is required.
|
|
133
|
+
return new Container(Object.assign(Object.assign({}, this.factories), factories));
|
|
134
|
+
}
|
|
135
|
+
return this.providesService(fnOrContainer);
|
|
136
|
+
}
|
|
137
|
+
providesService(fn) {
|
|
138
|
+
const token = fn.token;
|
|
139
|
+
const dependencies = fn.dependencies;
|
|
140
|
+
const factory = memoize((container) => {
|
|
141
|
+
return fn(...dependencies.map((t) => {
|
|
142
|
+
// To support overwriting an already-existing service with a new implementation, it should be
|
|
143
|
+
// possibleto do `provide(A, [A], a => createNewServiceFromOld(a))` – that is, inject a dependency
|
|
144
|
+
// with the same token as this service's token.
|
|
145
|
+
//
|
|
146
|
+
// To avoid a circular dependency (in which the factory for service A depends on itself), we always
|
|
147
|
+
// use the service defined in the *parent* container (i.e. this) when injecting a dependency with
|
|
148
|
+
// the same token as the service we're providing. If we did not do this, calling `container.get(t)`
|
|
149
|
+
// would result in an infinite loop.
|
|
150
|
+
return t === token ? this.get(t) : container.get(t);
|
|
151
|
+
}));
|
|
152
|
+
});
|
|
153
|
+
// Safety: `token` and `factory` are property type checked, so extending `this.factories` produces a
|
|
154
|
+
// MaybeMemoizedFactories object with the expected set of services – but when using the spread operation to
|
|
155
|
+
// merge two objects, the compiler widens the Token type to string. So we must re-narrow via casting.
|
|
156
|
+
const factories = Object.assign(Object.assign({}, this.factories), { [token]: factory });
|
|
157
|
+
return new Container(factories);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
//# sourceMappingURL=Container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Container.js","sourceRoot":"","sources":["../../src/dependency-injection/Container.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAY,MAAM,mBAAmB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAoBtD,MAAM,CAAC,MAAM,SAAS,GAAG,YAAY,CAAC;AAGtC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH,gBAAgB;AAChB,MAAM,OAAO,SAAS;IAGlB,YAAY,SAA2C;QACnD,IAAI,CAAC,SAAS,GAAG,EAAyB,CAAC;QAC3C,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE;YACvB,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;YACxB,IAAI,UAAU,CAAC,EAAE,CAAC;gBAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC;;gBACtC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,EAAE,CAAC,CAAC;SACxC;IACL,CAAC;IAcD,MAAM,CAAC,QAAQ,CACX,aAAmG;QAEnG,6GAA6G;QAC7G,6GAA6G;QAC7G,2GAA2G;QAC3G,IAAI,aAAa,YAAY,gBAAgB;YAAE,OAAO,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QAChG,IAAI,aAAa,YAAY,SAAS;YAAE,OAAO,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACzF,OAAO,IAAI,SAAS,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;IACrD,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,CAA6C,cAAuB;QACpE,MAAM,SAAS,qBAA0C,IAAI,CAAC,SAAS,CAAE,CAAC;QAE1E,0GAA0G;QAC1G,8GAA8G;QAC9G,YAAY;QACZ,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,KAAqB,EAAE,EAAE;YACrD,SAAS,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,OAAO,IAAI,SAAS,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAkBD,GAAG,CAAC,KAAa;QACb,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACtC,IAAI,CAAC,OAAO,EAAE;YACV,MAAM,IAAI,KAAK,CACX,sDAAsD,KAAK,6BAA6B;gBACpF,0FAA0F;gBAC1F,iGAAiG;gBACjG,uDAAuD,CAC9D,CAAC;SACL;QACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;IAyCD,GAAG,CACC,aAEoD;QAEpD,IAAI,aAAa,YAAY,gBAAgB,EAAE;YAC3C,MAAM,iBAAiB,GAAG,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;YACvD,KAAK,MAAM,KAAK,IAAI,aAAa,CAAC,SAAS,EAAE,EAAE;gBAC3C,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;aAChC;SACJ;aAAM;YACH,IAAI,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;SACzD;QACD,OAAO,IAAI,CAAC;IAChB,CAAC;IAkDD,QAAQ,CACJ,aAGmC;QAEnC,IAAI,aAAa,YAAY,gBAAgB,IAAI,aAAa,YAAY,SAAS,EAAE;YACjF,MAAM,SAAS,GACX,aAAa,YAAY,gBAAgB,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,SAAS,CAAC;YAC3G,oGAAoG;YACpG,oGAAoG;YACpG,uFAAuF;YACvF,OAAO,IAAI,SAAS,CAAE,gCACf,IAAI,CAAC,SAAS,GACd,SAAS,CACsD,CAAC,CAAC;SAC3E;QACD,OAAO,IAAI,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IAC/C,CAAC;IAEO,eAAe,CACnB,EAAwD;QAExD,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,CAAC;QACvB,MAAM,YAAY,GAAmB,EAAE,CAAC,YAAY,CAAC;QAErD,MAAM,OAAO,GAAG,OAAO,CAAC,CAAC,SAA8B,EAAE,EAAE;YACvD,OAAO,EAAE,CACL,GAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;gBACvB,6FAA6F;gBAC7F,kGAAkG;gBAClG,+CAA+C;gBAC/C,EAAE;gBACF,mGAAmG;gBACnG,iGAAiG;gBACjG,mGAAmG;gBACnG,oCAAoC;gBACpC,OAAO,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACxD,CAAC,CAAS,CACb,CAAC;QACN,CAAC,CAAC,CAAC;QAEH,oGAAoG;QACpG,2GAA2G;QAC3G,qGAAqG;QACrG,MAAM,SAAS,mCAAQ,IAAI,CAAC,SAAS,KAAE,CAAC,KAAK,CAAC,EAAE,OAAO,GAAE,CAAC;QAC1D,OAAO,IAAI,SAAS,CAAE,SAAqF,CAAC,CAAC;IACjH,CAAC;CACJ","sourcesContent":["import { isMemoized, memoize, Memoized } from \"../common/memoize\";\nimport { PartialContainer } from \"./PartialContainer\";\nimport { AddService, InjectableFunction, ValidTokens } from \"./types\";\n\n// This is un-safe. In practice, Containers should always be created by calling `Container::provides` on some other\n// Container (except for some \"root\" Container which is instantiated with no Services) – `Container::provides\" is safely\n// type-checked, so this doesn't introduce much risk. But a more accurate solution would be for the `Factories` and\n// `MaybeMemoizedFactories` types to keep track of which specific Services must be present in the Container\n// corresponding to each Service. But this is much more complex to implement.\ntype UnsafePartialContainer<Services> = Container<Partial<Services>>;\n\ntype MaybeMemoizedFactories<Services> = {\n [K in keyof Services]:\n | ((c: UnsafePartialContainer<Services>) => Services[K])\n | Memoized<(c: UnsafePartialContainer<Services>) => Services[K]>;\n};\n\nexport type Factories<Services> = {\n [K in keyof Services]: Memoized<(c: UnsafePartialContainer<Services>) => Services[K]>;\n};\n\nexport const CONTAINER = \"$container\";\nexport type ContainerToken = typeof CONTAINER;\n\n/**\n * A Container of values, indexed each by a unique token, which can be used throughout CameraKit. This is how CameraKit\n * implements simple dependency injection.\n *\n * Dependency injection is a way to decouple the *use* of a dependency from the *creation* of that dependency. This\n * improves modularity and re-usability, since components only care about the *interfaces* of dependencies (since that\n * determines their use) and not about their concrete creation. New implementations of a particular dependency may be\n * provided without the need to change any of the consumers of that dependency.\n *\n * There are a few commonly-used terms used when talking about dependency injection:\n *\n * - Container (or Injector): Maintains a registry of all available Services and understands how to create them.\n * - Service: Anything that can be provided by the Container is called a Service – this can be a value of any type.\n * - Token: Each Service is associated with a unique name, or Token. In order to obtain a Service from the Container,\n * the consumer must provide the Token corresponding to that Service.\n * - InjectableFunction: Services are created by InjectableFunctions. When adding a Service to a Container, the\n * Service provider gives the Container a InjectableFunction which, when called will return the Service. These\n * InjectableFunctions may themselves use other Services, which will be passed to them as arguments.\n *\n * Services are, by default, singletons – that is, each call to `get()` a particular Service will return a reference\n * to the same value. In other words, InjectableFunctions are only invoked once. If multiple instances of a Service are\n * desired, a new Container can be created using the `copy([Token])` method – passing a Token to this method forces the\n * new Container to recreate the corresponding Service (the InjectableFunction will be invoked again). We say that the\n * Service is then \"scoped\" to the new Container.\n *\n *\n * One common downside of many dependency injection implementations is that the dependency graph formed by the various\n * Services can only be validated at runtime. That is, if a dependency is missing or a circular dependency is found, the\n * developer must wait until runtime to discover the error. These errors can often be confusing and hard to debug.\n *\n * This implementation eliminates this issue by moving these sorts of errors to compile time. If an unknown dependency\n * is used in a InjectableFunction, for example, the code simply won't compile.\n *\n * To achieve this, we do lose the ability to implicitly define the dependency graph, as is common with many dependency\n * injection frameworks that employ decorators to define Services and their dependencies. Instead, the dependency graph\n * must be constructed explicitly, step-by-step, via successive calls to the `provide()` method. This is a suitable\n * trade-off for CameraKit, as there are a relatively small number of Services.\n *\n * Here's a simple example of Container usage:\n * ```ts\n * const fooFactory = Injectable('Foo', () => new Foo())\n * const barFactory = Injectable('Bar', ['Foo'] as const, (foo: Foo) => new Bar(foo))\n * const container = Container.empy()\n * .provide(fooFactory)\n * .provide(barFactory)\n *\n * const bar: Bar = container.get('Bar')\n * ```\n */\n/** @internal */\nexport class Container<Services = {}> {\n private readonly factories: Factories<Services>;\n\n constructor(factories: MaybeMemoizedFactories<Services>) {\n this.factories = {} as Factories<Services>;\n for (const k in factories) {\n const fn = factories[k];\n if (isMemoized(fn)) this.factories[k] = fn;\n else this.factories[k] = memoize(fn);\n }\n }\n\n /**\n * Create a new [Container] by providing a [PartialContainer] that has no dependencies.\n */\n static provides<Services>(container: PartialContainer<Services, {}> | Container<Services>): Container<Services>;\n\n /**\n * Create a new [Container] by providing a Service that has no dependencies.\n */\n static provides<Token extends string, Service>(\n fn: InjectableFunction<{}, [], Token, Service>\n ): Container<AddService<{}, Token, Service>>;\n\n static provides(\n fnOrContainer: InjectableFunction<{}, [], string, any> | PartialContainer<any, {}> | Container<any>\n ): Container<any> {\n // Although the `provides` method has overloads that match both members of the union type separately, it does\n // not match the union type itself, so the compiler forces us to branch and handle each type within the union\n // separately. (Maybe in the future the compiler will decide to infer this, but for now this is necessary.)\n if (fnOrContainer instanceof PartialContainer) return new Container({}).provides(fnOrContainer);\n if (fnOrContainer instanceof Container) return new Container({}).provides(fnOrContainer);\n return new Container({}).provides(fnOrContainer);\n }\n\n /**\n * Create a copy of this Container, optionally providing a list of Services which will be scoped to the copy.\n *\n * This can be useful, for example, if different parts of an application wish to use the same Service interface, but\n * do not want to share a reference to same Service instance.\n *\n * Say we have a Service which manages a list of Users. Our application wishes to display two lists of Users, which\n * may be edited independently. In this case it may be desirable to create a Container for each list component, with\n * the UserList Service scoped to those Containers – that way, each list component gets a unique copy of the\n * UserList Service that can be edited independently of the other.\n *\n * @param scopedServices A list of Tokens identifying Services which will be scoped to the new Container – that is,\n * if those Services had already been created by the source Container, they will be re-created by their Factory\n * functions when provided by the new Container.\n * @returns A new copy of this Container, sharing all of this Container's Services. Services corresponding to any\n * Tokens passed to this method will be re-created by the new Container (i.e. they become \"scoped\" to the new\n * Container).\n */\n copy<Tokens extends readonly (keyof Services)[]>(scopedServices?: Tokens): Container<Services> {\n const factories: MaybeMemoizedFactories<Services> = { ...this.factories };\n\n // We \"un-memoize\" scoped Service InjectableFunctions so they will create a new copy of their Service when\n // provided by the new Container – we re-memoize them so the new Container will itself only create one Service\n // instance.\n (scopedServices || []).forEach((token: keyof Services) => {\n factories[token] = this.factories[token].delegate;\n });\n return new Container(factories);\n }\n\n /**\n * Gets a reference to this Container.\n *\n * @param token The CONTAINER token.\n * @returns This Container.\n */\n get(token: ContainerToken): this;\n\n /**\n * Get a specific Service provided by this Container.\n *\n * @param token A unique string corresponding to a Service\n * @returns A Service corresponding to the given Token.\n */\n get<Token extends keyof Services>(token: Token): Services[Token];\n\n get(token: string): this | Services[keyof Services] {\n if (token === CONTAINER) return this;\n const factory = this.factories[token];\n if (!factory) {\n throw new Error(\n `[Container::get] Could not find Service for Token \"${token}\". This should've caused a ` +\n \"compile-time error. If the Token is 'undefined', check all your calls to the Injectable \" +\n \"function. Make sure you define dependencies using string literals or string constants that are \" +\n \"definitely initialized before the call to Injectable.\"\n );\n }\n return factory(this);\n }\n\n /**\n * Run the services in this [PartialContainer]. \"Run\" simply means that [Container::get] will be called for each\n * Service, which invokes that Service's factory function, creating the Service.\n *\n * This may be useful e.g. if services need to initialize themselves, since generally a Service factory is only\n * invoked when the Service is needed.\n *\n * Note this method cannot be used to add services to a Container. – that is, calling this method does not provide\n * the services in a new Container.\n *\n * @param container Optionally provide a [PartialContainer], which will be used as a filter – the only services\n * from *this* container that will run are those with a token that is also present in this PartialContainer.\n * @returns No mutation is done to the Container, it is returned as-is (convenient for chaining).\n */\n run<AdditionalServices, Dependencies, FulfilledDependencies extends Dependencies>(\n // FullfilledDependencies is assignable to Dependencies -- by specifying Container<FulfilledDependencies> as the\n // `this` type, we ensure this Container can provide all the Dependencies required by the PartialContainer.\n this: Container<FulfilledDependencies>,\n container: PartialContainer<AdditionalServices, Dependencies>\n ): this;\n\n /**\n * Run the given Service. \"Run\" simply means that [Container::get] will be called for this Service, which invokes\n * the Service's factory function, creating the Service.\n *\n * This may be useful e.g. if services need to initialize themselves, since generally a Service factory is only\n * invoked when the Service is needed.\n *\n * Note this method cannot be used to add services to a Container. – that is, calling this method does not provide\n * the services in a new Container.\n *\n * @param fn Optionally provide an [InjectableFunction], which will be used as a filter – the only services\n * from *this* container that will run are those with a token that is also present in this PartialContainer.\n * @returns No mutation is done to the Container, it is returned as-is (convenient for chaining).\n */\n run<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service>(\n fn: InjectableFunction<Services, Tokens, Token, Service>\n ): this;\n\n run<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service, AdditionalServices>(\n fnOrContainer:\n | InjectableFunction<Services, Tokens, Token, Service>\n | PartialContainer<AdditionalServices, Services>\n ): this {\n if (fnOrContainer instanceof PartialContainer) {\n const runnableContainer = this.provides(fnOrContainer);\n for (const token of fnOrContainer.getTokens()) {\n runnableContainer.get(token);\n }\n } else {\n this.provides(fnOrContainer).get(fnOrContainer.token);\n }\n return this;\n }\n\n /**\n * Create a new Container from this Container with additional services from a given [PartialContainer].\n *\n * Services in the provided PartialContainer take precedence if there are service token conflicts.\n *\n * Services from the provided PartialContainer become scoped to the new Container – that is, if PartialContainer A\n * is provided to Container X and Container Y, each resultant Container will contain its own copy of the services\n * from PartialContainer A.\n *\n * @param container A [PartialContainer] providing additional services.\n */\n provides<AdditionalServices, Dependencies, FulfilledDependencies extends Dependencies>(\n // FullfilledDependencies is assignable to Dependencies -- by specifying Container<FulfilledDependencies> as the\n // `this` type, we ensure this Container can provide all the Dependencies required by the PartialContainer.\n this: Container<FulfilledDependencies>,\n container: PartialContainer<AdditionalServices, Dependencies>\n ): Container<Services & AdditionalServices>;\n\n /**\n * Creates a new Container from this Container with additional services from another Container.\n *\n * Services in the provided PartialContainer take precedence if there are service token conflicts.\n *\n * Services from the provided Container become scoped to both Containers (the one from which they were provided\n * and the new Container returned by this method) - that is, if Container A is provided to Container B,\n * they will share the same instances of any Services provided by Container A.\n * If Container B should re-create new instances of the Services from Container A,\n * Container A must first be copied before providing it here.\n *\n * @param container A [Container] providing additional services.\n */\n provides<AdditionalServices>(container: Container<AdditionalServices>): Container<Services & AdditionalServices>;\n\n /**\n * Create a new Container which provides a Service created by the given [InjectableFunction].\n *\n * The InjectableFunction contains metadata specifying the Token by which the created Service will be known, as well\n * as an ordered list of Tokens to be resolved and provided to the InjectableFunction as arguments.\n *\n * If any of these required dependencies are missing from the Container (or if there is a mismatch between the types\n * of those dependencies and the arguments of the InjectableFunction), a compiler error will be raised.\n *\n * @param fn A factory function, taking dependencies as arguments, which returns the Service.\n */\n provides<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service>(\n fn: InjectableFunction<Services, Tokens, Token, Service>\n ): Container<AddService<Services, Token, Service>>;\n\n provides<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service, AdditionalServices>(\n fnOrContainer:\n | InjectableFunction<Services, Tokens, Token, Service>\n | PartialContainer<AdditionalServices, Services>\n | Container<AdditionalServices>\n ): Container<any> {\n if (fnOrContainer instanceof PartialContainer || fnOrContainer instanceof Container) {\n const factories =\n fnOrContainer instanceof PartialContainer ? fnOrContainer.getFactories(this) : fnOrContainer.factories;\n // Safety: `this.factories` and `factories` are both properly type checked, so merging them produces\n // a Factories object with keys from both Services and AdditionalServices. The compiler is unable to\n // infer that Factories<A> & Factories<B> == Factories<A & B>, so the cast is required.\n return new Container(({\n ...this.factories,\n ...factories,\n } as unknown) as MaybeMemoizedFactories<Services & AdditionalServices>);\n }\n return this.providesService(fnOrContainer);\n }\n\n private providesService<Token extends string, Tokens extends readonly ValidTokens<Services>[], Service>(\n fn: InjectableFunction<Services, Tokens, Token, Service>\n ): Container<AddService<Services, Token, Service>> {\n const token = fn.token;\n const dependencies: readonly any[] = fn.dependencies;\n\n const factory = memoize((container: Container<Services>) => {\n return fn(\n ...(dependencies.map((t) => {\n // To support overwriting an already-existing service with a new implementation, it should be\n // possibleto do `provide(A, [A], a => createNewServiceFromOld(a))` – that is, inject a dependency\n // with the same token as this service's token.\n //\n // To avoid a circular dependency (in which the factory for service A depends on itself), we always\n // use the service defined in the *parent* container (i.e. this) when injecting a dependency with\n // the same token as the service we're providing. If we did not do this, calling `container.get(t)`\n // would result in an infinite loop.\n return t === token ? this.get(t) : container.get(t);\n }) as any)\n );\n });\n\n // Safety: `token` and `factory` are property type checked, so extending `this.factories` produces a\n // MaybeMemoizedFactories object with the expected set of services – but when using the spread operation to\n // merge two objects, the compiler widens the Token type to string. So we must re-narrow via casting.\n const factories = { ...this.factories, [token]: factory };\n return new Container((factories as unknown) as MaybeMemoizedFactories<AddService<Services, Token, Service>>);\n }\n}\n"]}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { InjectableFunction, ServicesFromTokenizedParams } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Create an Injectable function with no dependencies (i.e. arguments).
|
|
4
|
+
*
|
|
5
|
+
* Ex:
|
|
6
|
+
* ```ts
|
|
7
|
+
* const createMyService = Factory(
|
|
8
|
+
* 'MyService',
|
|
9
|
+
* () => { ... },
|
|
10
|
+
* )
|
|
11
|
+
* ```
|
|
12
|
+
*
|
|
13
|
+
* @param token A unique string Token which will correspond to the created Service.
|
|
14
|
+
* @param fn A function with no arguments which returns the Service.
|
|
15
|
+
*/
|
|
16
|
+
export declare function Injectable<Token extends string, Service>(token: Token, fn: () => Service): InjectableFunction<any, [], Token, Service>;
|
|
17
|
+
/**
|
|
18
|
+
* Create an Injectable function with dependencies (i.e. arguments).
|
|
19
|
+
*
|
|
20
|
+
* **Note:** the list of dependencies must be readonly – that is, a literal tuple marked `as const`. This tuple must
|
|
21
|
+
* contain only string literals or string consts.
|
|
22
|
+
*
|
|
23
|
+
* Ex:
|
|
24
|
+
* ```ts
|
|
25
|
+
* const DependencyB = 'DependencyB'
|
|
26
|
+
* const createMyService = Factory(
|
|
27
|
+
* 'MyService',
|
|
28
|
+
* ['DependencyA', DependencyB] as const,
|
|
29
|
+
* (a: A, b: B) => { ... },
|
|
30
|
+
* )
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @param token A unique string Token which will correspond to the created Service.
|
|
34
|
+
* @param dependencies A *readonly* list of Tokens corresponding to dependencies (i.e. arguments to the Factory), which
|
|
35
|
+
* will be resolved by the Container to which this Factory is provided.
|
|
36
|
+
* @param fn A function with arguments matching in type and length to the given list of dependencies. When called, it
|
|
37
|
+
* must return the Service.
|
|
38
|
+
*/
|
|
39
|
+
export declare function Injectable<Token extends string, Tokens extends readonly string[], Params extends readonly any[], Service>(token: Token, dependencies: Tokens, fn: (...args: Tokens["length"] extends Params["length"] ? Params : void[]) => Service): Tokens["length"] extends Params["length"] ? InjectableFunction<ServicesFromTokenizedParams<Tokens, Params>, Tokens, Token, Service> : never;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export function Injectable(token, dependenciesOrFn, maybeFn) {
|
|
2
|
+
const dependencies = Array.isArray(dependenciesOrFn) ? dependenciesOrFn : [];
|
|
3
|
+
const fn = typeof dependenciesOrFn === "function" ? dependenciesOrFn : maybeFn;
|
|
4
|
+
if (!fn) {
|
|
5
|
+
throw new TypeError("[Factory] Received invalid arguments. The factory function must be either the second " +
|
|
6
|
+
"or third argument.");
|
|
7
|
+
}
|
|
8
|
+
if (fn.length !== dependencies.length) {
|
|
9
|
+
throw new TypeError("[Factory] Function arity does not match the number of dependencies. Function has arity " +
|
|
10
|
+
`${fn.length}, but ${dependencies.length} dependencies were specified.` +
|
|
11
|
+
`\nDependencies: ${JSON.stringify(dependencies)}`);
|
|
12
|
+
}
|
|
13
|
+
const factory = (...args) => fn(...args);
|
|
14
|
+
factory.token = token;
|
|
15
|
+
factory.dependencies = dependencies;
|
|
16
|
+
return factory;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=Injectable.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Injectable.js","sourceRoot":"","sources":["../../src/dependency-injection/Injectable.ts"],"names":[],"mappings":"AA2DA,MAAM,UAAU,UAAU,CACtB,KAAa,EACb,gBAAkD,EAClD,OAAiC;IAEjC,MAAM,YAAY,GAAa,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;IACvF,MAAM,EAAE,GAAG,OAAO,gBAAgB,KAAK,UAAU,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,OAAO,CAAC;IAE/E,IAAI,CAAC,EAAE,EAAE;QACL,MAAM,IAAI,SAAS,CACf,uFAAuF;YACnF,oBAAoB,CAC3B,CAAC;KACL;IAED,IAAI,EAAE,CAAC,MAAM,KAAK,YAAY,CAAC,MAAM,EAAE;QACnC,MAAM,IAAI,SAAS,CACf,yFAAyF;YACrF,GAAG,EAAE,CAAC,MAAM,SAAS,YAAY,CAAC,MAAM,+BAA+B;YACvE,mBAAmB,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,CACxD,CAAC;KACL;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,IAAW,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,CAAC;IAChD,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC;IACtB,OAAO,CAAC,YAAY,GAAG,YAAY,CAAC;IACpC,OAAO,OAAO,CAAC;AACnB,CAAC","sourcesContent":["import { InjectableFunction, ServicesFromTokenizedParams } from \"./types\";\n\n/**\n * Create an Injectable function with no dependencies (i.e. arguments).\n *\n * Ex:\n * ```ts\n * const createMyService = Factory(\n * 'MyService',\n * () => { ... },\n * )\n * ```\n *\n * @param token A unique string Token which will correspond to the created Service.\n * @param fn A function with no arguments which returns the Service.\n */\nexport function Injectable<Token extends string, Service>(\n token: Token,\n fn: () => Service\n): InjectableFunction<any, [], Token, Service>;\n\n/**\n * Create an Injectable function with dependencies (i.e. arguments).\n *\n * **Note:** the list of dependencies must be readonly – that is, a literal tuple marked `as const`. This tuple must\n * contain only string literals or string consts.\n *\n * Ex:\n * ```ts\n * const DependencyB = 'DependencyB'\n * const createMyService = Factory(\n * 'MyService',\n * ['DependencyA', DependencyB] as const,\n * (a: A, b: B) => { ... },\n * )\n * ```\n *\n * @param token A unique string Token which will correspond to the created Service.\n * @param dependencies A *readonly* list of Tokens corresponding to dependencies (i.e. arguments to the Factory), which\n * will be resolved by the Container to which this Factory is provided.\n * @param fn A function with arguments matching in type and length to the given list of dependencies. When called, it\n * must return the Service.\n */\nexport function Injectable<\n Token extends string,\n Tokens extends readonly string[],\n Params extends readonly any[],\n Service\n>(\n token: Token,\n dependencies: Tokens,\n // The function arity (number of arguments) must match the number of dependencies specified – if they don't, we'll\n // force a compiler error by saying the arguments should be `void[]`. We'll also throw at runtime, so the return\n // type will be `never`.\n fn: (...args: Tokens[\"length\"] extends Params[\"length\"] ? Params : void[]) => Service\n): Tokens[\"length\"] extends Params[\"length\"]\n ? InjectableFunction<ServicesFromTokenizedParams<Tokens, Params>, Tokens, Token, Service>\n : never;\n\nexport function Injectable(\n token: string,\n dependenciesOrFn?: readonly string[] | (() => any),\n maybeFn?: (...args: any[]) => any\n): InjectableFunction<any, readonly string[], string, any> {\n const dependencies: string[] = Array.isArray(dependenciesOrFn) ? dependenciesOrFn : [];\n const fn = typeof dependenciesOrFn === \"function\" ? dependenciesOrFn : maybeFn;\n\n if (!fn) {\n throw new TypeError(\n \"[Factory] Received invalid arguments. The factory function must be either the second \" +\n \"or third argument.\"\n );\n }\n\n if (fn.length !== dependencies.length) {\n throw new TypeError(\n \"[Factory] Function arity does not match the number of dependencies. Function has arity \" +\n `${fn.length}, but ${dependencies.length} dependencies were specified.` +\n `\\nDependencies: ${JSON.stringify(dependencies)}`\n );\n }\n\n const factory = (...args: any[]) => fn(...args);\n factory.token = token;\n factory.dependencies = dependencies;\n return factory;\n}\n"]}
|