@nlabs/reaktor 0.10.5 → 0.10.7
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/lib/actions/apps.d.ts +1 -0
- package/lib/actions/apps.d.ts.map +1 -0
- package/lib/actions/apps.js +221 -0
- package/lib/actions/connections.d.ts +1 -0
- package/lib/actions/connections.d.ts.map +1 -0
- package/lib/actions/connections.js +62 -0
- package/lib/actions/content.d.ts +1 -0
- package/lib/actions/content.d.ts.map +1 -0
- package/lib/actions/content.js +240 -0
- package/lib/actions/conversations.d.ts +1 -0
- package/lib/actions/conversations.d.ts.map +1 -0
- package/lib/actions/conversations.js +335 -0
- package/lib/actions/dynamodb.d.ts +1 -0
- package/lib/actions/dynamodb.d.ts.map +1 -0
- package/lib/actions/dynamodb.js +119 -0
- package/lib/actions/email.d.ts +1 -0
- package/lib/actions/email.d.ts.map +1 -0
- package/lib/actions/email.js +56 -0
- package/lib/actions/files.d.ts +1 -0
- package/lib/actions/files.d.ts.map +1 -0
- package/lib/actions/files.js +226 -0
- package/lib/actions/groups.d.ts +1 -0
- package/lib/actions/groups.d.ts.map +1 -0
- package/lib/actions/groups.js +267 -0
- package/lib/actions/images.d.ts +1 -0
- package/lib/actions/images.d.ts.map +1 -0
- package/lib/actions/images.js +723 -0
- package/lib/actions/index.d.ts +1 -0
- package/lib/actions/index.d.ts.map +1 -0
- package/lib/actions/index.js +29 -0
- package/lib/actions/ios.d.ts +1 -0
- package/lib/actions/ios.d.ts.map +1 -0
- package/lib/actions/ios.js +230 -0
- package/lib/actions/locations.d.ts +1 -0
- package/lib/actions/locations.d.ts.map +1 -0
- package/lib/actions/locations.js +111 -0
- package/lib/actions/messages.d.ts +1 -0
- package/lib/actions/messages.d.ts.map +1 -0
- package/lib/actions/messages.js +167 -0
- package/lib/actions/notifications.d.ts +3 -2
- package/lib/actions/notifications.d.ts.map +1 -0
- package/lib/actions/notifications.js +37 -0
- package/lib/actions/payments.d.ts +1 -0
- package/lib/actions/payments.d.ts.map +1 -0
- package/lib/actions/payments.js +449 -0
- package/lib/actions/posts.d.ts +1 -0
- package/lib/actions/posts.d.ts.map +1 -0
- package/lib/actions/posts.js +608 -0
- package/lib/actions/profiles.d.ts +1 -0
- package/lib/actions/profiles.d.ts.map +1 -0
- package/lib/actions/profiles.js +58 -0
- package/lib/actions/reactions.d.ts +1 -0
- package/lib/actions/reactions.d.ts.map +1 -0
- package/lib/actions/reactions.js +286 -0
- package/lib/actions/s3.d.ts +1 -0
- package/lib/actions/s3.d.ts.map +1 -0
- package/lib/actions/s3.js +102 -0
- package/lib/actions/search.d.ts +1 -0
- package/lib/actions/search.d.ts.map +1 -0
- package/lib/actions/search.js +81 -0
- package/lib/actions/sms.d.ts +1 -0
- package/lib/actions/sms.d.ts.map +1 -0
- package/lib/actions/sms.js +52 -0
- package/lib/actions/statistics.d.ts +1 -0
- package/lib/actions/statistics.d.ts.map +1 -0
- package/lib/actions/statistics.js +43 -0
- package/lib/actions/subscriptions.d.ts +1 -0
- package/lib/actions/subscriptions.d.ts.map +1 -0
- package/lib/actions/subscriptions.js +202 -0
- package/lib/actions/tags.d.ts +1 -0
- package/lib/actions/tags.d.ts.map +1 -0
- package/lib/actions/tags.js +263 -0
- package/lib/actions/users.d.ts +1 -0
- package/lib/actions/users.d.ts.map +1 -0
- package/lib/actions/users.js +802 -0
- package/lib/actions/videos.d.ts +1 -0
- package/lib/actions/videos.d.ts.map +1 -0
- package/lib/actions/videos.js +423 -0
- package/lib/actions/websockets.d.ts +1 -0
- package/lib/actions/websockets.d.ts.map +1 -0
- package/lib/actions/websockets.js +164 -0
- package/lib/adapters/arangoAdapter.d.ts +1 -0
- package/lib/adapters/arangoAdapter.d.ts.map +1 -0
- package/lib/adapters/arangoAdapter.js +70 -0
- package/lib/adapters/contentAdapter.d.ts +1 -0
- package/lib/adapters/contentAdapter.d.ts.map +1 -0
- package/lib/adapters/contentAdapter.js +108 -0
- package/lib/adapters/fileAdapter.d.ts +1 -0
- package/lib/adapters/fileAdapter.d.ts.map +1 -0
- package/lib/adapters/fileAdapter.js +119 -0
- package/lib/adapters/imageAdapter.d.ts +1 -0
- package/lib/adapters/imageAdapter.d.ts.map +1 -0
- package/lib/adapters/imageAdapter.js +112 -0
- package/lib/adapters/index.d.ts +1 -0
- package/lib/adapters/index.d.ts.map +1 -0
- package/lib/adapters/index.js +11 -0
- package/lib/adapters/messageAdapter.d.ts +1 -0
- package/lib/adapters/messageAdapter.d.ts.map +1 -0
- package/lib/adapters/messageAdapter.js +82 -0
- package/lib/adapters/postAdapter.d.ts +1 -0
- package/lib/adapters/postAdapter.d.ts.map +1 -0
- package/lib/adapters/postAdapter.js +117 -0
- package/lib/adapters/reaktorAdapter.d.ts +1 -0
- package/lib/adapters/reaktorAdapter.d.ts.map +1 -0
- package/lib/adapters/reaktorAdapter.js +59 -0
- package/lib/adapters/tagAdapter.d.ts +1 -0
- package/lib/adapters/tagAdapter.d.ts.map +1 -0
- package/lib/adapters/tagAdapter.js +99 -0
- package/lib/adapters/userAdapter.d.ts +1 -0
- package/lib/adapters/userAdapter.d.ts.map +1 -0
- package/lib/adapters/userAdapter.js +264 -0
- package/lib/config.d.ts +1 -0
- package/lib/config.d.ts.map +1 -0
- package/lib/config.js +161 -0
- package/lib/handlers/graphqlHandler.d.ts +1 -0
- package/lib/handlers/graphqlHandler.d.ts.map +1 -0
- package/lib/handlers/graphqlHandler.js +118 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +18 -0
- package/lib/lambdas/actions/websockets.d.ts +1 -0
- package/lib/lambdas/actions/websockets.d.ts.map +1 -0
- package/lib/lambdas/actions/websockets.js +105 -0
- package/lib/lambdas/authorizer.d.ts +1 -0
- package/lib/lambdas/authorizer.d.ts.map +1 -0
- package/lib/lambdas/authorizer.js +41 -0
- package/lib/lambdas/connection.d.ts +1 -0
- package/lib/lambdas/connection.d.ts.map +1 -0
- package/lib/lambdas/connection.js +85 -0
- package/lib/lambdas/utils/message.d.ts +1 -0
- package/lib/lambdas/utils/message.d.ts.map +1 -0
- package/lib/lambdas/utils/message.js +20 -0
- package/lib/lambdas/utils/websocket.d.ts +1 -0
- package/lib/lambdas/utils/websocket.d.ts.map +1 -0
- package/lib/lambdas/utils/websocket.js +78 -0
- package/lib/mocks/conversation.d.ts +1 -0
- package/lib/mocks/conversation.d.ts.map +1 -0
- package/lib/mocks/conversation.js +10 -0
- package/lib/mocks/file.d.ts +1 -0
- package/lib/mocks/file.d.ts.map +1 -0
- package/lib/mocks/file.js +13 -0
- package/lib/mocks/group.d.ts +1 -0
- package/lib/mocks/group.d.ts.map +1 -0
- package/lib/mocks/group.js +20 -0
- package/lib/mocks/image.d.ts +1 -0
- package/lib/mocks/image.d.ts.map +1 -0
- package/lib/mocks/image.js +17 -0
- package/lib/mocks/post.d.ts +1 -0
- package/lib/mocks/post.d.ts.map +1 -0
- package/lib/mocks/post.js +28 -0
- package/lib/mocks/tag.d.ts +1 -0
- package/lib/mocks/tag.d.ts.map +1 -0
- package/lib/mocks/tag.js +12 -0
- package/lib/mocks/user.d.ts +1 -0
- package/lib/mocks/user.d.ts.map +1 -0
- package/lib/mocks/user.js +61 -0
- package/lib/mocks/video.d.ts +1 -0
- package/lib/mocks/video.d.ts.map +1 -0
- package/lib/mocks/video.js +17 -0
- package/lib/mutations/content.d.ts +1 -0
- package/lib/mutations/content.d.ts.map +1 -0
- package/lib/mutations/content.js +27 -0
- package/lib/mutations/index.d.ts +1 -0
- package/lib/mutations/index.d.ts.map +1 -0
- package/lib/mutations/index.js +29 -0
- package/lib/mutations/locations.d.ts +1 -0
- package/lib/mutations/locations.d.ts.map +1 -0
- package/lib/mutations/locations.js +22 -0
- package/lib/mutations/messages.d.ts +1 -0
- package/lib/mutations/messages.d.ts.map +1 -0
- package/lib/mutations/messages.js +75 -0
- package/lib/mutations/posts.d.ts +1 -0
- package/lib/mutations/posts.d.ts.map +1 -0
- package/lib/mutations/posts.js +31 -0
- package/lib/mutations/profiles.d.ts +1 -0
- package/lib/mutations/profiles.d.ts.map +1 -0
- package/lib/mutations/profiles.js +78 -0
- package/lib/mutations/reactions.d.ts +1 -0
- package/lib/mutations/reactions.d.ts.map +1 -0
- package/lib/mutations/reactions.js +29 -0
- package/lib/mutations/statistics.d.ts +1 -0
- package/lib/mutations/statistics.d.ts.map +1 -0
- package/lib/mutations/statistics.js +17 -0
- package/lib/mutations/subscriptions.d.ts +1 -0
- package/lib/mutations/subscriptions.d.ts.map +1 -0
- package/lib/mutations/subscriptions.js +38 -0
- package/lib/mutations/tags.d.ts +1 -0
- package/lib/mutations/tags.d.ts.map +1 -0
- package/lib/mutations/tags.js +109 -0
- package/lib/mutations/users.d.ts +1 -0
- package/lib/mutations/users.d.ts.map +1 -0
- package/lib/mutations/users.js +129 -0
- package/lib/objectTypes/app.d.ts +1 -0
- package/lib/objectTypes/app.d.ts.map +1 -0
- package/lib/objectTypes/app.js +147 -0
- package/lib/objectTypes/bankAccount.d.ts +1 -0
- package/lib/objectTypes/bankAccount.d.ts.map +1 -0
- package/lib/objectTypes/bankAccount.js +54 -0
- package/lib/objectTypes/connection.d.ts +1 -0
- package/lib/objectTypes/connection.d.ts.map +1 -0
- package/lib/objectTypes/connection.js +26 -0
- package/lib/objectTypes/content.d.ts +1 -0
- package/lib/objectTypes/content.d.ts.map +1 -0
- package/lib/objectTypes/content.js +79 -0
- package/lib/objectTypes/conversation.d.ts +1 -0
- package/lib/objectTypes/conversation.d.ts.map +1 -0
- package/lib/objectTypes/conversation.js +53 -0
- package/lib/objectTypes/creditCard.d.ts +1 -0
- package/lib/objectTypes/creditCard.d.ts.map +1 -0
- package/lib/objectTypes/creditCard.js +64 -0
- package/lib/objectTypes/document.d.ts +1 -0
- package/lib/objectTypes/document.d.ts.map +1 -0
- package/lib/objectTypes/document.js +21 -0
- package/lib/objectTypes/error.d.ts +1 -0
- package/lib/objectTypes/error.d.ts.map +1 -0
- package/lib/objectTypes/error.js +24 -0
- package/lib/objectTypes/external.d.ts +1 -0
- package/lib/objectTypes/external.d.ts.map +1 -0
- package/lib/objectTypes/external.js +52 -0
- package/lib/objectTypes/file.d.ts +1 -0
- package/lib/objectTypes/file.d.ts.map +1 -0
- package/lib/objectTypes/file.js +76 -0
- package/lib/objectTypes/filter.d.ts +1 -0
- package/lib/objectTypes/filter.d.ts.map +1 -0
- package/lib/objectTypes/filter.js +21 -0
- package/lib/objectTypes/group.d.ts +1 -0
- package/lib/objectTypes/group.d.ts.map +1 -0
- package/lib/objectTypes/group.js +97 -0
- package/lib/objectTypes/iapSubscription.d.ts +1 -0
- package/lib/objectTypes/iapSubscription.d.ts.map +1 -0
- package/lib/objectTypes/iapSubscription.js +18 -0
- package/lib/objectTypes/image.d.ts +1 -0
- package/lib/objectTypes/image.d.ts.map +1 -0
- package/lib/objectTypes/image.js +105 -0
- package/lib/objectTypes/index.d.ts +1 -0
- package/lib/objectTypes/index.d.ts.map +1 -0
- package/lib/objectTypes/index.js +28 -0
- package/lib/objectTypes/location.d.ts +1 -0
- package/lib/objectTypes/location.d.ts.map +1 -0
- package/lib/objectTypes/location.js +85 -0
- package/lib/objectTypes/message.d.ts +1 -0
- package/lib/objectTypes/message.d.ts.map +1 -0
- package/lib/objectTypes/message.js +72 -0
- package/lib/objectTypes/passcode.d.ts +1 -0
- package/lib/objectTypes/passcode.d.ts.map +1 -0
- package/lib/objectTypes/passcode.js +20 -0
- package/lib/objectTypes/plan.d.ts +1 -0
- package/lib/objectTypes/plan.d.ts.map +1 -0
- package/lib/objectTypes/plan.js +71 -0
- package/lib/objectTypes/post.d.ts +1 -0
- package/lib/objectTypes/post.d.ts.map +1 -0
- package/lib/objectTypes/post.js +101 -0
- package/lib/objectTypes/profile.d.ts +1 -0
- package/lib/objectTypes/profile.d.ts.map +1 -0
- package/lib/objectTypes/profile.js +68 -0
- package/lib/objectTypes/reaction.d.ts +1 -0
- package/lib/objectTypes/reaction.d.ts.map +1 -0
- package/lib/objectTypes/reaction.js +37 -0
- package/lib/objectTypes/relation.d.ts +1 -0
- package/lib/objectTypes/relation.d.ts.map +1 -0
- package/lib/objectTypes/relation.js +27 -0
- package/lib/objectTypes/search.d.ts +1 -0
- package/lib/objectTypes/search.d.ts.map +1 -0
- package/lib/objectTypes/search.js +50 -0
- package/lib/objectTypes/statistics.d.ts +1 -0
- package/lib/objectTypes/statistics.d.ts.map +1 -0
- package/lib/objectTypes/statistics.js +17 -0
- package/lib/objectTypes/subscription.d.ts +1 -0
- package/lib/objectTypes/subscription.d.ts.map +1 -0
- package/lib/objectTypes/subscription.js +102 -0
- package/lib/objectTypes/tag.d.ts +1 -0
- package/lib/objectTypes/tag.d.ts.map +1 -0
- package/lib/objectTypes/tag.js +41 -0
- package/lib/objectTypes/user.d.ts +1 -0
- package/lib/objectTypes/user.d.ts.map +1 -0
- package/lib/objectTypes/user.js +111 -0
- package/lib/queries/content.d.ts +1 -0
- package/lib/queries/content.d.ts.map +1 -0
- package/lib/queries/content.js +50 -0
- package/lib/queries/index.d.ts +1 -0
- package/lib/queries/index.d.ts.map +1 -0
- package/lib/queries/index.js +27 -0
- package/lib/queries/locations.d.ts +1 -0
- package/lib/queries/locations.d.ts.map +1 -0
- package/lib/queries/locations.js +23 -0
- package/lib/queries/messages.d.ts +1 -0
- package/lib/queries/messages.d.ts.map +1 -0
- package/lib/queries/messages.js +35 -0
- package/lib/queries/posts.d.ts +1 -0
- package/lib/queries/posts.d.ts.map +1 -0
- package/lib/queries/posts.js +154 -0
- package/lib/queries/reactions.d.ts +1 -0
- package/lib/queries/reactions.d.ts.map +1 -0
- package/lib/queries/reactions.js +34 -0
- package/lib/queries/statistics.d.ts +1 -0
- package/lib/queries/statistics.d.ts.map +1 -0
- package/lib/queries/statistics.js +17 -0
- package/lib/queries/subscriptions.d.ts +1 -0
- package/lib/queries/subscriptions.d.ts.map +1 -0
- package/lib/queries/subscriptions.js +21 -0
- package/lib/queries/tags.d.ts +1 -0
- package/lib/queries/tags.d.ts.map +1 -0
- package/lib/queries/tags.js +56 -0
- package/lib/queries/users.d.ts +1 -0
- package/lib/queries/users.d.ts.map +1 -0
- package/lib/queries/users.js +39 -0
- package/lib/templates/email/layout.d.ts +1 -0
- package/lib/templates/email/layout.d.ts.map +1 -0
- package/lib/templates/email/layout.js +281 -0
- package/lib/templates/email/passwordForgot.d.ts +1 -0
- package/lib/templates/email/passwordForgot.d.ts.map +1 -0
- package/lib/templates/email/passwordForgot.js +17 -0
- package/lib/templates/email/passwordRecovery.d.ts +1 -0
- package/lib/templates/email/passwordRecovery.d.ts.map +1 -0
- package/lib/templates/email/passwordRecovery.js +14 -0
- package/lib/templates/email/verifyEmail.d.ts +1 -0
- package/lib/templates/email/verifyEmail.d.ts.map +1 -0
- package/lib/templates/email/verifyEmail.js +17 -0
- package/lib/templates/email/welcome.d.ts +1 -0
- package/lib/templates/email/welcome.d.ts.map +1 -0
- package/lib/templates/email/welcome.js +17 -0
- package/lib/templates/sms/passwordForgot.d.ts +1 -0
- package/lib/templates/sms/passwordForgot.d.ts.map +1 -0
- package/lib/templates/sms/passwordForgot.js +3 -0
- package/lib/templates/sms/passwordRecovery.d.ts +1 -0
- package/lib/templates/sms/passwordRecovery.d.ts.map +1 -0
- package/lib/templates/sms/passwordRecovery.js +3 -0
- package/lib/templates/sms/verifyEmail.d.ts +1 -0
- package/lib/templates/sms/verifyEmail.d.ts.map +1 -0
- package/lib/templates/sms/verifyEmail.js +3 -0
- package/lib/templates/sms/verifyPhone.d.ts +1 -0
- package/lib/templates/sms/verifyPhone.d.ts.map +1 -0
- package/lib/templates/sms/verifyPhone.js +3 -0
- package/lib/templates/sms/welcome.d.ts +1 -0
- package/lib/templates/sms/welcome.d.ts.map +1 -0
- package/lib/templates/sms/welcome.js +3 -0
- package/lib/types/apps.types.d.ts +1 -0
- package/lib/types/apps.types.d.ts.map +1 -0
- package/lib/types/apps.types.js +10 -0
- package/lib/types/arangodb.types.d.ts +1 -0
- package/lib/types/arangodb.types.d.ts.map +1 -0
- package/lib/types/arangodb.types.js +6 -0
- package/lib/types/auth.types.d.ts +1 -0
- package/lib/types/auth.types.d.ts.map +1 -0
- package/lib/types/auth.types.js +6 -0
- package/lib/types/connections.types.d.ts +1 -0
- package/lib/types/connections.types.d.ts.map +1 -0
- package/lib/types/connections.types.js +6 -0
- package/lib/types/content.types.d.ts +1 -0
- package/lib/types/content.types.d.ts.map +1 -0
- package/lib/types/content.types.js +6 -0
- package/lib/types/conversations.types.d.ts +1 -0
- package/lib/types/conversations.types.d.ts.map +1 -0
- package/lib/types/conversations.types.js +6 -0
- package/lib/types/email.types.d.ts +1 -0
- package/lib/types/email.types.d.ts.map +1 -0
- package/lib/types/email.types.js +6 -0
- package/lib/types/error.types.d.ts +1 -0
- package/lib/types/error.types.d.ts.map +1 -0
- package/lib/types/error.types.js +20 -0
- package/lib/types/files.types.d.ts +1 -0
- package/lib/types/files.types.d.ts.map +1 -0
- package/lib/types/files.types.js +6 -0
- package/lib/types/google.types.d.ts +1 -0
- package/lib/types/google.types.d.ts.map +1 -0
- package/lib/types/google.types.js +6 -0
- package/lib/types/groups.types.d.ts +1 -0
- package/lib/types/groups.types.d.ts.map +1 -0
- package/lib/types/groups.types.js +6 -0
- package/lib/types/images.types.d.ts +1 -0
- package/lib/types/images.types.d.ts.map +1 -0
- package/lib/types/images.types.js +6 -0
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.d.ts.map +1 -0
- package/lib/types/index.js +28 -0
- package/lib/types/locations.types.d.ts +1 -0
- package/lib/types/locations.types.d.ts.map +1 -0
- package/lib/types/locations.types.js +6 -0
- package/lib/types/messages.types.d.ts +1 -0
- package/lib/types/messages.types.d.ts.map +1 -0
- package/lib/types/messages.types.js +6 -0
- package/lib/types/notifications.types.d.ts +1 -0
- package/lib/types/notifications.types.d.ts.map +1 -0
- package/lib/types/notifications.types.js +6 -0
- package/lib/types/payments.types.d.ts +1 -0
- package/lib/types/payments.types.d.ts.map +1 -0
- package/lib/types/payments.types.js +6 -0
- package/lib/types/posts.types.d.ts +1 -0
- package/lib/types/posts.types.d.ts.map +1 -0
- package/lib/types/posts.types.js +6 -0
- package/lib/types/profiles.types.d.ts +1 -0
- package/lib/types/profiles.types.d.ts.map +1 -0
- package/lib/types/profiles.types.js +3 -0
- package/lib/types/statistics.types.d.ts +1 -0
- package/lib/types/statistics.types.d.ts.map +1 -0
- package/lib/types/statistics.types.js +3 -0
- package/lib/types/tags.types.d.ts +1 -0
- package/lib/types/tags.types.d.ts.map +1 -0
- package/lib/types/tags.types.js +6 -0
- package/lib/types/users.types.d.ts +1 -0
- package/lib/types/users.types.d.ts.map +1 -0
- package/lib/types/users.types.js +6 -0
- package/lib/types/videos.types.d.ts +1 -0
- package/lib/types/videos.types.d.ts.map +1 -0
- package/lib/types/videos.types.js +6 -0
- package/lib/types/websockets.types.d.ts +1 -0
- package/lib/types/websockets.types.d.ts.map +1 -0
- package/lib/types/websockets.types.js +6 -0
- package/lib/utils/adapterUtils.d.ts +1 -0
- package/lib/utils/adapterUtils.d.ts.map +1 -0
- package/lib/utils/adapterUtils.js +23 -0
- package/lib/utils/analyticsUtils.d.ts +1 -0
- package/lib/utils/analyticsUtils.d.ts.map +1 -0
- package/lib/utils/analyticsUtils.js +45 -0
- package/lib/utils/arangodbUtils.d.ts +1 -0
- package/lib/utils/arangodbUtils.d.ts.map +1 -0
- package/lib/utils/arangodbUtils.js +130 -0
- package/lib/utils/authUtils.d.ts +1 -0
- package/lib/utils/authUtils.d.ts.map +1 -0
- package/lib/utils/authUtils.js +54 -0
- package/lib/utils/contextUtils.d.ts +1 -0
- package/lib/utils/contextUtils.d.ts.map +1 -0
- package/lib/utils/contextUtils.js +10 -0
- package/lib/utils/dbI18n.d.ts +1 -0
- package/lib/utils/dbI18n.d.ts.map +1 -0
- package/lib/utils/dbI18n.example.d.ts +1 -0
- package/lib/utils/dbI18n.example.d.ts.map +1 -0
- package/lib/utils/dbI18n.example.js +93 -0
- package/lib/utils/dbI18n.js +28 -0
- package/lib/utils/googleTranslate.d.ts +1 -0
- package/lib/utils/googleTranslate.d.ts.map +1 -0
- package/lib/utils/googleTranslate.js +70 -0
- package/lib/utils/graphqlUtils.d.ts +1 -0
- package/lib/utils/graphqlUtils.d.ts.map +1 -0
- package/lib/utils/graphqlUtils.js +11 -0
- package/lib/utils/index.d.ts +1 -0
- package/lib/utils/index.d.ts.map +1 -0
- package/lib/utils/index.js +19 -0
- package/lib/utils/languageDetection.d.ts +1 -0
- package/lib/utils/languageDetection.d.ts.map +1 -0
- package/lib/utils/languageDetection.js +120 -0
- package/lib/utils/localeUtils.d.ts +1 -0
- package/lib/utils/localeUtils.d.ts.map +1 -0
- package/lib/utils/localeUtils.example.d.ts +1 -0
- package/lib/utils/localeUtils.example.d.ts.map +1 -0
- package/lib/utils/localeUtils.example.js +124 -0
- package/lib/utils/localeUtils.js +71 -0
- package/lib/utils/middlewareUtils.d.ts +1 -0
- package/lib/utils/middlewareUtils.d.ts.map +1 -0
- package/lib/utils/middlewareUtils.js +10 -0
- package/lib/utils/sessionUtils.d.ts +1 -0
- package/lib/utils/sessionUtils.d.ts.map +1 -0
- package/lib/utils/sessionUtils.js +26 -0
- package/lib/utils/stripeUtils.d.ts +2 -1
- package/lib/utils/stripeUtils.d.ts.map +1 -0
- package/lib/utils/stripeUtils.js +12 -0
- package/lib/utils/templateUtils.d.ts +1 -0
- package/lib/utils/templateUtils.d.ts.map +1 -0
- package/lib/utils/templateUtils.js +11 -0
- package/lib/utils/testUtils.d.ts +1 -0
- package/lib/utils/testUtils.d.ts.map +1 -0
- package/lib/utils/testUtils.js +292 -0
- package/lib/utils/translationQueue.d.ts +1 -0
- package/lib/utils/translationQueue.d.ts.map +1 -0
- package/lib/utils/translationQueue.example.d.ts +1 -0
- package/lib/utils/translationQueue.example.d.ts.map +1 -0
- package/lib/utils/translationQueue.example.js +340 -0
- package/lib/utils/translationQueue.js +113 -0
- package/package.json +54 -24
- package/.env +0 -1
- package/.env.example +0 -1
- package/DATABASE_I18N_GUIDE.md +0 -434
- package/TEST_UTILITIES_GUIDE.md +0 -360
- package/coverage/actions/groups.ts.html +0 -1039
- package/coverage/actions/images.ts.html +0 -2500
- package/coverage/actions/index.html +0 -116
- package/coverage/actions/notifications.ts.html +0 -223
- package/coverage/actions/posts.ts.html +0 -2356
- package/coverage/actions/tags.ts.html +0 -1000
- package/coverage/adapters/arangoAdapter.ts.html +0 -301
- package/coverage/adapters/fileAdapter.ts.html +0 -445
- package/coverage/adapters/index.html +0 -176
- package/coverage/adapters/postAdapter.ts.html +0 -436
- package/coverage/adapters/reaktorAdapter.ts.html +0 -310
- package/coverage/adapters/tagAdapter.ts.html +0 -409
- package/coverage/adapters/userAdapter.ts.html +0 -829
- package/coverage/analyticsUtils.ts.html +0 -286
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -6
- package/coverage/config.ts.html +0 -766
- package/coverage/coverage-final.json +0 -1
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -221
- package/coverage/lcov-report/base.css +0 -224
- package/coverage/lcov-report/block-navigation.js +0 -87
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +0 -101
- package/coverage/lcov-report/prettify.css +0 -1
- package/coverage/lcov-report/prettify.js +0 -2
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +0 -196
- package/coverage/lcov.info +0 -0
- package/coverage/mocks/file.ts.html +0 -118
- package/coverage/mocks/group.ts.html +0 -145
- package/coverage/mocks/image.ts.html +0 -142
- package/coverage/mocks/index.html +0 -176
- package/coverage/mocks/post.ts.html +0 -169
- package/coverage/mocks/tag.ts.html +0 -121
- package/coverage/mocks/user.ts.html +0 -271
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -210
- package/coverage/testUtils.ts.html +0 -1309
- package/coverage/translationQueue.ts.html +0 -592
- package/coverage/types/error.ts.html +0 -145
- package/coverage/types/error.types.ts.html +0 -148
- package/coverage/types/index.html +0 -116
- package/coverage/utils/adapterUtils.ts.html +0 -163
- package/coverage/utils/analyticsUtils.ts.html +0 -286
- package/coverage/utils/arangodbUtils.ts.html +0 -463
- package/coverage/utils/authUtils.ts.html +0 -328
- package/coverage/utils/dbI18n.ts.html +0 -280
- package/coverage/utils/googleTranslate.ts.html +0 -385
- package/coverage/utils/index.html +0 -131
- package/coverage/utils/localeUtils.ts.html +0 -193
- package/coverage/utils/sessionUtils.ts.html +0 -211
- package/coverage/utils/testUtils.ts.html +0 -1309
- package/index.js +0 -5
- package/jpg:- +0 -0
- package/lex.config.mjs +0 -34
- package/tsconfig.build.json +0 -21
- package/tsconfig.lint.json +0 -33
- package/tsconfig.test.json +0 -31
|
@@ -0,0 +1,608 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2019-Present, Nitrogen Labs, Inc.
|
|
3
|
+
* Copyrights licensed under the MIT License. See the accompanying LICENSE file for terms.
|
|
4
|
+
*/ import { parseNum } from '@nlabs/utils/parsers/numbers';
|
|
5
|
+
import { createHash, parseArangoId, parseChar, parseId, parseString, parseVarChar } from '@nlabs/utils/parsers/strings';
|
|
6
|
+
import { aql } from 'arangojs';
|
|
7
|
+
import { parsePost } from '../adapters/postAdapter.js';
|
|
8
|
+
import { ErrorTypes } from '../types/error.types.js';
|
|
9
|
+
import { logError, logException } from '../utils/analyticsUtils.js';
|
|
10
|
+
import { getLimit, useDb } from '../utils/arangodbUtils.js';
|
|
11
|
+
import { extractTags, getTagsByName, updateTagsInItem } from './tags.js';
|
|
12
|
+
const MAX_CONTENT_LENGTH = 100000;
|
|
13
|
+
const eventCategory = 'posts';
|
|
14
|
+
export const parsePostOptions = (options = {})=>{
|
|
15
|
+
const { from = 0, latitude = 0, longitude = 0, to = 30, type = 'post' } = options;
|
|
16
|
+
return {
|
|
17
|
+
latitude: parseNum(latitude, 32),
|
|
18
|
+
limit: getLimit(from, to),
|
|
19
|
+
longitude: parseNum(longitude, 32),
|
|
20
|
+
type: parseChar(type, 32)
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
export const getPostOptional = (fields = [], sessionId = '')=>(fields || []).reduce((selects, field)=>{
|
|
24
|
+
switch(field){
|
|
25
|
+
case 'hasRsvp':
|
|
26
|
+
{
|
|
27
|
+
selects.queries.push(`LET hasRsvp = TO_BOOL(FIRST(
|
|
28
|
+
FOR post, r IN INBOUND p._id hasReaction
|
|
29
|
+
FILTER r.name == "rsvp" && r.type == "posts" && r._from == "users/${sessionId}"
|
|
30
|
+
COLLECT WITH COUNT INTO count
|
|
31
|
+
RETURN count
|
|
32
|
+
))`);
|
|
33
|
+
selects.objects.push('hasRsvp:hasRsvp');
|
|
34
|
+
return selects;
|
|
35
|
+
}
|
|
36
|
+
case 'isSaved':
|
|
37
|
+
{
|
|
38
|
+
selects.queries.push(`LET isSaved = TO_BOOL(FIRST(
|
|
39
|
+
FOR post, r IN INBOUND p._id hasReaction
|
|
40
|
+
FILTER r.name == "pin" && r.type == "posts" && r._from == "users/${sessionId}"
|
|
41
|
+
COLLECT WITH COUNT INTO count
|
|
42
|
+
RETURN count
|
|
43
|
+
))`);
|
|
44
|
+
selects.objects.push('isSaved:isSaved');
|
|
45
|
+
return selects;
|
|
46
|
+
}
|
|
47
|
+
case 'reactions':
|
|
48
|
+
{
|
|
49
|
+
selects.queries.push(`LET reactions = (
|
|
50
|
+
FOR post, r IN INBOUND p._id hasReaction
|
|
51
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
52
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
53
|
+
)`);
|
|
54
|
+
selects.objects.push('reactions:reactions');
|
|
55
|
+
return selects;
|
|
56
|
+
}
|
|
57
|
+
case 'rsvpCount':
|
|
58
|
+
{
|
|
59
|
+
selects.queries.push(`LET rsvpCount = FIRST(
|
|
60
|
+
FOR post, r IN INBOUND p._id hasReaction
|
|
61
|
+
FILTER r.name == "rsvp" && r.type == "posts"
|
|
62
|
+
COLLECT WITH COUNT INTO count
|
|
63
|
+
RETURN count
|
|
64
|
+
)`);
|
|
65
|
+
selects.objects.push('rsvpCount:rsvpCount');
|
|
66
|
+
return selects;
|
|
67
|
+
}
|
|
68
|
+
case 'viewCount':
|
|
69
|
+
{
|
|
70
|
+
selects.queries.push(`LET viewCount = FIRST(
|
|
71
|
+
FOR post, r IN INBOUND p._id hasReaction
|
|
72
|
+
FILTER r.name == "view" && r.type == "posts"
|
|
73
|
+
COLLECT WITH COUNT INTO count
|
|
74
|
+
RETURN count
|
|
75
|
+
)`);
|
|
76
|
+
selects.objects.push('viewCount:viewCount');
|
|
77
|
+
return selects;
|
|
78
|
+
}
|
|
79
|
+
default:
|
|
80
|
+
{
|
|
81
|
+
return selects;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}, {
|
|
85
|
+
objects: [],
|
|
86
|
+
queries: []
|
|
87
|
+
});
|
|
88
|
+
export const getPost = async (context, postId, options)=>{
|
|
89
|
+
const action = 'getPost';
|
|
90
|
+
const { databaseName, fields, session: { userId: sessionId } = {} } = context;
|
|
91
|
+
const formatItemId = parseId(postId);
|
|
92
|
+
const { type } = parsePostOptions(options);
|
|
93
|
+
const database = useDb(databaseName);
|
|
94
|
+
const { objects: selectObjects, queries: selectQueries } = getPostOptional(fields, sessionId);
|
|
95
|
+
const aqlQry = aql`FOR p IN posts
|
|
96
|
+
FILTER p._key == ${formatItemId} && p.type == ${type}
|
|
97
|
+
LIMIT 1
|
|
98
|
+
RETURN p`;
|
|
99
|
+
return database.query(aqlQry).then((cursor)=>cursor.next()).then((post)=>{
|
|
100
|
+
const { _id: postDocId, userId, groupId, privacy = 'default' } = post;
|
|
101
|
+
let privacyAqlQry;
|
|
102
|
+
if (userId === sessionId) {
|
|
103
|
+
return post;
|
|
104
|
+
}
|
|
105
|
+
if (groupId && privacy === 'group') {
|
|
106
|
+
privacyAqlQry = `LET p = DOCUMENT("${postDocId}")
|
|
107
|
+
${selectQueries.join('\n')}
|
|
108
|
+
FOR group IN groups
|
|
109
|
+
FILTER group._key == p.groupId
|
|
110
|
+
FOR u, e IN OUTBOUND group._id hasConnection
|
|
111
|
+
FILTER u._key == "${sessionId}"
|
|
112
|
+
LIMIT 1
|
|
113
|
+
RETURN MERGE(p, {${selectObjects.join(', ')}})`;
|
|
114
|
+
} else if (privacy === 'public') {
|
|
115
|
+
privacyAqlQry = `LET p = DOCUMENT("${postDocId}")
|
|
116
|
+
${selectQueries.join('\n')}
|
|
117
|
+
LIMIT 1
|
|
118
|
+
RETURN MERGE(p, {${selectObjects.join(', ')}})`;
|
|
119
|
+
}
|
|
120
|
+
if (privacyAqlQry) {
|
|
121
|
+
return database.query(privacyAqlQry).then((cursor)=>cursor.next()).catch((error)=>logError({
|
|
122
|
+
action,
|
|
123
|
+
category: eventCategory,
|
|
124
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
125
|
+
}, error, context));
|
|
126
|
+
}
|
|
127
|
+
return {};
|
|
128
|
+
}).catch((error)=>logError({
|
|
129
|
+
action,
|
|
130
|
+
category: eventCategory,
|
|
131
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
132
|
+
}, error, context));
|
|
133
|
+
};
|
|
134
|
+
// export const getPostList = (context: ApiContext, options?: PostOptions): Promise<PostType[]> => {
|
|
135
|
+
// // const action: string = 'getListByApp';
|
|
136
|
+
// const {database, fields, session: {userId: sessionId}} = context;
|
|
137
|
+
// const {limit, type} = parsePostOptions(options);
|
|
138
|
+
// const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields, sessionId);
|
|
139
|
+
// const aqlQry: string = `FOR p IN posts
|
|
140
|
+
// FILTER p.type == "${type}" && p.privacy == "public" && p.parent == null
|
|
141
|
+
// ${selectQueries.join('\n')}
|
|
142
|
+
// ${limit.aql}
|
|
143
|
+
// SORT p.added
|
|
144
|
+
// RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
145
|
+
// return database.query(aqlQry)
|
|
146
|
+
// .then((cursor) => cursor.all())
|
|
147
|
+
// .catch((error: Error) => {
|
|
148
|
+
// throw error;
|
|
149
|
+
// });
|
|
150
|
+
// };
|
|
151
|
+
export const getPostsByArea = (context, latitude, longitude, options)=>{
|
|
152
|
+
const action = 'getPostsByArea';
|
|
153
|
+
const { databaseName, fields, session: { userId: sessionId } = {} } = context;
|
|
154
|
+
const { limit, type } = parsePostOptions(options);
|
|
155
|
+
const formatLatitude = parseNum(latitude);
|
|
156
|
+
const formatLongitude = parseNum(longitude);
|
|
157
|
+
const { objects: selectObjects, queries: selectQueries } = getPostOptional(fields, sessionId);
|
|
158
|
+
selectQueries.push(`LET distance = DISTANCE(
|
|
159
|
+
${formatLatitude},
|
|
160
|
+
${formatLongitude},
|
|
161
|
+
NOT_NULL(p.latitude, 0),
|
|
162
|
+
NOT_NULL(p.longitude, 0))
|
|
163
|
+
`);
|
|
164
|
+
selectObjects.push('distance:distance');
|
|
165
|
+
const aqlQry = `FOR p IN posts
|
|
166
|
+
${selectQueries.join('\n')}
|
|
167
|
+
FILTER p.type == "${type}" && p.privacy == "public" && p.parentId == null
|
|
168
|
+
${limit.aql}
|
|
169
|
+
SORT distance, p.added
|
|
170
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
171
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
|
|
172
|
+
logError({
|
|
173
|
+
action,
|
|
174
|
+
category: eventCategory,
|
|
175
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
176
|
+
}, error, context);
|
|
177
|
+
return [];
|
|
178
|
+
});
|
|
179
|
+
};
|
|
180
|
+
// export const getPostsByGroup = (
|
|
181
|
+
// context: ApiContext,
|
|
182
|
+
// groupId: string,
|
|
183
|
+
// options?: PostOptions
|
|
184
|
+
// ): Promise<PostType[]> => {
|
|
185
|
+
// // const action: string = 'getListByGroup';
|
|
186
|
+
// const {database, fields, session: {userId: sessionId}} = context;
|
|
187
|
+
// const {objects: selectObjects, queries: selectQueries} = getPostOptional(fields, sessionId);
|
|
188
|
+
// // Group id
|
|
189
|
+
// const formatGroupId: string = parseId(groupId);
|
|
190
|
+
// const db = database;
|
|
191
|
+
// const aqlQry: string = `FOR u, g IN INBOUND ${formatGroupId} hasGroup
|
|
192
|
+
// FILTER u._key == ${sessionId}
|
|
193
|
+
// RETURN g`;
|
|
194
|
+
// return db.query(aqlQry)
|
|
195
|
+
// .then((cursor) => cursor.all())
|
|
196
|
+
// .then((groups: GroupType[] = []) => {
|
|
197
|
+
// if(groups.length) {
|
|
198
|
+
// const {limit, type} = parsePostOptions(options);
|
|
199
|
+
// const postAqlQry: string = `FOR p IN posts
|
|
200
|
+
// FILTER p.type == "${type}" && p.groupId == "${formatGroupId}" && p.parent == null
|
|
201
|
+
// ${selectQueries.join('\n')}
|
|
202
|
+
// ${limit.aql}
|
|
203
|
+
// SORT p.added
|
|
204
|
+
// RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
205
|
+
// return db.query(postAqlQry)
|
|
206
|
+
// .then((cursor) => cursor.all())
|
|
207
|
+
// .catch((error: Error) => {
|
|
208
|
+
// throw error;
|
|
209
|
+
// });
|
|
210
|
+
// }
|
|
211
|
+
// return [];
|
|
212
|
+
// })
|
|
213
|
+
// .catch((error: Error) => {
|
|
214
|
+
// throw error;
|
|
215
|
+
// });
|
|
216
|
+
// };
|
|
217
|
+
export const getPostsByLatest = (context, options)=>{
|
|
218
|
+
// const action: string = 'getListByLatest';
|
|
219
|
+
const { databaseName, fields, session: { userId: sessionId } = {} } = context;
|
|
220
|
+
const { limit, type } = parsePostOptions(options);
|
|
221
|
+
const { objects: selectObjects, queries: selectQueries } = getPostOptional(fields, sessionId);
|
|
222
|
+
const aqlQry = `FOR p IN posts
|
|
223
|
+
FILTER p.type == "${type}" && p.privacy == "public" && p.parent == null
|
|
224
|
+
${selectQueries.join('\n')}
|
|
225
|
+
${limit.aql}
|
|
226
|
+
SORT p.added DESC
|
|
227
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
228
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
|
|
229
|
+
throw error;
|
|
230
|
+
});
|
|
231
|
+
};
|
|
232
|
+
export const getPostsByReactions = (context, reactions = [], options)=>{
|
|
233
|
+
const action = 'getPostsByReactions';
|
|
234
|
+
const { databaseName, fields, session: { userId: sessionId } = {} } = context;
|
|
235
|
+
const { latitude, limit, longitude, type } = parsePostOptions(options);
|
|
236
|
+
const { objects: selectObjects, queries: selectQueries } = getPostOptional(fields, sessionId);
|
|
237
|
+
const formatSessionId = `users/${sessionId}`;
|
|
238
|
+
const formatReactions = JSON.stringify(reactions.map((reaction)=>parseChar(reaction, 32).toLowerCase()));
|
|
239
|
+
const sortBy = [];
|
|
240
|
+
const filters = [
|
|
241
|
+
`p.type == "${type}"`,
|
|
242
|
+
'p.privacy == "public"'
|
|
243
|
+
];
|
|
244
|
+
const formatLatitude = parseNum(latitude);
|
|
245
|
+
const formatLongitude = parseNum(longitude);
|
|
246
|
+
if (formatLatitude && formatLongitude) {
|
|
247
|
+
selectQueries.push(`LET distance = DISTANCE(
|
|
248
|
+
${formatLatitude},
|
|
249
|
+
${formatLongitude},
|
|
250
|
+
NOT_NULL(p.latitude, 0),
|
|
251
|
+
NOT_NULL(p.longitude, 0))
|
|
252
|
+
`);
|
|
253
|
+
selectObjects.push('distance:distance');
|
|
254
|
+
sortBy.push('distance');
|
|
255
|
+
}
|
|
256
|
+
if (reactions.length) {
|
|
257
|
+
sortBy.push('matchedTags DESC');
|
|
258
|
+
selectQueries.push(`LET matchedReactions = LENGTH(
|
|
259
|
+
FOR mr IN reactions
|
|
260
|
+
FILTER mr.matched == true
|
|
261
|
+
RETURN mr
|
|
262
|
+
)`);
|
|
263
|
+
selectObjects.push('matchedReactions:matchedReactions');
|
|
264
|
+
filters.push('matchedReactions > 0');
|
|
265
|
+
}
|
|
266
|
+
sortBy.push('p.added DESC');
|
|
267
|
+
selectObjects.push('reactions:reactions');
|
|
268
|
+
// Get data from database
|
|
269
|
+
const aqlQry = `FOR p, r IN OUTBOUND "${formatSessionId}" hasReaction
|
|
270
|
+
LET reactions = (
|
|
271
|
+
FOR reaction, hr IN 1..1 INBOUND p isTagged
|
|
272
|
+
LET matched = LENGTH(${formatReactions}) > 0 && POSITION(${formatReactions}, reaction.name)
|
|
273
|
+
SORT reaction.name
|
|
274
|
+
RETURN MERGE(reaction, {matched:matched})
|
|
275
|
+
)
|
|
276
|
+
${selectQueries.join('\n')}
|
|
277
|
+
FILTER ${filters.join(' && ')}
|
|
278
|
+
${limit.aql}
|
|
279
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
280
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
|
|
281
|
+
logError({
|
|
282
|
+
action,
|
|
283
|
+
category: eventCategory,
|
|
284
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
285
|
+
}, error, context);
|
|
286
|
+
return [];
|
|
287
|
+
});
|
|
288
|
+
};
|
|
289
|
+
export const getPostsByTags = (context, tags = [], options)=>{
|
|
290
|
+
const action = 'getPostsByTags';
|
|
291
|
+
const { databaseName, fields, session: { userId: sessionId } = {} } = context;
|
|
292
|
+
const { latitude, limit, longitude, type } = parsePostOptions(options);
|
|
293
|
+
const { objects: selectObjects, queries: selectQueries } = getPostOptional(fields, sessionId);
|
|
294
|
+
const formatTagNames = JSON.stringify(tags.map((tag)=>parseChar(tag, 32).toLowerCase()));
|
|
295
|
+
const sortBy = [];
|
|
296
|
+
const filters = [
|
|
297
|
+
`p.type == "${type}"`,
|
|
298
|
+
'p.privacy == "public"'
|
|
299
|
+
];
|
|
300
|
+
const formatLatitude = parseNum(latitude);
|
|
301
|
+
const formatLongitude = parseNum(longitude);
|
|
302
|
+
if (formatLatitude && formatLongitude) {
|
|
303
|
+
selectQueries.push(`LET distance = DISTANCE(
|
|
304
|
+
${formatLatitude},
|
|
305
|
+
${formatLongitude},
|
|
306
|
+
NOT_NULL(p.latitude, 0),
|
|
307
|
+
NOT_NULL(p.longitude, 0))
|
|
308
|
+
`);
|
|
309
|
+
selectObjects.push('distance:distance');
|
|
310
|
+
sortBy.push('distance');
|
|
311
|
+
}
|
|
312
|
+
if (tags.length) {
|
|
313
|
+
sortBy.push('matchedTags DESC');
|
|
314
|
+
selectQueries.push(`LET matchedTags = LENGTH(
|
|
315
|
+
FOR t IN tags
|
|
316
|
+
FILTER t.matched == true
|
|
317
|
+
RETURN t
|
|
318
|
+
)`);
|
|
319
|
+
selectObjects.push('matchedTags:matchedTags');
|
|
320
|
+
filters.push('matchedTags > 0');
|
|
321
|
+
}
|
|
322
|
+
sortBy.push('p.added DESC');
|
|
323
|
+
selectObjects.push('tags:tags');
|
|
324
|
+
const aqlQry = `FOR p IN posts
|
|
325
|
+
LET tags = (
|
|
326
|
+
FOR tag, it IN 1..1 INBOUND p isTagged
|
|
327
|
+
LET matched = LENGTH(${formatTagNames}) > 0 && POSITION(${formatTagNames}, tag.name)
|
|
328
|
+
SORT tag.name
|
|
329
|
+
RETURN MERGE(tag, {matched:matched})
|
|
330
|
+
)
|
|
331
|
+
${selectQueries.join('\n')}
|
|
332
|
+
FILTER ${filters.join(' && ')}
|
|
333
|
+
${limit.aql}
|
|
334
|
+
SORT ${sortBy.join(', ')}
|
|
335
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
336
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
|
|
337
|
+
logError({
|
|
338
|
+
action,
|
|
339
|
+
category: eventCategory,
|
|
340
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
341
|
+
}, error, context);
|
|
342
|
+
return [];
|
|
343
|
+
});
|
|
344
|
+
};
|
|
345
|
+
export const getPostsByUser = (context, userId, options)=>{
|
|
346
|
+
const action = 'getPostsByUser';
|
|
347
|
+
const { databaseName, fields, session: { userId: sessionId } = {} } = context;
|
|
348
|
+
const { limit, type } = parsePostOptions(options);
|
|
349
|
+
const formatUserId = parseId(userId);
|
|
350
|
+
const { objects: selectObjects, queries: selectQueries } = getPostOptional(fields, sessionId);
|
|
351
|
+
const aqlQry = `FOR p IN posts
|
|
352
|
+
FILTER p.userId == "${formatUserId}" && p.type == "${type}" && p.privacy == "public" && p.parent == null
|
|
353
|
+
${selectQueries.join('\n')}
|
|
354
|
+
${limit.aql}
|
|
355
|
+
SORT p.added
|
|
356
|
+
RETURN DISTINCT MERGE(p, {${selectObjects.join(', ')}})`;
|
|
357
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.all()).catch((error)=>{
|
|
358
|
+
logError({
|
|
359
|
+
action,
|
|
360
|
+
category: eventCategory,
|
|
361
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
362
|
+
}, error, context);
|
|
363
|
+
return [];
|
|
364
|
+
});
|
|
365
|
+
};
|
|
366
|
+
export const getPostComments = (context, postId, options)=>{
|
|
367
|
+
const action = 'getPostComments';
|
|
368
|
+
const { databaseName, session: { userId: sessionId } = {} } = context;
|
|
369
|
+
const { limit, type } = parsePostOptions(options);
|
|
370
|
+
const formatItemId = parseId(postId);
|
|
371
|
+
// Get the parent post to get restrictions
|
|
372
|
+
const aqlQry = aql`FOR p IN posts
|
|
373
|
+
FILTER p.type == ${type} && p._key == ${formatItemId}
|
|
374
|
+
LIMIT 1
|
|
375
|
+
RETURN p`;
|
|
376
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).then((post)=>{
|
|
377
|
+
const { _key, groupId, privacy = 'default' } = post;
|
|
378
|
+
// Query based on privacy level
|
|
379
|
+
let privacyAqlQry;
|
|
380
|
+
if (groupId && privacy === 'group') {
|
|
381
|
+
privacyAqlQry = `FOR p IN posts
|
|
382
|
+
FOR user IN users
|
|
383
|
+
FILTER p.parent == "${_key}" && user._key == p.userId
|
|
384
|
+
LET reactions = (
|
|
385
|
+
FOR post, r IN INBOUND p._id reactions
|
|
386
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
387
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
388
|
+
)
|
|
389
|
+
FOR group IN groups
|
|
390
|
+
FILTER group._key == p.groupId
|
|
391
|
+
FOR u, e IN OUTBOUND group._id hasConnection
|
|
392
|
+
FILTER u._key == "${sessionId}"
|
|
393
|
+
SORT p.added
|
|
394
|
+
${limit.aql}
|
|
395
|
+
RETURN MERGE(p, {user: user, reactions: reactions})`;
|
|
396
|
+
} else if (privacy === 'public') {
|
|
397
|
+
privacyAqlQry = `FOR p IN posts
|
|
398
|
+
FOR user IN users
|
|
399
|
+
FILTER p.parent == "${_key}" && user._key == p.userId
|
|
400
|
+
LET reactions = (
|
|
401
|
+
FOR post, r IN INBOUND p._id reactions
|
|
402
|
+
COLLECT reactionName = r.value INTO reactionItems
|
|
403
|
+
RETURN {name: reactionName, count: LENGTH(reactionItems[*].r.value)}
|
|
404
|
+
)
|
|
405
|
+
SORT p.added
|
|
406
|
+
${limit.aql}
|
|
407
|
+
RETURN MERGE(p, {user: user, reactions: reactions})`;
|
|
408
|
+
}
|
|
409
|
+
if (privacyAqlQry) {
|
|
410
|
+
return useDb(databaseName).query(privacyAqlQry).then((cursor)=>cursor.all()).catch((error)=>{
|
|
411
|
+
logError({
|
|
412
|
+
action,
|
|
413
|
+
category: eventCategory,
|
|
414
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
415
|
+
}, error, context);
|
|
416
|
+
return [];
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
return [];
|
|
420
|
+
}).catch((error)=>{
|
|
421
|
+
logError({
|
|
422
|
+
action,
|
|
423
|
+
category: eventCategory,
|
|
424
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
425
|
+
}, error, context);
|
|
426
|
+
return [];
|
|
427
|
+
});
|
|
428
|
+
};
|
|
429
|
+
export const addPost = async (context, { content = '', endDate, groupId = '', location, latitude, longitude, name = '', parentId = '', privacy = 'public', tags = [], startDate, type = 'default' })=>{
|
|
430
|
+
const action = 'addPost';
|
|
431
|
+
const { databaseName, session: { userId: sessionId } = {} } = context;
|
|
432
|
+
const now = Date.now();
|
|
433
|
+
const postId = createHash(`post-${sessionId}`);
|
|
434
|
+
const insert = {
|
|
435
|
+
_id: `posts/${postId}`,
|
|
436
|
+
_key: postId,
|
|
437
|
+
added: now,
|
|
438
|
+
content: parseString(content, MAX_CONTENT_LENGTH) || '',
|
|
439
|
+
endDate: endDate ? parseNum(endDate, 13) : undefined,
|
|
440
|
+
groupId: groupId ? parseId(groupId) : undefined,
|
|
441
|
+
latitude: latitude !== undefined ? parseNum(latitude) : undefined,
|
|
442
|
+
location: location ? parseString(location, 160) : undefined,
|
|
443
|
+
longitude: longitude !== undefined ? parseNum(longitude) : undefined,
|
|
444
|
+
modified: now,
|
|
445
|
+
name: parseString(name, 160),
|
|
446
|
+
parentId: parentId ? parseId(parentId) : undefined,
|
|
447
|
+
privacy: parseVarChar(privacy, 16),
|
|
448
|
+
startDate: startDate ? parseNum(startDate, 13) : undefined,
|
|
449
|
+
type: parseChar(type, 32),
|
|
450
|
+
userId: sessionId
|
|
451
|
+
};
|
|
452
|
+
const aqlQry = aql`INSERT ${insert} IN posts RETURN NEW`;
|
|
453
|
+
try {
|
|
454
|
+
const savedPost = await useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).catch((error)=>logError({
|
|
455
|
+
action,
|
|
456
|
+
category: eventCategory,
|
|
457
|
+
label: ErrorTypes.DATABASE_ERROR
|
|
458
|
+
}, error, context));
|
|
459
|
+
const { _id: postDocId } = savedPost;
|
|
460
|
+
const contentTagNames = await extractTags(insert.content || '');
|
|
461
|
+
if (tags.length || contentTagNames.length) {
|
|
462
|
+
const userTags = (await getTagsByName(context, tags.map(({ name })=>name || ''))).map((tag)=>({
|
|
463
|
+
...tag,
|
|
464
|
+
tagBy: sessionId
|
|
465
|
+
}));
|
|
466
|
+
const contentTags = (await getTagsByName(context, contentTagNames || [])).map((tag)=>({
|
|
467
|
+
...tag,
|
|
468
|
+
tagBy: 'extract'
|
|
469
|
+
}));
|
|
470
|
+
const updatedTags = await updateTagsInItem(context, {
|
|
471
|
+
itemDocId: postDocId,
|
|
472
|
+
tags: [
|
|
473
|
+
...contentTags,
|
|
474
|
+
...userTags
|
|
475
|
+
]
|
|
476
|
+
});
|
|
477
|
+
return {
|
|
478
|
+
...savedPost,
|
|
479
|
+
tags: updatedTags
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
return savedPost;
|
|
483
|
+
} catch (error) {
|
|
484
|
+
throw error;
|
|
485
|
+
}
|
|
486
|
+
};
|
|
487
|
+
export const updatePost = async (context, post)=>{
|
|
488
|
+
const action = 'updatePost';
|
|
489
|
+
const { databaseName, session: { userId: sessionId } = {} } = context;
|
|
490
|
+
const now = Date.now();
|
|
491
|
+
const parsedPost = parsePost(post);
|
|
492
|
+
const { postId, tags = [] } = parsedPost;
|
|
493
|
+
const update = {
|
|
494
|
+
...parsedPost,
|
|
495
|
+
modified: now
|
|
496
|
+
};
|
|
497
|
+
if (!postId) {
|
|
498
|
+
throw logException({
|
|
499
|
+
action,
|
|
500
|
+
category: eventCategory,
|
|
501
|
+
value: ErrorTypes.INVALID_ID
|
|
502
|
+
}, context);
|
|
503
|
+
}
|
|
504
|
+
const insert = {
|
|
505
|
+
...update,
|
|
506
|
+
_key: postId,
|
|
507
|
+
added: now,
|
|
508
|
+
userId: sessionId
|
|
509
|
+
};
|
|
510
|
+
const aqlQry = aql`UPSERT {_key: ${postId}, userId: ${sessionId}}
|
|
511
|
+
INSERT ${insert}
|
|
512
|
+
UPDATE ${update}
|
|
513
|
+
IN posts RETURN NEW`;
|
|
514
|
+
try {
|
|
515
|
+
const updatedPost = await useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).catch((error)=>logError({
|
|
516
|
+
action,
|
|
517
|
+
category: eventCategory,
|
|
518
|
+
value: ErrorTypes.DATABASE_ERROR
|
|
519
|
+
}, error, {}));
|
|
520
|
+
const { _id: updatedPostId } = updatedPost;
|
|
521
|
+
const contentTagNames = await extractTags(insert.content || '');
|
|
522
|
+
if (tags?.length || contentTagNames?.length) {
|
|
523
|
+
const userTags = tags?.length ? (await getTagsByName(context, tags.map(({ name })=>name || ''))).map((tag)=>({
|
|
524
|
+
...tag,
|
|
525
|
+
tagBy: sessionId
|
|
526
|
+
})) : [];
|
|
527
|
+
const contentTags = contentTagNames?.length ? (await getTagsByName(context, contentTagNames || [])).map((tag)=>({
|
|
528
|
+
...tag,
|
|
529
|
+
tagBy: 'extract'
|
|
530
|
+
})) : [];
|
|
531
|
+
const updatedTags = await updateTagsInItem(context, {
|
|
532
|
+
itemDocId: updatedPostId,
|
|
533
|
+
tags: [
|
|
534
|
+
...contentTags,
|
|
535
|
+
...userTags
|
|
536
|
+
]
|
|
537
|
+
});
|
|
538
|
+
return {
|
|
539
|
+
...updatedPost,
|
|
540
|
+
tags: updatedTags
|
|
541
|
+
};
|
|
542
|
+
}
|
|
543
|
+
return updatedPost;
|
|
544
|
+
} catch (error) {
|
|
545
|
+
throw error;
|
|
546
|
+
}
|
|
547
|
+
};
|
|
548
|
+
export const deletePost = async (context, postDocId)=>{
|
|
549
|
+
const action = 'deletePost';
|
|
550
|
+
const { databaseName, session: { userId: sessionId } = {} } = context;
|
|
551
|
+
const formatPostId = parseArangoId(postDocId);
|
|
552
|
+
if (!formatPostId) {
|
|
553
|
+
throw logException({
|
|
554
|
+
action,
|
|
555
|
+
category: eventCategory,
|
|
556
|
+
value: ErrorTypes.INVALID_ID
|
|
557
|
+
}, context);
|
|
558
|
+
}
|
|
559
|
+
const edgeAqlQry = aql`FOR t IN isTagged
|
|
560
|
+
FILTER t._to == ${formatPostId}
|
|
561
|
+
REMOVE t IN isTagged`;
|
|
562
|
+
await useDb(databaseName).query(edgeAqlQry).catch((error)=>{
|
|
563
|
+
throw error;
|
|
564
|
+
});
|
|
565
|
+
const fileAqlQry = aql`FOR f IN hasFile
|
|
566
|
+
FILTER f._to == ${formatPostId}
|
|
567
|
+
REMOVE f IN hasFile`;
|
|
568
|
+
await useDb(databaseName).query(fileAqlQry).catch((error)=>{
|
|
569
|
+
throw error;
|
|
570
|
+
});
|
|
571
|
+
const aqlQry = aql`FOR p IN posts
|
|
572
|
+
FILTER p._id == ${formatPostId} && p.userId == ${sessionId}
|
|
573
|
+
LIMIT 1
|
|
574
|
+
REMOVE p IN posts
|
|
575
|
+
RETURN OLD`;
|
|
576
|
+
return useDb(databaseName).query(aqlQry).then((cursor)=>cursor.next()).catch((error)=>{
|
|
577
|
+
throw error;
|
|
578
|
+
});
|
|
579
|
+
};
|
|
580
|
+
export const createPostEdge = (context, postDocId, itemDocId, edgeType = 'isPosted', props = {})=>{
|
|
581
|
+
const action = 'createPostEdge';
|
|
582
|
+
const { databaseName } = context;
|
|
583
|
+
const edgeCollection = useDb(databaseName).collection(edgeType);
|
|
584
|
+
const formatPostId = parseArangoId(postDocId);
|
|
585
|
+
const formatDocId = parseArangoId(itemDocId);
|
|
586
|
+
if (!formatDocId || !formatPostId) {
|
|
587
|
+
throw new Error(ErrorTypes.INVALID_ID);
|
|
588
|
+
}
|
|
589
|
+
const edgeId = createHash(`postEdge-${formatPostId}-${formatDocId}`);
|
|
590
|
+
const edge = {
|
|
591
|
+
_from: formatPostId,
|
|
592
|
+
_key: edgeId,
|
|
593
|
+
_to: formatDocId,
|
|
594
|
+
added: Date.now(),
|
|
595
|
+
...props
|
|
596
|
+
};
|
|
597
|
+
return edgeCollection.save(edge, {
|
|
598
|
+
returnNew: true
|
|
599
|
+
}).catch((error)=>{
|
|
600
|
+
throw logError({
|
|
601
|
+
action,
|
|
602
|
+
category: eventCategory,
|
|
603
|
+
value: ErrorTypes.DATABASE_ERROR
|
|
604
|
+
}, error, context);
|
|
605
|
+
});
|
|
606
|
+
};
|
|
607
|
+
|
|
608
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi9Vc2Vycy9uaXRyb2c3L0RldmVsb3BtZW50L3JlYWt0b3Ivc3JjL2FjdGlvbnMvcG9zdHMudHMiXSwic291cmNlc0NvbnRlbnQiOlsiLyoqXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTktUHJlc2VudCwgTml0cm9nZW4gTGFicywgSW5jLlxuICogQ29weXJpZ2h0cyBsaWNlbnNlZCB1bmRlciB0aGUgTUlUIExpY2Vuc2UuIFNlZSB0aGUgYWNjb21wYW55aW5nIExJQ0VOU0UgZmlsZSBmb3IgdGVybXMuXG4gKi9cbmltcG9ydCB7IHBhcnNlTnVtIH0gZnJvbSAnQG5sYWJzL3V0aWxzL3BhcnNlcnMvbnVtYmVycyc7XG5pbXBvcnQge1xuICAgIGNyZWF0ZUhhc2gsIHBhcnNlQXJhbmdvSWQsIHBhcnNlQ2hhciwgcGFyc2VJZCwgcGFyc2VTdHJpbmcsIHBhcnNlVmFyQ2hhclxufSBmcm9tICdAbmxhYnMvdXRpbHMvcGFyc2Vycy9zdHJpbmdzJztcbmltcG9ydCB7IGFxbCB9IGZyb20gJ2FyYW5nb2pzJztcbmltcG9ydCB7IEFxbFF1ZXJ5IH0gZnJvbSAnYXJhbmdvanMvYXFsJztcblxuaW1wb3J0IHsgcGFyc2VQb3N0IH0gZnJvbSAnLi4vYWRhcHRlcnMvcG9zdEFkYXB0ZXIuanMnO1xuaW1wb3J0IHsgRXJyb3JUeXBlcyB9IGZyb20gJy4uL3R5cGVzL2Vycm9yLnR5cGVzLmpzJztcbmltcG9ydCB7IGxvZ0Vycm9yLCBsb2dFeGNlcHRpb24gfSBmcm9tICcuLi91dGlscy9hbmFseXRpY3NVdGlscy5qcyc7XG5pbXBvcnQgeyBnZXRMaW1pdCwgdXNlRGIgfSBmcm9tICcuLi91dGlscy9hcmFuZ29kYlV0aWxzLmpzJztcbmltcG9ydCB7IGV4dHJhY3RUYWdzLCBnZXRUYWdzQnlOYW1lLCB1cGRhdGVUYWdzSW5JdGVtIH0gZnJvbSAnLi90YWdzLmpzJztcblxuaW1wb3J0IHR5cGUgeyBFZGdlQ29sbGVjdGlvbiB9IGZyb20gJ2FyYW5nb2pzL2NvbGxlY3Rpb25zJztcbmltcG9ydCB0eXBlIHsgQXJhbmdvRGJMaW1pdCB9IGZyb20gJy4uL3R5cGVzL2FyYW5nb2RiLnR5cGVzLmpzJztcbmltcG9ydCB0eXBlIHsgQXBpQ29udGV4dCB9IGZyb20gJy4uL3R5cGVzL2F1dGgudHlwZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBGaWxlVHlwZSB9IGZyb20gJy4uL3R5cGVzL2ZpbGVzLnR5cGVzLmpzJztcbmltcG9ydCB0eXBlIHsgUG9zdElucHV0VHlwZSwgUG9zdE9wdGlvbnMsIFBvc3RUeXBlIH0gZnJvbSAnLi4vdHlwZXMvcG9zdHMudHlwZXMuanMnO1xuaW1wb3J0IHR5cGUgeyBUYWdUeXBlIH0gZnJvbSAnLi4vdHlwZXMvdGFncy50eXBlcy5qcyc7XG5cbmNvbnN0IE1BWF9DT05URU5UX0xFTkdUSDogbnVtYmVyID0gMTAwMDAwO1xuY29uc3QgZXZlbnRDYXRlZ29yeTogc3RyaW5nID0gJ3Bvc3RzJztcblxuZXhwb3J0IGNvbnN0IHBhcnNlUG9zdE9wdGlvbnMgPSAob3B0aW9uczogUG9zdE9wdGlvbnMgPSB7fSkgPT4ge1xuICBjb25zdCB7XG4gICAgZnJvbSA9IDAsXG4gICAgbGF0aXR1ZGUgPSAwLFxuICAgIGxvbmdpdHVkZSA9IDAsXG4gICAgdG8gPSAzMCxcbiAgICB0eXBlID0gJ3Bvc3QnXG4gIH0gPSBvcHRpb25zO1xuXG4gIHJldHVybiB7XG4gICAgbGF0aXR1ZGU6IHBhcnNlTnVtKGxhdGl0dWRlLCAzMiksXG4gICAgbGltaXQ6IGdldExpbWl0KGZyb20sIHRvKSBhcyBBcmFuZ29EYkxpbWl0LFxuICAgIGxvbmdpdHVkZTogcGFyc2VOdW0obG9uZ2l0dWRlLCAzMiksXG4gICAgdHlwZTogcGFyc2VDaGFyKHR5cGUsIDMyKVxuICB9O1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFBvc3RPcHRpb25hbCA9IChmaWVsZHM6IHN0cmluZ1tdID0gW10sIHNlc3Npb25JZDogc3RyaW5nID0gJycpID0+XG4gIChmaWVsZHMgfHwgW10pLnJlZHVjZSgoc2VsZWN0czoge29iamVjdHM6IHN0cmluZ1tdLCBxdWVyaWVzOiBzdHJpbmdbXX0sIGZpZWxkOiBzdHJpbmcpID0+IHtcbiAgICBzd2l0Y2goZmllbGQpIHtcbiAgICAgIGNhc2UgJ2hhc1JzdnAnOiB7XG4gICAgICAgIHNlbGVjdHMucXVlcmllcy5wdXNoKGBMRVQgaGFzUnN2cCA9IFRPX0JPT0woRklSU1QoXG4gICAgICAgICAgRk9SIHBvc3QsIHIgSU4gSU5CT1VORCBwLl9pZCBoYXNSZWFjdGlvblxuICAgICAgICAgIEZJTFRFUiByLm5hbWUgPT0gXCJyc3ZwXCIgJiYgci50eXBlID09IFwicG9zdHNcIiAmJiByLl9mcm9tID09IFwidXNlcnMvJHtzZXNzaW9uSWR9XCJcbiAgICAgICAgICBDT0xMRUNUIFdJVEggQ09VTlQgSU5UTyBjb3VudFxuICAgICAgICAgIFJFVFVSTiBjb3VudFxuICAgICAgICApKWApO1xuICAgICAgICBzZWxlY3RzLm9iamVjdHMucHVzaCgnaGFzUnN2cDpoYXNSc3ZwJyk7XG4gICAgICAgIHJldHVybiBzZWxlY3RzO1xuICAgICAgfVxuICAgICAgY2FzZSAnaXNTYXZlZCc6IHtcbiAgICAgICAgc2VsZWN0cy5xdWVyaWVzLnB1c2goYExFVCBpc1NhdmVkID0gVE9fQk9PTChGSVJTVChcbiAgICAgICAgICBGT1IgcG9zdCwgciBJTiBJTkJPVU5EIHAuX2lkIGhhc1JlYWN0aW9uXG4gICAgICAgICAgRklMVEVSIHIubmFtZSA9PSBcInBpblwiICYmIHIudHlwZSA9PSBcInBvc3RzXCIgJiYgci5fZnJvbSA9PSBcInVzZXJzLyR7c2Vzc2lvbklkfVwiXG4gICAgICAgICAgQ09MTEVDVCBXSVRIIENPVU5UIElOVE8gY291bnRcbiAgICAgICAgICBSRVRVUk4gY291bnRcbiAgICAgICAgKSlgKTtcbiAgICAgICAgc2VsZWN0cy5vYmplY3RzLnB1c2goJ2lzU2F2ZWQ6aXNTYXZlZCcpO1xuICAgICAgICByZXR1cm4gc2VsZWN0cztcbiAgICAgIH1cbiAgICAgIGNhc2UgJ3JlYWN0aW9ucyc6IHtcbiAgICAgICAgc2VsZWN0cy5xdWVyaWVzLnB1c2goYExFVCByZWFjdGlvbnMgPSAoXG4gICAgICAgICAgRk9SIHBvc3QsIHIgSU4gSU5CT1VORCBwLl9pZCBoYXNSZWFjdGlvblxuICAgICAgICAgIENPTExFQ1QgcmVhY3Rpb25OYW1lID0gci52YWx1ZSBJTlRPIHJlYWN0aW9uSXRlbXNcbiAgICAgICAgICBSRVRVUk4ge25hbWU6IHJlYWN0aW9uTmFtZSwgY291bnQ6IExFTkdUSChyZWFjdGlvbkl0ZW1zWypdLnIudmFsdWUpfVxuICAgICAgICApYCk7XG4gICAgICAgIHNlbGVjdHMub2JqZWN0cy5wdXNoKCdyZWFjdGlvbnM6cmVhY3Rpb25zJyk7XG4gICAgICAgIHJldHVybiBzZWxlY3RzO1xuICAgICAgfVxuICAgICAgY2FzZSAncnN2cENvdW50Jzoge1xuICAgICAgICBzZWxlY3RzLnF1ZXJpZXMucHVzaChgTEVUIHJzdnBDb3VudCA9IEZJUlNUKFxuICAgICAgICAgIEZPUiBwb3N0LCByIElOIElOQk9VTkQgcC5faWQgaGFzUmVhY3Rpb25cbiAgICAgICAgICBGSUxURVIgci5uYW1lID09IFwicnN2cFwiICYmIHIudHlwZSA9PSBcInBvc3RzXCJcbiAgICAgICAgICBDT0xMRUNUIFdJVEggQ09VTlQgSU5UTyBjb3VudFxuICAgICAgICAgIFJFVFVSTiBjb3VudFxuICAgICAgICApYCk7XG4gICAgICAgIHNlbGVjdHMub2JqZWN0cy5wdXNoKCdyc3ZwQ291bnQ6cnN2cENvdW50Jyk7XG4gICAgICAgIHJldHVybiBzZWxlY3RzO1xuICAgICAgfVxuICAgICAgY2FzZSAndmlld0NvdW50Jzoge1xuICAgICAgICBzZWxlY3RzLnF1ZXJpZXMucHVzaChgTEVUIHZpZXdDb3VudCA9IEZJUlNUKFxuICAgICAgICAgIEZPUiBwb3N0LCByIElOIElOQk9VTkQgcC5faWQgaGFzUmVhY3Rpb25cbiAgICAgICAgICBGSUxURVIgci5uYW1lID09IFwidmlld1wiICYmIHIudHlwZSA9PSBcInBvc3RzXCJcbiAgICAgICAgICBDT0xMRUNUIFdJVEggQ09VTlQgSU5UTyBjb3VudFxuICAgICAgICAgIFJFVFVSTiBjb3VudFxuICAgICAgICApYCk7XG4gICAgICAgIHNlbGVjdHMub2JqZWN0cy5wdXNoKCd2aWV3Q291bnQ6dmlld0NvdW50Jyk7XG4gICAgICAgIHJldHVybiBzZWxlY3RzO1xuICAgICAgfVxuICAgICAgZGVmYXVsdDoge1xuICAgICAgICByZXR1cm4gc2VsZWN0cztcbiAgICAgIH1cbiAgICB9XG4gIH0sIHtvYmplY3RzOiBbXSwgcXVlcmllczogW119KTtcblxuZXhwb3J0IGNvbnN0IGdldFBvc3QgPSBhc3luYyAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIHBvc3RJZDogc3RyaW5nLFxuICBvcHRpb25zPzogUG9zdE9wdGlvbnNcbik6IFByb21pc2U8UG9zdFR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0UG9zdCc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIGZpZWxkcywgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfSA9IHt9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IGZvcm1hdEl0ZW1JZDogc3RyaW5nID0gcGFyc2VJZChwb3N0SWQpO1xuICBjb25zdCB7dHlwZX0gPSBwYXJzZVBvc3RPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCBkYXRhYmFzZSA9IHVzZURiKGRhdGFiYXNlTmFtZSk7XG4gIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFBvc3RPcHRpb25hbChmaWVsZHMsIHNlc3Npb25JZCk7XG4gIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgRk9SIHAgSU4gcG9zdHNcbiAgICBGSUxURVIgcC5fa2V5ID09ICR7Zm9ybWF0SXRlbUlkfSAmJiBwLnR5cGUgPT0gJHt0eXBlfVxuICAgIExJTUlUIDFcbiAgICBSRVRVUk4gcGA7XG5cbiAgcmV0dXJuIGRhdGFiYXNlLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC50aGVuKChwb3N0OiBQb3N0VHlwZSkgPT4ge1xuICAgICAgY29uc3Qge1xuICAgICAgICBfaWQ6IHBvc3REb2NJZCxcbiAgICAgICAgdXNlcklkLFxuICAgICAgICBncm91cElkLFxuICAgICAgICBwcml2YWN5ID0gJ2RlZmF1bHQnXG4gICAgICB9OiBQb3N0VHlwZSA9IHBvc3Q7XG5cbiAgICAgIGxldCBwcml2YWN5QXFsUXJ5OiBzdHJpbmcgfCB1bmRlZmluZWQ7XG5cbiAgICAgIGlmKHVzZXJJZCA9PT0gc2Vzc2lvbklkKSB7XG4gICAgICAgIHJldHVybiBwb3N0O1xuICAgICAgfVxuXG4gICAgICBpZihncm91cElkICYmIHByaXZhY3kgPT09ICdncm91cCcpIHtcbiAgICAgICAgcHJpdmFjeUFxbFFyeSA9IGBMRVQgcCA9IERPQ1VNRU5UKFwiJHtwb3N0RG9jSWR9XCIpXG4gICAgICAgICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuICAgICAgICAgIEZPUiBncm91cCBJTiBncm91cHNcbiAgICAgICAgICBGSUxURVIgZ3JvdXAuX2tleSA9PSBwLmdyb3VwSWRcbiAgICAgICAgICBGT1IgdSwgZSBJTiBPVVRCT1VORCBncm91cC5faWQgaGFzQ29ubmVjdGlvblxuICAgICAgICAgIEZJTFRFUiB1Ll9rZXkgPT0gXCIke3Nlc3Npb25JZH1cIlxuICAgICAgICAgIExJTUlUIDFcbiAgICAgICAgICBSRVRVUk4gTUVSR0UocCwgeyR7c2VsZWN0T2JqZWN0cy5qb2luKCcsICcpfX0pYDtcbiAgICAgIH0gZWxzZSBpZihwcml2YWN5ID09PSAncHVibGljJykge1xuICAgICAgICBwcml2YWN5QXFsUXJ5ID0gYExFVCBwID0gRE9DVU1FTlQoXCIke3Bvc3REb2NJZH1cIilcbiAgICAgICAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4gICAgICAgICAgTElNSVQgMVxuICAgICAgICAgIFJFVFVSTiBNRVJHRShwLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuICAgICAgfVxuXG4gICAgICBpZihwcml2YWN5QXFsUXJ5KSB7XG4gICAgICAgIHJldHVybiBkYXRhYmFzZS5xdWVyeShwcml2YWN5QXFsUXJ5KVxuICAgICAgICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgICAgICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IGxvZ0Vycm9yKHtcbiAgICAgICAgICAgIGFjdGlvbixcbiAgICAgICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICAgICAgICB9LCBlcnJvciwgY29udGV4dCkpO1xuICAgICAgfVxuXG4gICAgICByZXR1cm4ge307XG4gICAgfSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgYWN0aW9uLFxuICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICBsYWJlbDogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgIH0sIGVycm9yLCBjb250ZXh0KSk7XG59O1xuXG5cbi8vIGV4cG9ydCBjb25zdCBnZXRQb3N0TGlzdCA9IChjb250ZXh0OiBBcGlDb250ZXh0LCBvcHRpb25zPzogUG9zdE9wdGlvbnMpOiBQcm9taXNlPFBvc3RUeXBlW10+ID0+IHtcbi8vICAgLy8gY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0TGlzdEJ5QXBwJztcbi8vICAgY29uc3Qge2RhdGFiYXNlLCBmaWVsZHMsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH19ID0gY29udGV4dDtcbi8vICAgY29uc3Qge2xpbWl0LCB0eXBlfSA9IHBhcnNlUG9zdE9wdGlvbnMob3B0aW9ucyk7XG4vLyAgIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFBvc3RPcHRpb25hbChmaWVsZHMsIHNlc3Npb25JZCk7XG4vLyAgIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBwIElOIHBvc3RzXG4vLyAgICAgRklMVEVSIHAudHlwZSA9PSBcIiR7dHlwZX1cIiAmJiBwLnByaXZhY3kgPT0gXCJwdWJsaWNcIiAmJiBwLnBhcmVudCA9PSBudWxsXG4vLyAgICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuLy8gICAgICR7bGltaXQuYXFsfVxuLy8gICAgIFNPUlQgcC5hZGRlZFxuLy8gICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRShwLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4vLyAgIHJldHVybiBkYXRhYmFzZS5xdWVyeShhcWxRcnkpXG4vLyAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuLy8gICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4vLyAgICAgICB0aHJvdyBlcnJvcjtcbi8vICAgICB9KTtcbi8vIH07XG5cbmV4cG9ydCBjb25zdCBnZXRQb3N0c0J5QXJlYSA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgbGF0aXR1ZGU6IG51bWJlcixcbiAgbG9uZ2l0dWRlOiBudW1iZXIsXG4gIG9wdGlvbnM/OiBQb3N0T3B0aW9uc1xuKTogUHJvbWlzZTxQb3N0VHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFBvc3RzQnlBcmVhJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZSwgZmllbGRzLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9ID0ge319ID0gY29udGV4dDtcbiAgY29uc3Qge2xpbWl0LCB0eXBlfSA9IHBhcnNlUG9zdE9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IGZvcm1hdExhdGl0dWRlOiBudW1iZXIgPSBwYXJzZU51bShsYXRpdHVkZSk7XG4gIGNvbnN0IGZvcm1hdExvbmdpdHVkZTogbnVtYmVyID0gcGFyc2VOdW0obG9uZ2l0dWRlKTtcbiAgY29uc3Qge29iamVjdHM6IHNlbGVjdE9iamVjdHMsIHF1ZXJpZXM6IHNlbGVjdFF1ZXJpZXN9ID0gZ2V0UG9zdE9wdGlvbmFsKGZpZWxkcywgc2Vzc2lvbklkKTtcbiAgc2VsZWN0UXVlcmllcy5wdXNoKGBMRVQgZGlzdGFuY2UgPSBESVNUQU5DRShcbiAgICAke2Zvcm1hdExhdGl0dWRlfSxcbiAgICAke2Zvcm1hdExvbmdpdHVkZX0sXG4gICAgTk9UX05VTEwocC5sYXRpdHVkZSwgMCksXG4gICAgTk9UX05VTEwocC5sb25naXR1ZGUsIDApKVxuICBgKTtcbiAgc2VsZWN0T2JqZWN0cy5wdXNoKCdkaXN0YW5jZTpkaXN0YW5jZScpO1xuXG4gIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBwIElOIHBvc3RzXG4gICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuICAgIEZJTFRFUiBwLnR5cGUgPT0gXCIke3R5cGV9XCIgJiYgcC5wcml2YWN5ID09IFwicHVibGljXCIgJiYgcC5wYXJlbnRJZCA9PSBudWxsXG4gICAgJHtsaW1pdC5hcWx9XG4gICAgU09SVCBkaXN0YW5jZSwgcC5hZGRlZFxuICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRShwLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkgYXMgdW5rbm93biBhcyBQb3N0VHlwZVtdKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dCk7XG5cbiAgICAgIHJldHVybiBbXSBhcyBQb3N0VHlwZVtdO1xuICAgIH0pO1xufTtcblxuLy8gZXhwb3J0IGNvbnN0IGdldFBvc3RzQnlHcm91cCA9IChcbi8vICAgY29udGV4dDogQXBpQ29udGV4dCxcbi8vICAgZ3JvdXBJZDogc3RyaW5nLFxuLy8gICBvcHRpb25zPzogUG9zdE9wdGlvbnNcbi8vICk6IFByb21pc2U8UG9zdFR5cGVbXT4gPT4ge1xuLy8gICAvLyBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRMaXN0QnlHcm91cCc7XG4vLyAgIGNvbnN0IHtkYXRhYmFzZSwgZmllbGRzLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9fSA9IGNvbnRleHQ7XG4vLyAgIGNvbnN0IHtvYmplY3RzOiBzZWxlY3RPYmplY3RzLCBxdWVyaWVzOiBzZWxlY3RRdWVyaWVzfSA9IGdldFBvc3RPcHRpb25hbChmaWVsZHMsIHNlc3Npb25JZCk7XG5cbi8vICAgLy8gR3JvdXAgaWRcbi8vICAgY29uc3QgZm9ybWF0R3JvdXBJZDogc3RyaW5nID0gcGFyc2VJZChncm91cElkKTtcbi8vICAgY29uc3QgZGIgPSBkYXRhYmFzZTtcbi8vICAgY29uc3QgYXFsUXJ5OiBzdHJpbmcgPSBgRk9SIHUsIGcgSU4gSU5CT1VORCAke2Zvcm1hdEdyb3VwSWR9IGhhc0dyb3VwXG4vLyAgICAgICBGSUxURVIgdS5fa2V5ID09ICR7c2Vzc2lvbklkfVxuLy8gICAgICAgUkVUVVJOIGdgO1xuXG4vLyAgIHJldHVybiBkYi5xdWVyeShhcWxRcnkpXG4vLyAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuLy8gICAgIC50aGVuKChncm91cHM6IEdyb3VwVHlwZVtdID0gW10pID0+IHtcbi8vICAgICAgIGlmKGdyb3Vwcy5sZW5ndGgpIHtcbi8vICAgICAgICAgY29uc3Qge2xpbWl0LCB0eXBlfSA9IHBhcnNlUG9zdE9wdGlvbnMob3B0aW9ucyk7XG4vLyAgICAgICAgIGNvbnN0IHBvc3RBcWxRcnk6IHN0cmluZyA9IGBGT1IgcCBJTiBwb3N0c1xuLy8gICAgICAgICAgIEZJTFRFUiBwLnR5cGUgPT0gXCIke3R5cGV9XCIgJiYgcC5ncm91cElkID09IFwiJHtmb3JtYXRHcm91cElkfVwiICYmIHAucGFyZW50ID09IG51bGxcbi8vICAgICAgICAgICAke3NlbGVjdFF1ZXJpZXMuam9pbignXFxuJyl9XG4vLyAgICAgICAgICAgJHtsaW1pdC5hcWx9XG4vLyAgICAgICAgICAgU09SVCBwLmFkZGVkXG4vLyAgICAgICAgICAgUkVUVVJOIERJU1RJTkNUIE1FUkdFKHAsIHske3NlbGVjdE9iamVjdHMuam9pbignLCAnKX19KWA7XG5cbi8vICAgICAgICAgcmV0dXJuIGRiLnF1ZXJ5KHBvc3RBcWxRcnkpXG4vLyAgICAgICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpKVxuLy8gICAgICAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4vLyAgICAgICAgICAgICB0aHJvdyBlcnJvcjtcbi8vICAgICAgICAgICB9KTtcbi8vICAgICAgIH1cblxuLy8gICAgICAgcmV0dXJuIFtdO1xuLy8gICAgIH0pXG4vLyAgICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbi8vICAgICAgIHRocm93IGVycm9yO1xuLy8gICAgIH0pO1xuLy8gfTtcblxuZXhwb3J0IGNvbnN0IGdldFBvc3RzQnlMYXRlc3QgPSAoY29udGV4dDogQXBpQ29udGV4dCwgb3B0aW9ucz86IFBvc3RPcHRpb25zKTogUHJvbWlzZTxQb3N0VHlwZVtdPiA9PiB7XG4gIC8vIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldExpc3RCeUxhdGVzdCc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIGZpZWxkcywgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfSA9IHt9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtsaW1pdCwgdHlwZX0gPSBwYXJzZVBvc3RPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRQb3N0T3B0aW9uYWwoZmllbGRzLCBzZXNzaW9uSWQpO1xuICBjb25zdCBhcWxRcnk6IHN0cmluZyA9IGBGT1IgcCBJTiBwb3N0c1xuICAgIEZJTFRFUiBwLnR5cGUgPT0gXCIke3R5cGV9XCIgJiYgcC5wcml2YWN5ID09IFwicHVibGljXCIgJiYgcC5wYXJlbnQgPT0gbnVsbFxuICAgICR7c2VsZWN0UXVlcmllcy5qb2luKCdcXG4nKX1cbiAgICAke2xpbWl0LmFxbH1cbiAgICBTT1JUIHAuYWRkZWQgREVTQ1xuICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRShwLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkpXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgIHRocm93IGVycm9yO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFBvc3RzQnlSZWFjdGlvbnMgPSAoXG4gIGNvbnRleHQ6IEFwaUNvbnRleHQsXG4gIHJlYWN0aW9uczogc3RyaW5nW10gPSBbXSxcbiAgb3B0aW9ucz86IFBvc3RPcHRpb25zXG4pOiBQcm9taXNlPFBvc3RUeXBlW10+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZ2V0UG9zdHNCeVJlYWN0aW9ucyc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIGZpZWxkcywgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfSA9IHt9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtsYXRpdHVkZSwgbGltaXQsIGxvbmdpdHVkZSwgdHlwZX0gPSBwYXJzZVBvc3RPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRQb3N0T3B0aW9uYWwoZmllbGRzLCBzZXNzaW9uSWQpO1xuICBjb25zdCBmb3JtYXRTZXNzaW9uSWQ6IHN0cmluZyA9IGB1c2Vycy8ke3Nlc3Npb25JZH1gO1xuICBjb25zdCBmb3JtYXRSZWFjdGlvbnM6IHN0cmluZyA9IEpTT04uc3RyaW5naWZ5KHJlYWN0aW9ucy5tYXAoKHJlYWN0aW9uKSA9PiBwYXJzZUNoYXIocmVhY3Rpb24sIDMyKS50b0xvd2VyQ2FzZSgpKSk7XG4gIGNvbnN0IHNvcnRCeTogc3RyaW5nW10gPSBbXTtcbiAgY29uc3QgZmlsdGVyczogc3RyaW5nW10gPSBbYHAudHlwZSA9PSBcIiR7dHlwZX1cImAsICdwLnByaXZhY3kgPT0gXCJwdWJsaWNcIiddO1xuICBjb25zdCBmb3JtYXRMYXRpdHVkZTogbnVtYmVyID0gcGFyc2VOdW0obGF0aXR1ZGUpO1xuICBjb25zdCBmb3JtYXRMb25naXR1ZGU6IG51bWJlciA9IHBhcnNlTnVtKGxvbmdpdHVkZSk7XG5cbiAgaWYoZm9ybWF0TGF0aXR1ZGUgJiYgZm9ybWF0TG9uZ2l0dWRlKSB7XG4gICAgc2VsZWN0UXVlcmllcy5wdXNoKGBMRVQgZGlzdGFuY2UgPSBESVNUQU5DRShcbiAgICAgICR7Zm9ybWF0TGF0aXR1ZGV9LFxuICAgICAgJHtmb3JtYXRMb25naXR1ZGV9LFxuICAgICAgTk9UX05VTEwocC5sYXRpdHVkZSwgMCksXG4gICAgICBOT1RfTlVMTChwLmxvbmdpdHVkZSwgMCkpXG4gICAgYCk7XG4gICAgc2VsZWN0T2JqZWN0cy5wdXNoKCdkaXN0YW5jZTpkaXN0YW5jZScpO1xuICAgIHNvcnRCeS5wdXNoKCdkaXN0YW5jZScpO1xuICB9XG5cbiAgaWYocmVhY3Rpb25zLmxlbmd0aCkge1xuICAgIHNvcnRCeS5wdXNoKCdtYXRjaGVkVGFncyBERVNDJyk7XG4gICAgc2VsZWN0UXVlcmllcy5wdXNoKGBMRVQgbWF0Y2hlZFJlYWN0aW9ucyA9IExFTkdUSChcbiAgICAgIEZPUiBtciBJTiByZWFjdGlvbnNcbiAgICAgIEZJTFRFUiBtci5tYXRjaGVkID09IHRydWVcbiAgICAgIFJFVFVSTiBtclxuICAgIClgKTtcbiAgICBzZWxlY3RPYmplY3RzLnB1c2goJ21hdGNoZWRSZWFjdGlvbnM6bWF0Y2hlZFJlYWN0aW9ucycpO1xuICAgIGZpbHRlcnMucHVzaCgnbWF0Y2hlZFJlYWN0aW9ucyA+IDAnKTtcbiAgfVxuXG4gIHNvcnRCeS5wdXNoKCdwLmFkZGVkIERFU0MnKTtcbiAgc2VsZWN0T2JqZWN0cy5wdXNoKCdyZWFjdGlvbnM6cmVhY3Rpb25zJyk7XG5cbiAgLy8gR2V0IGRhdGEgZnJvbSBkYXRhYmFzZVxuICBjb25zdCBhcWxRcnk6IHN0cmluZyA9IGBGT1IgcCwgciBJTiBPVVRCT1VORCBcIiR7Zm9ybWF0U2Vzc2lvbklkfVwiIGhhc1JlYWN0aW9uXG4gICAgTEVUIHJlYWN0aW9ucyA9IChcbiAgICAgIEZPUiByZWFjdGlvbiwgaHIgSU4gMS4uMSBJTkJPVU5EIHAgaXNUYWdnZWRcbiAgICAgIExFVCBtYXRjaGVkID0gTEVOR1RIKCR7Zm9ybWF0UmVhY3Rpb25zfSkgPiAwICYmIFBPU0lUSU9OKCR7Zm9ybWF0UmVhY3Rpb25zfSwgcmVhY3Rpb24ubmFtZSlcbiAgICAgIFNPUlQgcmVhY3Rpb24ubmFtZVxuICAgICAgUkVUVVJOIE1FUkdFKHJlYWN0aW9uLCB7bWF0Y2hlZDptYXRjaGVkfSlcbiAgICApXG4gICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuICAgIEZJTFRFUiAke2ZpbHRlcnMuam9pbignICYmICcpfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRShwLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkgYXMgdW5rbm93biBhcyBQb3N0VHlwZVtdKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dCk7XG5cbiAgICAgIHJldHVybiBbXSBhcyBQb3N0VHlwZVtdO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFBvc3RzQnlUYWdzID0gKFxuICBjb250ZXh0OiBBcGlDb250ZXh0LFxuICB0YWdzOiBzdHJpbmdbXSA9IFtdLFxuICBvcHRpb25zPzogUG9zdE9wdGlvbnNcbik6IFByb21pc2U8UG9zdFR5cGVbXT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICdnZXRQb3N0c0J5VGFncyc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIGZpZWxkcywgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfSA9IHt9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IHtsYXRpdHVkZSwgbGltaXQsIGxvbmdpdHVkZSwgdHlwZX0gPSBwYXJzZVBvc3RPcHRpb25zKG9wdGlvbnMpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRQb3N0T3B0aW9uYWwoZmllbGRzLCBzZXNzaW9uSWQpO1xuICBjb25zdCBmb3JtYXRUYWdOYW1lczogc3RyaW5nID0gSlNPTi5zdHJpbmdpZnkodGFncy5tYXAoKHRhZykgPT4gcGFyc2VDaGFyKHRhZywgMzIpLnRvTG93ZXJDYXNlKCkpKTtcbiAgY29uc3Qgc29ydEJ5OiBzdHJpbmdbXSA9IFtdO1xuICBjb25zdCBmaWx0ZXJzOiBzdHJpbmdbXSA9IFtgcC50eXBlID09IFwiJHt0eXBlfVwiYCwgJ3AucHJpdmFjeSA9PSBcInB1YmxpY1wiJ107XG4gIGNvbnN0IGZvcm1hdExhdGl0dWRlOiBudW1iZXIgPSBwYXJzZU51bShsYXRpdHVkZSk7XG4gIGNvbnN0IGZvcm1hdExvbmdpdHVkZTogbnVtYmVyID0gcGFyc2VOdW0obG9uZ2l0dWRlKTtcblxuICBpZihmb3JtYXRMYXRpdHVkZSAmJiBmb3JtYXRMb25naXR1ZGUpIHtcbiAgICBzZWxlY3RRdWVyaWVzLnB1c2goYExFVCBkaXN0YW5jZSA9IERJU1RBTkNFKFxuICAgICAgJHtmb3JtYXRMYXRpdHVkZX0sXG4gICAgICAke2Zvcm1hdExvbmdpdHVkZX0sXG4gICAgICBOT1RfTlVMTChwLmxhdGl0dWRlLCAwKSxcbiAgICAgIE5PVF9OVUxMKHAubG9uZ2l0dWRlLCAwKSlcbiAgICBgKTtcbiAgICBzZWxlY3RPYmplY3RzLnB1c2goJ2Rpc3RhbmNlOmRpc3RhbmNlJyk7XG4gICAgc29ydEJ5LnB1c2goJ2Rpc3RhbmNlJyk7XG4gIH1cblxuICBpZih0YWdzLmxlbmd0aCkge1xuICAgIHNvcnRCeS5wdXNoKCdtYXRjaGVkVGFncyBERVNDJyk7XG4gICAgc2VsZWN0UXVlcmllcy5wdXNoKGBMRVQgbWF0Y2hlZFRhZ3MgPSBMRU5HVEgoXG4gICAgICBGT1IgdCBJTiB0YWdzXG4gICAgICBGSUxURVIgdC5tYXRjaGVkID09IHRydWVcbiAgICAgIFJFVFVSTiB0XG4gICAgKWApO1xuICAgIHNlbGVjdE9iamVjdHMucHVzaCgnbWF0Y2hlZFRhZ3M6bWF0Y2hlZFRhZ3MnKTtcbiAgICBmaWx0ZXJzLnB1c2goJ21hdGNoZWRUYWdzID4gMCcpO1xuICB9XG5cbiAgc29ydEJ5LnB1c2goJ3AuYWRkZWQgREVTQycpO1xuICBzZWxlY3RPYmplY3RzLnB1c2goJ3RhZ3M6dGFncycpO1xuXG4gIGNvbnN0IGFxbFFyeTogc3RyaW5nID0gYEZPUiBwIElOIHBvc3RzXG4gICAgTEVUIHRhZ3MgPSAoXG4gICAgICBGT1IgdGFnLCBpdCBJTiAxLi4xIElOQk9VTkQgcCBpc1RhZ2dlZFxuICAgICAgTEVUIG1hdGNoZWQgPSBMRU5HVEgoJHtmb3JtYXRUYWdOYW1lc30pID4gMCAmJiBQT1NJVElPTigke2Zvcm1hdFRhZ05hbWVzfSwgdGFnLm5hbWUpXG4gICAgICBTT1JUIHRhZy5uYW1lXG4gICAgICBSRVRVUk4gTUVSR0UodGFnLCB7bWF0Y2hlZDptYXRjaGVkfSlcbiAgICApXG4gICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuICAgIEZJTFRFUiAke2ZpbHRlcnMuam9pbignICYmICcpfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFNPUlQgJHtzb3J0Qnkuam9pbignLCAnKX1cbiAgICBSRVRVUk4gRElTVElOQ1QgTUVSR0UocCwgeyR7c2VsZWN0T2JqZWN0cy5qb2luKCcsICcpfX0pYDtcblxuICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShhcWxRcnkpXG4gICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLmFsbCgpIGFzIHVua25vd24gYXMgUG9zdFR5cGVbXSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICBsYWJlbDogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuXG4gICAgICByZXR1cm4gW10gYXMgUG9zdFR5cGVbXTtcbiAgICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBnZXRQb3N0c0J5VXNlciA9IChjb250ZXh0OiBBcGlDb250ZXh0LCB1c2VySWQ6IHN0cmluZywgb3B0aW9ucz86IFBvc3RPcHRpb25zKTogUHJvbWlzZTxQb3N0VHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFBvc3RzQnlVc2VyJztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZSwgZmllbGRzLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9ID0ge319ID0gY29udGV4dDtcbiAgY29uc3Qge2xpbWl0LCB0eXBlfSA9IHBhcnNlUG9zdE9wdGlvbnMob3B0aW9ucyk7XG4gIGNvbnN0IGZvcm1hdFVzZXJJZDogc3RyaW5nID0gcGFyc2VJZCh1c2VySWQpO1xuICBjb25zdCB7b2JqZWN0czogc2VsZWN0T2JqZWN0cywgcXVlcmllczogc2VsZWN0UXVlcmllc30gPSBnZXRQb3N0T3B0aW9uYWwoZmllbGRzLCBzZXNzaW9uSWQpO1xuICBjb25zdCBhcWxRcnk6IHN0cmluZyA9IGBGT1IgcCBJTiBwb3N0c1xuICAgIEZJTFRFUiBwLnVzZXJJZCA9PSBcIiR7Zm9ybWF0VXNlcklkfVwiICYmIHAudHlwZSA9PSBcIiR7dHlwZX1cIiAmJiBwLnByaXZhY3kgPT0gXCJwdWJsaWNcIiAmJiBwLnBhcmVudCA9PSBudWxsXG4gICAgJHtzZWxlY3RRdWVyaWVzLmpvaW4oJ1xcbicpfVxuICAgICR7bGltaXQuYXFsfVxuICAgIFNPUlQgcC5hZGRlZFxuICAgIFJFVFVSTiBESVNUSU5DVCBNRVJHRShwLCB7JHtzZWxlY3RPYmplY3RzLmpvaW4oJywgJyl9fSlgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IuYWxsKCkgYXMgdW5rbm93biBhcyBQb3N0VHlwZVtdKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dCk7XG5cbiAgICAgIHJldHVybiBbXSBhcyBQb3N0VHlwZVtdO1xuICAgIH0pO1xufTtcblxuZXhwb3J0IGNvbnN0IGdldFBvc3RDb21tZW50cyA9IChjb250ZXh0OiBBcGlDb250ZXh0LCBwb3N0SWQ6IHN0cmluZywgb3B0aW9ucz86IFBvc3RPcHRpb25zKTogUHJvbWlzZTxQb3N0VHlwZVtdPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2dldFBvc3RDb21tZW50cyc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH0gPSB7fX0gPSBjb250ZXh0O1xuICBjb25zdCB7bGltaXQsIHR5cGV9ID0gcGFyc2VQb3N0T3B0aW9ucyhvcHRpb25zKTtcbiAgY29uc3QgZm9ybWF0SXRlbUlkOiBzdHJpbmcgPSBwYXJzZUlkKHBvc3RJZCk7XG5cbiAgLy8gR2V0IHRoZSBwYXJlbnQgcG9zdCB0byBnZXQgcmVzdHJpY3Rpb25zXG4gIGNvbnN0IGFxbFFyeTogQXFsUXVlcnkgPSBhcWxgRk9SIHAgSU4gcG9zdHNcbiAgICBGSUxURVIgcC50eXBlID09ICR7dHlwZX0gJiYgcC5fa2V5ID09ICR7Zm9ybWF0SXRlbUlkfVxuICAgIExJTUlUIDFcbiAgICBSRVRVUk4gcGA7XG5cbiAgcmV0dXJuIHVzZURiKGRhdGFiYXNlTmFtZSkucXVlcnkoYXFsUXJ5KVxuICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgLnRoZW4oKHBvc3Q6IFBvc3RUeXBlKSA9PiB7XG4gICAgICBjb25zdCB7XG4gICAgICAgIF9rZXksXG4gICAgICAgIGdyb3VwSWQsXG4gICAgICAgIHByaXZhY3kgPSAnZGVmYXVsdCdcbiAgICAgIH06IFBvc3RUeXBlID0gcG9zdDtcblxuICAgICAgLy8gUXVlcnkgYmFzZWQgb24gcHJpdmFjeSBsZXZlbFxuICAgICAgbGV0IHByaXZhY3lBcWxRcnk6IHN0cmluZyB8IHVuZGVmaW5lZDtcblxuICAgICAgaWYoZ3JvdXBJZCAmJiBwcml2YWN5ID09PSAnZ3JvdXAnKSB7XG4gICAgICAgIHByaXZhY3lBcWxRcnkgPSBgRk9SIHAgSU4gcG9zdHNcbiAgICAgICAgICBGT1IgdXNlciBJTiB1c2Vyc1xuICAgICAgICAgIEZJTFRFUiBwLnBhcmVudCA9PSBcIiR7X2tleX1cIiAmJiB1c2VyLl9rZXkgPT0gcC51c2VySWRcbiAgICAgICAgICBMRVQgcmVhY3Rpb25zID0gKFxuICAgICAgICAgICAgRk9SIHBvc3QsIHIgSU4gSU5CT1VORCBwLl9pZCByZWFjdGlvbnNcbiAgICAgICAgICAgIENPTExFQ1QgcmVhY3Rpb25OYW1lID0gci52YWx1ZSBJTlRPIHJlYWN0aW9uSXRlbXNcbiAgICAgICAgICAgIFJFVFVSTiB7bmFtZTogcmVhY3Rpb25OYW1lLCBjb3VudDogTEVOR1RIKHJlYWN0aW9uSXRlbXNbKl0uci52YWx1ZSl9XG4gICAgICAgICAgKVxuICAgICAgICAgIEZPUiBncm91cCBJTiBncm91cHNcbiAgICAgICAgICBGSUxURVIgZ3JvdXAuX2tleSA9PSBwLmdyb3VwSWRcbiAgICAgICAgICBGT1IgdSwgZSBJTiBPVVRCT1VORCBncm91cC5faWQgaGFzQ29ubmVjdGlvblxuICAgICAgICAgIEZJTFRFUiB1Ll9rZXkgPT0gXCIke3Nlc3Npb25JZH1cIlxuICAgICAgICAgIFNPUlQgcC5hZGRlZFxuICAgICAgICAgICR7bGltaXQuYXFsfVxuICAgICAgICAgIFJFVFVSTiBNRVJHRShwLCB7dXNlcjogdXNlciwgcmVhY3Rpb25zOiByZWFjdGlvbnN9KWA7XG4gICAgICB9IGVsc2UgaWYocHJpdmFjeSA9PT0gJ3B1YmxpYycpIHtcbiAgICAgICAgcHJpdmFjeUFxbFFyeSA9IGBGT1IgcCBJTiBwb3N0c1xuICAgICAgICAgIEZPUiB1c2VyIElOIHVzZXJzXG4gICAgICAgICAgRklMVEVSIHAucGFyZW50ID09IFwiJHtfa2V5fVwiICYmIHVzZXIuX2tleSA9PSBwLnVzZXJJZFxuICAgICAgICAgIExFVCByZWFjdGlvbnMgPSAoXG4gICAgICAgICAgICBGT1IgcG9zdCwgciBJTiBJTkJPVU5EIHAuX2lkIHJlYWN0aW9uc1xuICAgICAgICAgICAgQ09MTEVDVCByZWFjdGlvbk5hbWUgPSByLnZhbHVlIElOVE8gcmVhY3Rpb25JdGVtc1xuICAgICAgICAgICAgUkVUVVJOIHtuYW1lOiByZWFjdGlvbk5hbWUsIGNvdW50OiBMRU5HVEgocmVhY3Rpb25JdGVtc1sqXS5yLnZhbHVlKX1cbiAgICAgICAgICApXG4gICAgICAgICAgU09SVCBwLmFkZGVkXG4gICAgICAgICAgJHtsaW1pdC5hcWx9XG4gICAgICAgICAgUkVUVVJOIE1FUkdFKHAsIHt1c2VyOiB1c2VyLCByZWFjdGlvbnM6IHJlYWN0aW9uc30pYDtcbiAgICAgIH1cblxuICAgICAgaWYocHJpdmFjeUFxbFFyeSkge1xuICAgICAgICByZXR1cm4gdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShwcml2YWN5QXFsUXJ5KVxuICAgICAgICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5hbGwoKSBhcyB1bmtub3duIGFzIFBvc3RUeXBlW10pXG4gICAgICAgICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgICAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgICAgICAgYWN0aW9uLFxuICAgICAgICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICAgICAgICAgIH0sIGVycm9yLCBjb250ZXh0KTtcblxuICAgICAgICAgICAgcmV0dXJuIFtdIGFzIFBvc3RUeXBlW107XG4gICAgICAgICAgfSk7XG4gICAgICB9XG5cbiAgICAgIHJldHVybiBbXSBhcyBQb3N0VHlwZVtdO1xuICAgIH0pXG4gICAgLmNhdGNoKChlcnJvcjogRXJyb3IpID0+IHtcbiAgICAgIGxvZ0Vycm9yKHtcbiAgICAgICAgYWN0aW9uLFxuICAgICAgICBjYXRlZ29yeTogZXZlbnRDYXRlZ29yeSxcbiAgICAgICAgbGFiZWw6IEVycm9yVHlwZXMuREFUQUJBU0VfRVJST1JcbiAgICAgIH0sIGVycm9yLCBjb250ZXh0KTtcblxuICAgICAgcmV0dXJuIFtdIGFzIFBvc3RUeXBlW107XG4gICAgfSk7XG59O1xuXG5leHBvcnQgY29uc3QgYWRkUG9zdCA9IGFzeW5jIChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAge1xuICAgIGNvbnRlbnQgPSAnJyxcbiAgICBlbmREYXRlLFxuICAgIGdyb3VwSWQgPSAnJyxcbiAgICBsb2NhdGlvbixcbiAgICBsYXRpdHVkZSxcbiAgICBsb25naXR1ZGUsXG4gICAgbmFtZSA9ICcnLFxuICAgIHBhcmVudElkID0gJycsXG4gICAgcHJpdmFjeSA9ICdwdWJsaWMnLFxuICAgIHRhZ3MgPSBbXSxcbiAgICBzdGFydERhdGUsXG4gICAgdHlwZSA9ICdkZWZhdWx0J1xuICB9OiBQb3N0SW5wdXRUeXBlXG4pOiBQcm9taXNlPFBvc3RUeXBlPiA9PiB7XG4gIGNvbnN0IGFjdGlvbjogc3RyaW5nID0gJ2FkZFBvc3QnO1xuICBjb25zdCB7ZGF0YWJhc2VOYW1lLCBzZXNzaW9uOiB7dXNlcklkOiBzZXNzaW9uSWR9ID0ge319ID0gY29udGV4dDtcbiAgY29uc3Qgbm93ID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgcG9zdElkID0gY3JlYXRlSGFzaChgcG9zdC0ke3Nlc3Npb25JZH1gKTtcbiAgY29uc3QgaW5zZXJ0OiBQb3N0VHlwZSA9IHtcbiAgICBfaWQ6IGBwb3N0cy8ke3Bvc3RJZH1gLFxuICAgIF9rZXk6IHBvc3RJZCxcbiAgICBhZGRlZDogbm93LFxuICAgIGNvbnRlbnQ6IHBhcnNlU3RyaW5nKGNvbnRlbnQsIE1BWF9DT05URU5UX0xFTkdUSCkgfHwgJycsXG4gICAgZW5kRGF0ZTogZW5kRGF0ZSA/IHBhcnNlTnVtKGVuZERhdGUsIDEzKSA6IHVuZGVmaW5lZCxcbiAgICBncm91cElkOiBncm91cElkID8gcGFyc2VJZChncm91cElkKSA6IHVuZGVmaW5lZCxcbiAgICBsYXRpdHVkZTogbGF0aXR1ZGUgIT09IHVuZGVmaW5lZCA/IHBhcnNlTnVtKGxhdGl0dWRlKSA6IHVuZGVmaW5lZCxcbiAgICBsb2NhdGlvbjogbG9jYXRpb24gPyBwYXJzZVN0cmluZyhsb2NhdGlvbiwgMTYwKSA6IHVuZGVmaW5lZCxcbiAgICBsb25naXR1ZGU6IGxvbmdpdHVkZSAhPT0gdW5kZWZpbmVkID8gcGFyc2VOdW0obG9uZ2l0dWRlKSA6IHVuZGVmaW5lZCxcbiAgICBtb2RpZmllZDogbm93LFxuICAgIG5hbWU6IHBhcnNlU3RyaW5nKG5hbWUsIDE2MCksXG4gICAgcGFyZW50SWQ6IHBhcmVudElkID8gcGFyc2VJZChwYXJlbnRJZCkgOiB1bmRlZmluZWQsXG4gICAgcHJpdmFjeTogcGFyc2VWYXJDaGFyKHByaXZhY3ksIDE2KSxcbiAgICBzdGFydERhdGU6IHN0YXJ0RGF0ZSA/IHBhcnNlTnVtKHN0YXJ0RGF0ZSwgMTMpIDogdW5kZWZpbmVkLFxuICAgIHR5cGU6IHBhcnNlQ2hhcih0eXBlLCAzMiksXG4gICAgdXNlcklkOiBzZXNzaW9uSWRcbiAgfTtcbiAgY29uc3QgYXFsUXJ5OiBBcWxRdWVyeSA9IGFxbGBJTlNFUlQgJHtpbnNlcnR9IElOIHBvc3RzIFJFVFVSTiBORVdgO1xuXG4gIHRyeSB7XG4gICAgY29uc3Qgc2F2ZWRQb3N0OiBQb3N0VHlwZSA9IGF3YWl0IHVzZURiKGRhdGFiYXNlTmFtZSkucXVlcnkoYXFsUXJ5KVxuICAgICAgLnRoZW4oKGN1cnNvcikgPT4gY3Vyc29yLm5leHQoKSlcbiAgICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiBsb2dFcnJvcih7XG4gICAgICAgIGFjdGlvbixcbiAgICAgICAgY2F0ZWdvcnk6IGV2ZW50Q2F0ZWdvcnksXG4gICAgICAgIGxhYmVsOiBFcnJvclR5cGVzLkRBVEFCQVNFX0VSUk9SXG4gICAgICB9LCBlcnJvciwgY29udGV4dCkpO1xuICAgIGNvbnN0IHtfaWQ6IHBvc3REb2NJZH0gPSBzYXZlZFBvc3Q7XG4gICAgY29uc3QgY29udGVudFRhZ05hbWVzID0gYXdhaXQgZXh0cmFjdFRhZ3MoaW5zZXJ0LmNvbnRlbnQgfHwgJycpO1xuXG4gICAgaWYodGFncy5sZW5ndGggfHwgY29udGVudFRhZ05hbWVzLmxlbmd0aCkge1xuICAgICAgY29uc3QgdXNlclRhZ3MgPSAoYXdhaXQgZ2V0VGFnc0J5TmFtZShjb250ZXh0LCB0YWdzLm1hcCgoe25hbWV9KSA9PiBuYW1lIHx8ICcnKSkpXG4gICAgICAgIC5tYXAoKHRhZykgPT4gKHsuLi50YWcsIHRhZ0J5OiBzZXNzaW9uSWR9KSk7XG4gICAgICBjb25zdCBjb250ZW50VGFncyA9IChhd2FpdCBnZXRUYWdzQnlOYW1lKGNvbnRleHQsIGNvbnRlbnRUYWdOYW1lcyB8fCBbXSkpXG4gICAgICAgIC5tYXAoKHRhZykgPT4gKHsuLi50YWcsIHRhZ0J5OiAnZXh0cmFjdCd9KSk7XG4gICAgICBjb25zdCB1cGRhdGVkVGFnczogVGFnVHlwZVtdID0gYXdhaXQgdXBkYXRlVGFnc0luSXRlbShcbiAgICAgICAgY29udGV4dCxcbiAgICAgICAge1xuICAgICAgICAgIGl0ZW1Eb2NJZDogcG9zdERvY0lkLFxuICAgICAgICAgIHRhZ3M6IFsuLi5jb250ZW50VGFncywgLi4udXNlclRhZ3NdXG4gICAgICAgIH1cbiAgICAgICk7XG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIC4uLnNhdmVkUG9zdCxcbiAgICAgICAgdGFnczogdXBkYXRlZFRhZ3NcbiAgICAgIH07XG4gICAgfVxuXG4gICAgcmV0dXJuIHNhdmVkUG9zdDtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIHRocm93IGVycm9yO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgdXBkYXRlUG9zdCA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCBwb3N0OiBQb3N0SW5wdXRUeXBlKTogUHJvbWlzZTxQb3N0VHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb246IHN0cmluZyA9ICd1cGRhdGVQb3N0JztcbiAgY29uc3Qge2RhdGFiYXNlTmFtZSwgc2Vzc2lvbjoge3VzZXJJZDogc2Vzc2lvbklkfSA9IHt9fSA9IGNvbnRleHQ7XG4gIGNvbnN0IG5vdzogbnVtYmVyID0gRGF0ZS5ub3coKTtcbiAgY29uc3QgcGFyc2VkUG9zdCA9IHBhcnNlUG9zdChwb3N0KTtcbiAgY29uc3Qge1xuICAgIHBvc3RJZCxcbiAgICB0YWdzID0gW11cbiAgfSA9IHBhcnNlZFBvc3Q7XG5cbiAgY29uc3QgdXBkYXRlOiBQb3N0VHlwZSA9IHtcbiAgICAuLi5wYXJzZWRQb3N0LFxuICAgIG1vZGlmaWVkOiBub3dcbiAgfTtcblxuICBpZighcG9zdElkKSB7XG4gICAgdGhyb3cgbG9nRXhjZXB0aW9uKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuSU5WQUxJRF9JRFxuICAgIH0sIGNvbnRleHQpO1xuICB9XG5cbiAgY29uc3QgaW5zZXJ0ID0ge1xuICAgIC4uLnVwZGF0ZSxcbiAgICBfa2V5OiBwb3N0SWQsXG4gICAgYWRkZWQ6IG5vdyxcbiAgICB1c2VySWQ6IHNlc3Npb25JZFxuICB9O1xuICBjb25zdCBhcWxRcnk6IEFxbFF1ZXJ5ID0gYXFsYFVQU0VSVCB7X2tleTogJHtwb3N0SWR9LCB1c2VySWQ6ICR7c2Vzc2lvbklkfX1cbiAgICBJTlNFUlQgJHtpbnNlcnR9XG4gICAgVVBEQVRFICR7dXBkYXRlfVxuICAgIElOIHBvc3RzIFJFVFVSTiBORVdgO1xuXG4gIHRyeSB7XG4gICAgY29uc3QgdXBkYXRlZFBvc3Q6IFBvc3RUeXBlID0gYXdhaXQgdXNlRGIoZGF0YWJhc2VOYW1lKVxuICAgICAgLnF1ZXJ5KGFxbFFyeSlcbiAgICAgIC50aGVuKChjdXJzb3IpID0+IGN1cnNvci5uZXh0KCkpXG4gICAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4gbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgfSwgZXJyb3IsIHt9KSk7XG4gICAgY29uc3Qge19pZDogdXBkYXRlZFBvc3RJZH0gPSB1cGRhdGVkUG9zdDtcbiAgICBjb25zdCBjb250ZW50VGFnTmFtZXMgPSBhd2FpdCBleHRyYWN0VGFncyhpbnNlcnQuY29udGVudCB8fCAnJyk7XG5cbiAgICBpZih0YWdzPy5sZW5ndGggfHwgY29udGVudFRhZ05hbWVzPy5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IHVzZXJUYWdzID0gdGFncz8ubGVuZ3RoID8gKGF3YWl0IGdldFRhZ3NCeU5hbWUoY29udGV4dCwgdGFncy5tYXAoKHtuYW1lfSkgPT4gbmFtZSB8fCAnJykpKVxuICAgICAgICAubWFwKCh0YWcpID0+ICh7Li4udGFnLCB0YWdCeTogc2Vzc2lvbklkfSkpIDogW107XG4gICAgICBjb25zdCBjb250ZW50VGFncyA9IGNvbnRlbnRUYWdOYW1lcz8ubGVuZ3RoID8gKGF3YWl0IGdldFRhZ3NCeU5hbWUoY29udGV4dCwgY29udGVudFRhZ05hbWVzIHx8IFtdKSlcbiAgICAgICAgLm1hcCgodGFnKSA9PiAoey4uLnRhZywgdGFnQnk6ICdleHRyYWN0J30pKSA6IFtdO1xuICAgICAgY29uc3QgdXBkYXRlZFRhZ3M6IFRhZ1R5cGVbXSA9IGF3YWl0IHVwZGF0ZVRhZ3NJbkl0ZW0oXG4gICAgICAgIGNvbnRleHQsXG4gICAgICAgIHtcbiAgICAgICAgICBpdGVtRG9jSWQ6IHVwZGF0ZWRQb3N0SWQsXG4gICAgICAgICAgdGFnczogWy4uLmNvbnRlbnRUYWdzLCAuLi51c2VyVGFnc11cbiAgICAgICAgfVxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgLi4udXBkYXRlZFBvc3QsXG4gICAgICAgIHRhZ3M6IHVwZGF0ZWRUYWdzXG4gICAgICB9O1xuICAgIH1cblxuICAgIHJldHVybiB1cGRhdGVkUG9zdDtcbiAgfSBjYXRjaChlcnJvcikge1xuICAgIHRocm93IGVycm9yO1xuICB9XG59O1xuXG5leHBvcnQgY29uc3QgZGVsZXRlUG9zdCA9IGFzeW5jIChjb250ZXh0OiBBcGlDb250ZXh0LCBwb3N0RG9jSWQ6IHN0cmluZyk6IFByb21pc2U8UG9zdFR5cGU+ID0+IHtcbiAgY29uc3QgYWN0aW9uOiBzdHJpbmcgPSAnZGVsZXRlUG9zdCc7XG4gIGNvbnN0IHtkYXRhYmFzZU5hbWUsIHNlc3Npb246IHt1c2VySWQ6IHNlc3Npb25JZH0gPSB7fX0gPSBjb250ZXh0O1xuICBjb25zdCBmb3JtYXRQb3N0SWQ6IHN0cmluZyA9IHBhcnNlQXJhbmdvSWQocG9zdERvY0lkKTtcblxuICBpZighZm9ybWF0UG9zdElkKSB7XG4gICAgdGhyb3cgbG9nRXhjZXB0aW9uKHtcbiAgICAgIGFjdGlvbixcbiAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgdmFsdWU6IEVycm9yVHlwZXMuSU5WQUxJRF9JRFxuICAgIH0sIGNvbnRleHQpO1xuICB9XG5cbiAgY29uc3QgZWRnZUFxbFFyeTogQXFsUXVlcnkgPSBhcWxgRk9SIHQgSU4gaXNUYWdnZWRcbiAgRklMVEVSIHQuX3RvID09ICR7Zm9ybWF0UG9zdElkfVxuICBSRU1PVkUgdCBJTiBpc1RhZ2dlZGA7XG5cbiAgYXdhaXQgdXNlRGIoZGF0YWJhc2VOYW1lKS5xdWVyeShlZGdlQXFsUXJ5KVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcblxuICBjb25zdCBmaWxlQXFsUXJ5OiBBcWxRdWVyeSA9IGFxbGBGT1IgZiBJTiBoYXNGaWxlXG4gICAgRklMVEVSIGYuX3RvID09ICR7Zm9ybWF0UG9zdElkfVxuICAgIFJFTU9WRSBmIElOIGhhc0ZpbGVgO1xuXG4gIGF3YWl0IHVzZURiKGRhdGFiYXNlTmFtZSkucXVlcnkoZmlsZUFxbFFyeSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgdGhyb3cgZXJyb3I7XG4gICAgfSk7XG5cbiAgY29uc3QgYXFsUXJ5ID0gYXFsYEZPUiBwIElOIHBvc3RzXG4gICAgICBGSUxURVIgcC5faWQgPT0gJHtmb3JtYXRQb3N0SWR9ICYmIHAudXNlcklkID09ICR7c2Vzc2lvbklkfVxuICAgICAgTElNSVQgMVxuICAgICAgUkVNT1ZFIHAgSU4gcG9zdHNcbiAgICAgIFJFVFVSTiBPTERgO1xuXG4gIHJldHVybiB1c2VEYihkYXRhYmFzZU5hbWUpLnF1ZXJ5KGFxbFFyeSlcbiAgICAudGhlbigoY3Vyc29yKSA9PiBjdXJzb3IubmV4dCgpKVxuICAgIC5jYXRjaCgoZXJyb3I6IEVycm9yKSA9PiB7XG4gICAgICB0aHJvdyBlcnJvcjtcbiAgICB9KTtcbn07XG5cbmV4cG9ydCBjb25zdCBjcmVhdGVQb3N0RWRnZSA9IChcbiAgY29udGV4dDogQXBpQ29udGV4dCxcbiAgcG9zdERvY0lkOiBzdHJpbmcsXG4gIGl0ZW1Eb2NJZDogc3RyaW5nLFxuICBlZGdlVHlwZTogc3RyaW5nID0gJ2lzUG9zdGVkJyxcbiAgcHJvcHMgPSB7fVxuKTogUHJvbWlzZTxGaWxlVHlwZT4gPT4ge1xuICBjb25zdCBhY3Rpb24gPSAnY3JlYXRlUG9zdEVkZ2UnO1xuICBjb25zdCB7ZGF0YWJhc2VOYW1lfSA9IGNvbnRleHQ7XG4gIGNvbnN0IGVkZ2VDb2xsZWN0aW9uOiBFZGdlQ29sbGVjdGlvbiA9IHVzZURiKGRhdGFiYXNlTmFtZSkuY29sbGVjdGlvbihlZGdlVHlwZSk7XG4gIGNvbnN0IGZvcm1hdFBvc3RJZDogc3RyaW5nID0gcGFyc2VBcmFuZ29JZChwb3N0RG9jSWQpO1xuICBjb25zdCBmb3JtYXREb2NJZDogc3RyaW5nID0gcGFyc2VBcmFuZ29JZChpdGVtRG9jSWQpO1xuXG4gIGlmKCFmb3JtYXREb2NJZCB8fCAhZm9ybWF0UG9zdElkKSB7XG4gICAgdGhyb3cgbmV3IEVycm9yKEVycm9yVHlwZXMuSU5WQUxJRF9JRCk7XG4gIH1cblxuICBjb25zdCBlZGdlSWQ6IHN0cmluZyA9IGNyZWF0ZUhhc2goYHBvc3RFZGdlLSR7Zm9ybWF0UG9zdElkfS0ke2Zvcm1hdERvY0lkfWApO1xuICBjb25zdCBlZGdlID0ge1xuICAgIF9mcm9tOiBmb3JtYXRQb3N0SWQsXG4gICAgX2tleTogZWRnZUlkLFxuICAgIF90bzogZm9ybWF0RG9jSWQsXG4gICAgYWRkZWQ6IERhdGUubm93KCksXG4gICAgLi4ucHJvcHNcbiAgfTtcblxuICByZXR1cm4gZWRnZUNvbGxlY3Rpb24uc2F2ZShlZGdlLCB7cmV0dXJuTmV3OiB0cnVlfSlcbiAgICAuY2F0Y2goKGVycm9yOiBFcnJvcikgPT4ge1xuICAgICAgdGhyb3cgbG9nRXJyb3Ioe1xuICAgICAgICBhY3Rpb24sXG4gICAgICAgIGNhdGVnb3J5OiBldmVudENhdGVnb3J5LFxuICAgICAgICB2YWx1ZTogRXJyb3JUeXBlcy5EQVRBQkFTRV9FUlJPUlxuICAgICAgfSwgZXJyb3IsIGNvbnRleHQpO1xuICAgIH0pO1xufTtcbiJdLCJuYW1lcyI6WyJwYXJzZU51bSIsImNyZWF0ZUhhc2giLCJwYXJzZUFyYW5nb0lkIiwicGFyc2VDaGFyIiwicGFyc2VJZCIsInBhcnNlU3RyaW5nIiwicGFyc2VWYXJDaGFyIiwiYXFsIiwicGFyc2VQb3N0IiwiRXJyb3JUeXBlcyIsImxvZ0Vycm9yIiwibG9nRXhjZXB0aW9uIiwiZ2V0TGltaXQiLCJ1c2VEYiIsImV4dHJhY3RUYWdzIiwiZ2V0VGFnc0J5TmFtZSIsInVwZGF0ZVRhZ3NJbkl0ZW0iLCJNQVhfQ09OVEVOVF9MRU5HVEgiLCJldmVudENhdGVnb3J5IiwicGFyc2VQb3N0T3B0aW9ucyIsIm9wdGlvbnMiLCJmcm9tIiwibGF0aXR1ZGUiLCJsb25naXR1ZGUiLCJ0byIsInR5cGUiLCJsaW1pdCIsImdldFBvc3RPcHRpb25hbCIsImZpZWxkcyIsInNlc3Npb25JZCIsInJlZHVjZSIsInNlbGVjdHMiLCJmaWVsZCIsInF1ZXJpZXMiLCJwdXNoIiwib2JqZWN0cyIsImdldFBvc3QiLCJjb250ZXh0IiwicG9zdElkIiwiYWN0aW9uIiwiZGF0YWJhc2VOYW1lIiwic2Vzc2lvbiIsInVzZXJJZCIsImZvcm1hdEl0ZW1JZCIsImRhdGFiYXNlIiwic2VsZWN0T2JqZWN0cyIsInNlbGVjdFF1ZXJpZXMiLCJhcWxRcnkiLCJxdWVyeSIsInRoZW4iLCJjdXJzb3IiLCJuZXh0IiwicG9zdCIsIl9pZCIsInBvc3REb2NJZCIsImdyb3VwSWQiLCJwcml2YWN5IiwicHJpdmFjeUFxbFFyeSIsImpvaW4iLCJjYXRjaCIsImVycm9yIiwiY2F0ZWdvcnkiLCJsYWJlbCIsIkRBVEFCQVNFX0VSUk9SIiwiZ2V0UG9zdHNCeUFyZWEiLCJmb3JtYXRMYXRpdHVkZSIsImZvcm1hdExvbmdpdHVkZSIsImFsbCIsImdldFBvc3RzQnlMYXRlc3QiLCJnZXRQb3N0c0J5UmVhY3Rpb25zIiwicmVhY3Rpb25zIiwiZm9ybWF0U2Vzc2lvbklkIiwiZm9ybWF0UmVhY3Rpb25zIiwiSlNPTiIsInN0cmluZ2lmeSIsIm1hcCIsInJlYWN0aW9uIiwidG9Mb3dlckNhc2UiLCJzb3J0QnkiLCJmaWx0ZXJzIiwibGVuZ3RoIiwiZ2V0UG9zdHNCeVRhZ3MiLCJ0YWdzIiwiZm9ybWF0VGFnTmFtZXMiLCJ0YWciLCJnZXRQb3N0c0J5VXNlciIsImZvcm1hdFVzZXJJZCIsImdldFBvc3RDb21tZW50cyIsIl9rZXkiLCJhZGRQb3N0IiwiY29udGVudCIsImVuZERhdGUiLCJsb2NhdGlvbiIsIm5hbWUiLCJwYXJlbnRJZCIsInN0YXJ0RGF0ZSIsIm5vdyIsIkRhdGUiLCJpbnNlcnQiLCJhZGRlZCIsInVuZGVmaW5lZCIsIm1vZGlmaWVkIiwic2F2ZWRQb3N0IiwiY29udGVudFRhZ05hbWVzIiwidXNlclRhZ3MiLCJ0YWdCeSIsImNvbnRlbnRUYWdzIiwidXBkYXRlZFRhZ3MiLCJpdGVtRG9jSWQiLCJ1cGRhdGVQb3N0IiwicGFyc2VkUG9zdCIsInVwZGF0ZSIsInZhbHVlIiwiSU5WQUxJRF9JRCIsInVwZGF0ZWRQb3N0IiwidXBkYXRlZFBvc3RJZCIsImRlbGV0ZVBvc3QiLCJmb3JtYXRQb3N0SWQiLCJlZGdlQXFsUXJ5IiwiZmlsZUFxbFFyeSIsImNyZWF0ZVBvc3RFZGdlIiwiZWRnZVR5cGUiLCJwcm9wcyIsImVkZ2VDb2xsZWN0aW9uIiwiY29sbGVjdGlvbiIsImZvcm1hdERvY0lkIiwiRXJyb3IiLCJlZGdlSWQiLCJlZGdlIiwiX2Zyb20iLCJfdG8iLCJzYXZlIiwicmV0dXJuTmV3Il0sIm1hcHBpbmdzIjoiQUFBQTs7O0NBR0MsR0FDRCxTQUFTQSxRQUFRLFFBQVEsK0JBQStCO0FBQ3hELFNBQ0lDLFVBQVUsRUFBRUMsYUFBYSxFQUFFQyxTQUFTLEVBQUVDLE9BQU8sRUFBRUMsV0FBVyxFQUFFQyxZQUFZLFFBQ3JFLCtCQUErQjtBQUN0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
|