payload-auth 1.4.0 → 1.5.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/dist/better-auth/adapter/index.d.ts +10 -0
- package/dist/better-auth/adapter/index.d.ts.map +1 -1
- package/dist/better-auth/adapter/index.js +151 -125
- package/dist/better-auth/adapter/transform/index.d.ts +2 -4
- package/dist/better-auth/adapter/transform/index.d.ts.map +1 -1
- package/dist/better-auth/adapter/transform/index.js +435 -311
- package/dist/better-auth/generated-types.d.ts +216 -0
- package/dist/better-auth/generated-types.d.ts.map +1 -0
- package/dist/better-auth/generated-types.js +4 -0
- package/dist/better-auth/plugin/constants.d.ts +146 -3
- package/dist/better-auth/plugin/constants.d.ts.map +1 -1
- package/dist/better-auth/plugin/constants.js +149 -6
- package/dist/better-auth/plugin/helpers/check-plugin-exists.d.ts +13 -0
- package/dist/better-auth/plugin/helpers/check-plugin-exists.d.ts.map +1 -0
- package/dist/better-auth/plugin/helpers/check-plugin-exists.js +14 -0
- package/dist/better-auth/plugin/helpers/get-better-auth-schema.d.ts +22 -0
- package/dist/better-auth/plugin/helpers/get-better-auth-schema.d.ts.map +1 -0
- package/dist/better-auth/plugin/helpers/get-better-auth-schema.js +50 -0
- package/dist/better-auth/plugin/helpers/get-collection-schema-map.d.ts +16 -0
- package/dist/better-auth/plugin/helpers/get-collection-schema-map.d.ts.map +1 -0
- package/dist/better-auth/plugin/helpers/get-collection-schema-map.js +108 -0
- package/dist/better-auth/plugin/helpers/get-collection-slug.d.ts +6 -0
- package/dist/better-auth/plugin/helpers/get-collection-slug.d.ts.map +1 -0
- package/dist/better-auth/plugin/helpers/get-collection-slug.js +20 -0
- package/dist/better-auth/plugin/helpers/get-collection.d.ts +41 -0
- package/dist/better-auth/plugin/helpers/get-collection.d.ts.map +1 -0
- package/dist/better-auth/plugin/helpers/get-collection.js +62 -0
- package/dist/better-auth/plugin/helpers/prepare-session-data.d.ts +52 -14
- package/dist/better-auth/plugin/helpers/prepare-session-data.d.ts.map +1 -1
- package/dist/better-auth/plugin/helpers/prepare-session-data.js +41 -35
- package/dist/better-auth/plugin/index.d.ts +3 -3
- package/dist/better-auth/plugin/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/index.js +31 -40
- package/dist/better-auth/plugin/lib/build-collections/accounts/hooks/sync-password-to-user.d.ts +2 -6
- package/dist/better-auth/plugin/lib/build-collections/accounts/hooks/sync-password-to-user.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/accounts/hooks/sync-password-to-user.js +22 -7
- package/dist/better-auth/plugin/lib/build-collections/accounts/index.d.ts +3 -6
- package/dist/better-auth/plugin/lib/build-collections/accounts/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/accounts/index.js +96 -102
- package/dist/better-auth/plugin/lib/build-collections/admin-invitations/index.d.ts +2 -2
- package/dist/better-auth/plugin/lib/build-collections/admin-invitations/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/admin-invitations/index.js +6 -5
- package/dist/better-auth/plugin/lib/build-collections/api-keys.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/api-keys.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/api-keys.js +97 -113
- package/dist/better-auth/plugin/lib/build-collections/index.d.ts +6 -6
- package/dist/better-auth/plugin/lib/build-collections/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/index.js +68 -84
- package/dist/better-auth/plugin/lib/build-collections/invitations.d.ts +2 -4
- package/dist/better-auth/plugin/lib/build-collections/invitations.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/invitations.js +75 -70
- package/dist/better-auth/plugin/lib/build-collections/jwks.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/jwks.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/jwks.js +46 -28
- package/dist/better-auth/plugin/lib/build-collections/members.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/members.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/members.js +52 -48
- package/dist/better-auth/plugin/lib/build-collections/oauth-access-tokens.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/oauth-access-tokens.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/oauth-access-tokens.js +74 -64
- package/dist/better-auth/plugin/lib/build-collections/oauth-applications.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/oauth-applications.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/oauth-applications.js +78 -71
- package/dist/better-auth/plugin/lib/build-collections/oauth-consents.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/oauth-consents.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/oauth-consents.js +68 -45
- package/dist/better-auth/plugin/lib/build-collections/organizations.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/organizations.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/organizations.js +52 -39
- package/dist/better-auth/plugin/lib/build-collections/passkeys.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/passkeys.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/passkeys.js +60 -64
- package/dist/better-auth/plugin/lib/build-collections/sessions.d.ts +3 -7
- package/dist/better-auth/plugin/lib/build-collections/sessions.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/sessions.js +100 -96
- package/dist/better-auth/plugin/lib/build-collections/sso-providers.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/sso-providers.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/sso-providers.js +56 -56
- package/dist/better-auth/plugin/lib/build-collections/subscriptions.d.ts +4 -0
- package/dist/better-auth/plugin/lib/build-collections/subscriptions.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/build-collections/subscriptions.js +113 -0
- package/dist/better-auth/plugin/lib/build-collections/teams.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/teams.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/teams.js +62 -30
- package/dist/better-auth/plugin/lib/build-collections/two-factors.d.ts +3 -5
- package/dist/better-auth/plugin/lib/build-collections/two-factors.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/two-factors.js +50 -37
- package/dist/better-auth/plugin/lib/build-collections/users/better-auth-strategy.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/better-auth-strategy.js +5 -5
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/generate-invite-url.js +3 -3
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/index.d.ts +6 -0
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/index.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/index.js +7 -0
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/set-admin-role.js +4 -4
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/signup.d.ts +2 -2
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/signup.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/endpoints/signup.js +93 -96
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-login.d.ts +1 -6
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-login.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-login.js +27 -16
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-logout.d.ts +1 -5
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-logout.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/after-logout.js +16 -8
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/before-delete.d.ts +2 -6
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/before-delete.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/before-delete.js +25 -6
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/before-login.d.ts +2 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/before-login.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/before-login.js +5 -8
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/index.d.ts +7 -0
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/index.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/index.js +8 -0
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/on-verified-change.d.ts +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/on-verified-change.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/on-verified-change.js +15 -12
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/sync-account.d.ts +1 -6
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/sync-account.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/hooks/sync-account.js +21 -10
- package/dist/better-auth/plugin/lib/build-collections/users/index.d.ts +3 -7
- package/dist/better-auth/plugin/lib/build-collections/users/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/users/index.js +153 -210
- package/dist/better-auth/plugin/lib/build-collections/utils/collection-schema.d.ts +16 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/collection-schema.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/collection-schema.js +32 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/get-timestamp-fields.d.ts +1 -1
- package/dist/better-auth/plugin/lib/build-collections/utils/get-timestamp-fields.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/utils/get-timestamp-fields.js +1 -1
- package/dist/better-auth/plugin/lib/build-collections/utils/model-field-transformations.d.ts +17 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/model-field-transformations.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/model-field-transformations.js +21 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/transform-schema-fields-to-payload.d.ts +22 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/transform-schema-fields-to-payload.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/build-collections/utils/transform-schema-fields-to-payload.js +95 -0
- package/dist/better-auth/plugin/lib/build-collections/verifications.d.ts +3 -6
- package/dist/better-auth/plugin/lib/build-collections/verifications.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/build-collections/verifications.js +62 -40
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/admin-plugin.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/admin-plugin.js +4 -3
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/api-key-plugin.d.ts +2 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/api-key-plugin.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/api-key-plugin.js +8 -15
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/index.d.ts +5 -3
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/index.js +56 -69
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/oidc-plugin.d.ts +2 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/oidc-plugin.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/oidc-plugin.js +16 -55
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/organizations-plugin.d.ts +2 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/organizations-plugin.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/organizations-plugin.js +21 -83
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/passkey-plugin.d.ts +2 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/passkey-plugin.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/passkey-plugin.js +8 -15
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/sso-plugin.d.ts +2 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/sso-plugin.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/sso-plugin.js +8 -15
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/two-factor-plugin.d.ts +3 -0
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/two-factor-plugin.d.ts.map +1 -0
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/two-factor-plugin.js +10 -0
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/require-admin-invite-for-sign-up-middleware.d.ts +3 -3
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/require-admin-invite-for-sign-up-middleware.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/require-admin-invite-for-sign-up-middleware.js +3 -3
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/save-to-jwt-middleware.d.ts +5 -4
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/save-to-jwt-middleware.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/sanitize-better-auth-options/utils/save-to-jwt-middleware.js +19 -17
- package/dist/better-auth/plugin/lib/set-login-methods.d.ts +1 -1
- package/dist/better-auth/plugin/lib/set-login-methods.d.ts.map +1 -1
- package/dist/better-auth/plugin/lib/set-login-methods.js +5 -6
- package/dist/better-auth/plugin/payload/views/admin-login/client.d.ts.map +1 -1
- package/dist/better-auth/plugin/payload/views/admin-login/client.js +2 -2
- package/dist/better-auth/plugin/payload/views/admin-login/index.d.ts +4 -4
- package/dist/better-auth/plugin/payload/views/admin-login/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/payload/views/admin-login/index.js +7 -8
- package/dist/better-auth/plugin/payload/views/admin-signup/client.d.ts +1 -1
- package/dist/better-auth/plugin/payload/views/admin-signup/client.d.ts.map +1 -1
- package/dist/better-auth/plugin/payload/views/admin-signup/client.js +27 -7
- package/dist/better-auth/plugin/payload/views/admin-signup/index.d.ts +4 -5
- package/dist/better-auth/plugin/payload/views/admin-signup/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/payload/views/admin-signup/index.js +6 -6
- package/dist/better-auth/plugin/payload/views/forgot-password/index.d.ts +1 -5
- package/dist/better-auth/plugin/payload/views/forgot-password/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/payload/views/forgot-password/index.js +1 -1
- package/dist/better-auth/plugin/payload/views/two-factor-verify/index.d.ts +3 -3
- package/dist/better-auth/plugin/payload/views/two-factor-verify/index.d.ts.map +1 -1
- package/dist/better-auth/plugin/payload/views/two-factor-verify/index.js +10 -7
- package/dist/better-auth/plugin/types.d.ts +41 -13
- package/dist/better-auth/plugin/types.d.ts.map +1 -1
- package/dist/better-auth/plugin/types.js +1 -1
- package/dist/better-auth/plugin/utils/set.d.ts +40 -0
- package/dist/better-auth/plugin/utils/set.d.ts.map +1 -0
- package/dist/better-auth/plugin/utils/set.js +84 -0
- package/dist/better-auth/scripts/generate-types.d.ts +2 -0
- package/dist/better-auth/scripts/generate-types.d.ts.map +1 -0
- package/dist/better-auth/scripts/generate-types.js +219 -0
- package/dist/shared/form/validation.d.ts +31 -7
- package/dist/shared/form/validation.d.ts.map +1 -1
- package/dist/shared/form/validation.js +13 -5
- package/package.json +14 -4
- package/dist/better-auth/plugin/helpers/check-passkey-plugin.d.ts +0 -3
- package/dist/better-auth/plugin/helpers/check-passkey-plugin.d.ts.map +0 -1
- package/dist/better-auth/plugin/helpers/check-passkey-plugin.js +0 -6
- package/dist/better-auth/plugin/helpers/check-two-factor-plugin.d.ts +0 -3
- package/dist/better-auth/plugin/helpers/check-two-factor-plugin.d.ts.map +0 -1
- package/dist/better-auth/plugin/helpers/check-two-factor-plugin.js +0 -6
- package/dist/better-auth/plugin/helpers/check-username-plugin.d.ts +0 -3
- package/dist/better-auth/plugin/helpers/check-username-plugin.d.ts.map +0 -1
- package/dist/better-auth/plugin/helpers/check-username-plugin.js +0 -6
- package/dist/better-auth/plugin/lib/get-required-collection-slugs.d.ts +0 -10
- package/dist/better-auth/plugin/lib/get-required-collection-slugs.d.ts.map +0 -1
- package/dist/better-auth/plugin/lib/get-required-collection-slugs.js +0 -35
- package/dist/better-auth/plugin/payload/utils/generate-metadata.d.ts +0 -15
- package/dist/better-auth/plugin/payload/utils/generate-metadata.d.ts.map +0 -1
- package/dist/better-auth/plugin/payload/utils/generate-metadata.js +0 -74
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { BetterAuthError } from "better-auth";
|
|
2
1
|
import { getAuthTables } from "better-auth/db";
|
|
3
2
|
export const createTransform = (options, enableDebugLogs)=>{
|
|
4
3
|
const schema = getAuthTables(options);
|
|
@@ -7,19 +6,82 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
7
6
|
console.log(`[payload-db-adapter]`, ...message);
|
|
8
7
|
}
|
|
9
8
|
}
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Maps a BetterAuth schema model name to its corresponding Payload CMS collection slug.
|
|
11
|
+
*
|
|
12
|
+
* This function resolves the appropriate collection slug by:
|
|
13
|
+
* 1. Looking up the model in the BetterAuth schema to find its configured modelName
|
|
14
|
+
* 2. Falling back to the original model name if no mapping exists
|
|
15
|
+
*
|
|
16
|
+
* Collection slug resolution follows these rules:
|
|
17
|
+
* - For base collections: The sanitizeBetterAuthOptions function ensures the collection slug
|
|
18
|
+
* from plugin options is set as the model name in the schema
|
|
19
|
+
* - For plugins: The betterAuthPluginSlugs constant is used as the modelName
|
|
20
|
+
*
|
|
21
|
+
* @param model - The BetterAuth model name to resolve
|
|
22
|
+
* @returns The corresponding Payload CMS collection slug
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // If schema['user'].modelName is 'users'
|
|
26
|
+
* getCollectionSlug('user') // Returns 'users'
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* // If model doesn't exist in schema
|
|
30
|
+
* getCollectionSlug('custom') // Returns 'custom'
|
|
31
|
+
*
|
|
32
|
+
* @warning If a collection is overridden using the collectionOverride option
|
|
33
|
+
* without updating the schema mapping, this function may return incorrect slugs
|
|
34
|
+
*/ function getCollectionSlug(model) {
|
|
35
|
+
// First try to get the modelName from schema, otherwise fall back to the original model name
|
|
11
36
|
const collection = schema[model]?.modelName || model;
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
37
|
+
debugLog([
|
|
38
|
+
'getCollectionSlug:',
|
|
39
|
+
{
|
|
40
|
+
model,
|
|
41
|
+
resolvedSlug: collection
|
|
42
|
+
}
|
|
43
|
+
]);
|
|
15
44
|
return collection;
|
|
16
45
|
}
|
|
17
|
-
|
|
18
|
-
|
|
46
|
+
/**
|
|
47
|
+
* Maps a BetterAuth schema field to its corresponding Payload CMS field name.
|
|
48
|
+
*
|
|
49
|
+
* This function resolves the appropriate field name by:
|
|
50
|
+
* 1. Preserving 'id' or '_id' fields as-is (special case handling)
|
|
51
|
+
* 2. Looking up the field in the BetterAuth schema to find its configured fieldName
|
|
52
|
+
* 3. Falling back to the original field name if no mapping exists
|
|
53
|
+
*
|
|
54
|
+
* @param model - The BetterAuth model name containing the field
|
|
55
|
+
* @param field - The original field name to resolve
|
|
56
|
+
* @returns The corresponding Payload CMS field name
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* // If schema['user'].fields['email'].fieldName is 'emailAddress'
|
|
60
|
+
* getFieldName('user', 'email') // Returns 'emailAddress'
|
|
61
|
+
*
|
|
62
|
+
* @example
|
|
63
|
+
* // Special case for ID fields
|
|
64
|
+
* getFieldName('user', 'id') // Always returns 'id'
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* // If field doesn't exist in schema or has no fieldName mapping
|
|
68
|
+
* getFieldName('user', 'custom') // Returns 'custom'
|
|
69
|
+
*
|
|
70
|
+
* @warning If a fieldName is overridden in the payload collection config using the collectionOverride option
|
|
71
|
+
* without updating the schema mapping, this function may return incorrect field names
|
|
72
|
+
*/ function getFieldName(model, field) {
|
|
73
|
+
// Special case: 'id' or '_id' is always preserved as-is
|
|
74
|
+
if ([
|
|
75
|
+
'id',
|
|
76
|
+
'_id'
|
|
77
|
+
].includes(field)) {
|
|
19
78
|
return field;
|
|
20
79
|
}
|
|
21
|
-
|
|
22
|
-
const
|
|
80
|
+
// Look up the field in the schema
|
|
81
|
+
const fieldDefinition = schema[model]?.fields[field];
|
|
82
|
+
// Use the configured fieldName if available, otherwise fall back to original
|
|
83
|
+
const fieldName = fieldDefinition?.fieldName || field;
|
|
84
|
+
// Log the field resolution for debugging
|
|
23
85
|
debugLog([
|
|
24
86
|
'getField: ',
|
|
25
87
|
{
|
|
@@ -30,372 +92,350 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
30
92
|
]);
|
|
31
93
|
return fieldName;
|
|
32
94
|
}
|
|
33
|
-
|
|
34
|
-
|
|
95
|
+
/**
|
|
96
|
+
* Determines if a field is a relationship field by checking for a references property.
|
|
97
|
+
*
|
|
98
|
+
* Relationship fields in the schema have a 'references' property that points to another model.
|
|
99
|
+
* This function checks if this property exists to identify relationship fields.
|
|
100
|
+
*
|
|
101
|
+
* @param fieldKey - The key of the field to check in the schema
|
|
102
|
+
* @param schemaFields - Object containing all fields from the schema for a specific model
|
|
103
|
+
* @returns True if the field is a relationship field (has references), false otherwise
|
|
104
|
+
*
|
|
105
|
+
* @example
|
|
106
|
+
* // If schema.user.fields.posts has { references: {} }
|
|
107
|
+
* isRelationshipField('posts', schema.user.fields) // Returns true
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // If schema.user.fields.email has no references property
|
|
111
|
+
* isRelationshipField('email', schema.user.fields) // Returns false
|
|
112
|
+
*/ function isRelationshipField(fieldKey, schemaFields) {
|
|
113
|
+
// A field is a relationship field if it has a 'references' property defined
|
|
114
|
+
return schemaFields[fieldKey]?.references !== undefined;
|
|
35
115
|
}
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
116
|
+
/**
|
|
117
|
+
* Determines if a value is a valid date string that can be parsed into a Date object.
|
|
118
|
+
*
|
|
119
|
+
* This utility function checks if a value is a string and can be successfully parsed
|
|
120
|
+
* into a JavaScript Date object using Date.parse(). It's used to identify date fields
|
|
121
|
+
* during data transformation processes.
|
|
122
|
+
*
|
|
123
|
+
* @param value - The value to check if it's a valid date string
|
|
124
|
+
* @returns True if the value is a string that can be parsed as a date, false otherwise
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* // Returns true for ISO date strings
|
|
128
|
+
* isDateField('2023-01-01T12:00:00Z') // true
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* // Returns false for non-date strings or other types
|
|
132
|
+
* isDateField('not a date') // false
|
|
133
|
+
* isDateField(123) // false
|
|
134
|
+
*/ function isDateField(value) {
|
|
135
|
+
// Check if value is a string and can be parsed as a valid date
|
|
136
|
+
return typeof value === 'string' && !isNaN(Date.parse(value));
|
|
42
137
|
}
|
|
43
|
-
|
|
138
|
+
/**
|
|
139
|
+
* Extracts a single ID value from a Payload where clause if it represents a simple ID query.
|
|
140
|
+
*
|
|
141
|
+
* This function analyzes a Payload where clause to determine if it's a simple query for a
|
|
142
|
+
* single document by ID. It supports both 'id' and '_id' fields with 'equals' or 'contains'
|
|
143
|
+
* operators. This is useful for optimizing queries when we only need to fetch a single document.
|
|
144
|
+
*
|
|
145
|
+
* @param where - The Payload where clause to analyze
|
|
146
|
+
* @returns The ID value (string or number) if the where clause is a simple ID query, null otherwise
|
|
147
|
+
*
|
|
148
|
+
* @example
|
|
149
|
+
* // Returns '123' for a simple equals query
|
|
150
|
+
* singleIdQuery({ id: { equals: '123' } }) // '123'
|
|
151
|
+
*
|
|
152
|
+
* @example
|
|
153
|
+
* // Returns 456 for a simple equals query with number ID
|
|
154
|
+
* singleIdQuery({ _id: { equals: 456 } }) // 456
|
|
155
|
+
*
|
|
156
|
+
* @example
|
|
157
|
+
* // Returns '789' for a contains query with a single value
|
|
158
|
+
* singleIdQuery({ id: { contains: ['789'] } }) // '789'
|
|
159
|
+
*
|
|
160
|
+
* @example
|
|
161
|
+
* // Returns null for complex queries
|
|
162
|
+
* singleIdQuery({ and: [{ id: { equals: '123' } }] }) // null
|
|
163
|
+
*/ function singleIdQuery(where) {
|
|
164
|
+
// Return null for empty where clauses or complex queries with 'and'/'or' operators
|
|
44
165
|
if (!where || 'and' in where || 'or' in where) return null;
|
|
45
|
-
//
|
|
46
|
-
|
|
47
|
-
|
|
166
|
+
// Check if the where clause contains either 'id' or '_id' field
|
|
167
|
+
if ([
|
|
168
|
+
'id',
|
|
169
|
+
'_id'
|
|
170
|
+
].some((field)=>field in where)) {
|
|
171
|
+
// Determine which ID field is being used (support both 'id' and '_id')
|
|
48
172
|
const idField = 'id' in where ? 'id' : '_id';
|
|
49
173
|
const condition = where[idField];
|
|
50
|
-
//
|
|
174
|
+
// Process the equals operator case
|
|
51
175
|
if (condition && typeof condition === 'object' && !Array.isArray(condition) && 'equals' in condition) {
|
|
52
176
|
const value = condition.equals;
|
|
177
|
+
// Only return string or number ID values
|
|
53
178
|
if (typeof value === 'string' || typeof value === 'number') {
|
|
54
179
|
return value;
|
|
55
180
|
}
|
|
56
181
|
}
|
|
57
|
-
//
|
|
182
|
+
// Process the contains operator case with a single value
|
|
58
183
|
if (condition && typeof condition === 'object' && !Array.isArray(condition) && 'contains' in condition && Array.isArray(condition.contains) && condition.contains.length === 1) {
|
|
59
184
|
const value = condition.contains[0];
|
|
185
|
+
// Only return string or number ID values
|
|
60
186
|
if (typeof value === 'string' || typeof value === 'number') {
|
|
61
187
|
return value;
|
|
62
188
|
}
|
|
63
189
|
}
|
|
64
190
|
}
|
|
191
|
+
// Return null if no valid ID query was found
|
|
65
192
|
return null;
|
|
66
193
|
}
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
}
|
|
83
|
-
function normalizeData({ fieldKey, incomingValue, schemaFields, relationshipField, idType }) {
|
|
84
|
-
// Early return for null/undefined values
|
|
85
|
-
if (incomingValue === null || incomingValue === undefined) {
|
|
86
|
-
return incomingValue;
|
|
87
|
-
}
|
|
88
|
-
//special case for accountId field in accounts collection
|
|
89
|
-
if (fieldKey === 'accountId') {
|
|
90
|
-
return String(incomingValue);
|
|
194
|
+
/**
|
|
195
|
+
* Normalizes data values based on field type and required ID type
|
|
196
|
+
*
|
|
197
|
+
* This function handles type conversion for relationship fields to ensure
|
|
198
|
+
* IDs are in the correct format (string or number) based on the configuration.
|
|
199
|
+
*
|
|
200
|
+
* @param key - The field key/name
|
|
201
|
+
* @param value - The value to normalize
|
|
202
|
+
* @param isRelatedField - Whether this field is a relationship field
|
|
203
|
+
* @param idType - The expected ID type ('number' or 'text')
|
|
204
|
+
* @returns The normalized value
|
|
205
|
+
*/ function normalizeData({ key, value, isRelatedField, idType }) {
|
|
206
|
+
// Skip processing for null/undefined values
|
|
207
|
+
if (value === null || value === undefined) {
|
|
208
|
+
return value;
|
|
91
209
|
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
210
|
+
if ([
|
|
211
|
+
'id',
|
|
212
|
+
'_id'
|
|
213
|
+
].includes(key)) {
|
|
214
|
+
if (typeof value === 'string' && idType === 'number') {
|
|
215
|
+
const parsed = parseInt(value, 10);
|
|
96
216
|
if (!isNaN(parsed)) {
|
|
97
217
|
debugLog([
|
|
98
|
-
`ID conversion: ${
|
|
218
|
+
`ID conversion: ${key} converting string ID to number`,
|
|
99
219
|
{
|
|
100
|
-
original:
|
|
220
|
+
original: value,
|
|
101
221
|
converted: parsed
|
|
102
222
|
}
|
|
103
223
|
]);
|
|
104
224
|
return parsed;
|
|
105
225
|
}
|
|
106
|
-
}
|
|
107
|
-
|
|
226
|
+
}
|
|
227
|
+
if (typeof value === 'number' && idType === 'text') {
|
|
228
|
+
const stringId = String(value);
|
|
108
229
|
debugLog([
|
|
109
|
-
`ID conversion: ${
|
|
230
|
+
`ID conversion: ${key} converting number ID to string`,
|
|
110
231
|
{
|
|
111
|
-
original:
|
|
232
|
+
original: value,
|
|
112
233
|
converted: stringId
|
|
113
234
|
}
|
|
114
235
|
]);
|
|
115
236
|
return stringId;
|
|
116
237
|
}
|
|
117
|
-
// Handle array of IDs
|
|
118
|
-
if (Array.isArray(incomingValue)) {
|
|
119
|
-
return incomingValue.map((id)=>{
|
|
120
|
-
if (idType === 'number' && typeof id === 'string') {
|
|
121
|
-
const parsed = parseInt(id, 10);
|
|
122
|
-
return !isNaN(parsed) ? parsed : id;
|
|
123
|
-
} else if (idType === 'text' && typeof id === 'number') {
|
|
124
|
-
return String(id);
|
|
125
|
-
}
|
|
126
|
-
return id;
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
return incomingValue;
|
|
130
238
|
}
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
// Handle string type
|
|
138
|
-
if (fieldType === 'string') {
|
|
139
|
-
if (typeof incomingValue !== 'string') {
|
|
140
|
-
if (incomingValue instanceof Date) {
|
|
141
|
-
const converted = incomingValue.toISOString();
|
|
142
|
-
debugLog([
|
|
143
|
-
`Type conversion: ${fieldKey} expected string but got Date`,
|
|
144
|
-
{
|
|
145
|
-
original: incomingValue,
|
|
146
|
-
converted
|
|
147
|
-
}
|
|
148
|
-
]);
|
|
149
|
-
return converted;
|
|
150
|
-
}
|
|
151
|
-
const converted = String(incomingValue);
|
|
152
|
-
debugLog([
|
|
153
|
-
`Type conversion: ${fieldKey} expected string but got ${typeof incomingValue}`,
|
|
154
|
-
{
|
|
155
|
-
original: incomingValue,
|
|
156
|
-
converted
|
|
157
|
-
}
|
|
158
|
-
]);
|
|
159
|
-
return converted;
|
|
160
|
-
}
|
|
161
|
-
return incomingValue;
|
|
162
|
-
}
|
|
163
|
-
// Handle number type
|
|
164
|
-
if (fieldType === 'number') {
|
|
165
|
-
if (typeof incomingValue !== 'number') {
|
|
166
|
-
if (incomingValue instanceof Date) {
|
|
167
|
-
const converted = incomingValue.getTime();
|
|
168
|
-
debugLog([
|
|
169
|
-
`Type conversion: ${fieldKey} expected number but got Date`,
|
|
170
|
-
{
|
|
171
|
-
original: incomingValue,
|
|
172
|
-
converted
|
|
173
|
-
}
|
|
174
|
-
]);
|
|
175
|
-
return converted;
|
|
176
|
-
}
|
|
177
|
-
if (typeof incomingValue === 'boolean') {
|
|
178
|
-
const converted = incomingValue ? 1 : 0;
|
|
239
|
+
// Only process relationship fields that need type conversion
|
|
240
|
+
if (isRelatedField) {
|
|
241
|
+
// Handle single ID value conversion
|
|
242
|
+
if (typeof value === 'string' && idType === 'number') {
|
|
243
|
+
const parsed = parseInt(value, 10);
|
|
244
|
+
if (!isNaN(parsed)) {
|
|
179
245
|
debugLog([
|
|
180
|
-
`
|
|
246
|
+
`ID conversion: ${key} converting string ID to number`,
|
|
181
247
|
{
|
|
182
|
-
original:
|
|
183
|
-
converted
|
|
248
|
+
original: value,
|
|
249
|
+
converted: parsed
|
|
184
250
|
}
|
|
185
251
|
]);
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
if (typeof incomingValue === 'string') {
|
|
189
|
-
const parsed = parseFloat(incomingValue);
|
|
190
|
-
if (!isNaN(parsed)) {
|
|
191
|
-
debugLog([
|
|
192
|
-
`Type conversion: ${fieldKey} expected number but got string`,
|
|
193
|
-
{
|
|
194
|
-
original: incomingValue,
|
|
195
|
-
converted: parsed
|
|
196
|
-
}
|
|
197
|
-
]);
|
|
198
|
-
return parsed;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return incomingValue;
|
|
203
|
-
}
|
|
204
|
-
// Handle boolean type
|
|
205
|
-
if (fieldType === 'boolean') {
|
|
206
|
-
if (typeof incomingValue !== 'boolean') {
|
|
207
|
-
let converted;
|
|
208
|
-
if (typeof incomingValue === 'string') {
|
|
209
|
-
converted = incomingValue.toLowerCase() === 'true' || incomingValue === '1';
|
|
210
|
-
} else if (typeof incomingValue === 'number') {
|
|
211
|
-
converted = incomingValue !== 0;
|
|
212
|
-
} else {
|
|
213
|
-
converted = !!incomingValue;
|
|
252
|
+
return parsed;
|
|
214
253
|
}
|
|
254
|
+
} else if (typeof value === 'number' && idType === 'text') {
|
|
255
|
+
const stringId = String(value);
|
|
215
256
|
debugLog([
|
|
216
|
-
`
|
|
257
|
+
`ID conversion: ${key} converting number ID to string`,
|
|
217
258
|
{
|
|
218
|
-
original:
|
|
219
|
-
converted
|
|
259
|
+
original: value,
|
|
260
|
+
converted: stringId
|
|
220
261
|
}
|
|
221
262
|
]);
|
|
222
|
-
return
|
|
263
|
+
return stringId;
|
|
223
264
|
}
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (
|
|
233
|
-
|
|
234
|
-
`Type conversion: ${fieldKey} expected Date but got ${typeof incomingValue}`,
|
|
235
|
-
{
|
|
236
|
-
original: incomingValue,
|
|
237
|
-
converted
|
|
238
|
-
}
|
|
239
|
-
]);
|
|
240
|
-
return converted;
|
|
265
|
+
// Handle array of IDs - map each value to the correct type
|
|
266
|
+
if (Array.isArray(value)) {
|
|
267
|
+
return value.map((id)=>{
|
|
268
|
+
// Skip null/undefined values in arrays
|
|
269
|
+
if (id === null || id === undefined) return id;
|
|
270
|
+
if (idType === 'number' && typeof id === 'string') {
|
|
271
|
+
const parsed = parseInt(id, 10);
|
|
272
|
+
return !isNaN(parsed) ? parsed : id;
|
|
273
|
+
} else if (idType === 'text' && typeof id === 'number') {
|
|
274
|
+
return String(id);
|
|
241
275
|
}
|
|
242
|
-
|
|
276
|
+
return id;
|
|
277
|
+
});
|
|
243
278
|
}
|
|
244
|
-
return incomingValue;
|
|
245
279
|
}
|
|
246
|
-
//
|
|
247
|
-
|
|
248
|
-
const baseType = fieldType.slice(0, -2);
|
|
249
|
-
// Convert to array if not already
|
|
250
|
-
let arrayValue = incomingValue;
|
|
251
|
-
if (!Array.isArray(incomingValue)) {
|
|
252
|
-
if (typeof incomingValue === 'string') {
|
|
253
|
-
try {
|
|
254
|
-
// Try to parse as JSON array
|
|
255
|
-
const parsed = JSON.parse(incomingValue);
|
|
256
|
-
if (Array.isArray(parsed)) {
|
|
257
|
-
debugLog([
|
|
258
|
-
`Type conversion: ${fieldKey} parsed JSON string to array`,
|
|
259
|
-
{
|
|
260
|
-
original: incomingValue,
|
|
261
|
-
converted: parsed
|
|
262
|
-
}
|
|
263
|
-
]);
|
|
264
|
-
arrayValue = parsed;
|
|
265
|
-
} else {
|
|
266
|
-
arrayValue = [
|
|
267
|
-
incomingValue
|
|
268
|
-
];
|
|
269
|
-
}
|
|
270
|
-
} catch (e) {
|
|
271
|
-
// If parsing fails, wrap in array
|
|
272
|
-
arrayValue = [
|
|
273
|
-
incomingValue
|
|
274
|
-
];
|
|
275
|
-
}
|
|
276
|
-
} else {
|
|
277
|
-
// Wrap non-array values in array
|
|
278
|
-
arrayValue = [
|
|
279
|
-
incomingValue
|
|
280
|
-
];
|
|
281
|
-
}
|
|
282
|
-
debugLog([
|
|
283
|
-
`Type conversion: ${fieldKey} converted to array`,
|
|
284
|
-
{
|
|
285
|
-
original: incomingValue,
|
|
286
|
-
converted: arrayValue
|
|
287
|
-
}
|
|
288
|
-
]);
|
|
289
|
-
}
|
|
290
|
-
// Normalize each array element based on the base type
|
|
291
|
-
return arrayValue.map((item, index)=>{
|
|
292
|
-
if (baseType === 'string' && typeof item !== 'string') {
|
|
293
|
-
const converted = String(item);
|
|
294
|
-
debugLog([
|
|
295
|
-
`Type conversion: ${fieldKey}[${index}] expected string but got ${typeof item}`,
|
|
296
|
-
{
|
|
297
|
-
original: item,
|
|
298
|
-
converted
|
|
299
|
-
}
|
|
300
|
-
]);
|
|
301
|
-
return converted;
|
|
302
|
-
}
|
|
303
|
-
if (baseType === 'number' && typeof item !== 'number') {
|
|
304
|
-
if (typeof item === 'string') {
|
|
305
|
-
const parsed = parseFloat(item);
|
|
306
|
-
if (!isNaN(parsed)) {
|
|
307
|
-
debugLog([
|
|
308
|
-
`Type conversion: ${fieldKey}[${index}] expected number but got string`,
|
|
309
|
-
{
|
|
310
|
-
original: item,
|
|
311
|
-
converted: parsed
|
|
312
|
-
}
|
|
313
|
-
]);
|
|
314
|
-
return parsed;
|
|
315
|
-
}
|
|
316
|
-
} else if (typeof item === 'boolean') {
|
|
317
|
-
return item ? 1 : 0;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
return item;
|
|
321
|
-
});
|
|
322
|
-
}
|
|
323
|
-
// For any other types or if no conversion needed, return as is
|
|
324
|
-
return incomingValue;
|
|
280
|
+
// Return original value if no conversion was needed or applicable
|
|
281
|
+
return value;
|
|
325
282
|
}
|
|
326
|
-
|
|
283
|
+
/**
|
|
284
|
+
* Transforms input data from better-auth to Payload CMS format
|
|
285
|
+
*
|
|
286
|
+
* This function handles:
|
|
287
|
+
* 1. Field name mapping according to schema definitions
|
|
288
|
+
* 2. ID type conversion for relationship fields
|
|
289
|
+
* 3. Proper data normalization based on field types
|
|
290
|
+
*
|
|
291
|
+
* @param data - The input data from better-auth
|
|
292
|
+
* @param model - The model name in the schema
|
|
293
|
+
* @param idType - The expected ID type ('number' or 'text')
|
|
294
|
+
* @returns Transformed data compatible with Payload CMS
|
|
295
|
+
*/ function transformInput({ data, model, idType }) {
|
|
327
296
|
const transformedData = {};
|
|
328
|
-
const schemaFields = schema[model]
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
297
|
+
const schemaFields = schema?.[model]?.fields ?? {};
|
|
298
|
+
// Process each field in the input data
|
|
299
|
+
Object.entries(data).forEach(([key, value])=>{
|
|
300
|
+
// Skip null/undefined values
|
|
301
|
+
if (value === null || value === undefined) {
|
|
302
|
+
return;
|
|
332
303
|
}
|
|
333
|
-
|
|
334
|
-
const
|
|
304
|
+
// Determine if this is a relationship field
|
|
305
|
+
const isRelatedField = isRelationshipField(key, schemaFields);
|
|
306
|
+
// Get the mapped field name from schema (if any)
|
|
307
|
+
const schemaFieldName = schemaFields[key]?.fieldName;
|
|
308
|
+
// Normalize the data value based on field type and ID type
|
|
335
309
|
const normalizedData = normalizeData({
|
|
336
310
|
idType,
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
relationshipField
|
|
311
|
+
key,
|
|
312
|
+
value,
|
|
313
|
+
isRelatedField
|
|
341
314
|
});
|
|
342
|
-
if
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
}
|
|
347
|
-
}
|
|
315
|
+
// Use the schema-defined field name if available, otherwise use original key
|
|
316
|
+
const targetFieldName = schemaFieldName || key;
|
|
317
|
+
transformedData[targetFieldName] = normalizedData;
|
|
318
|
+
});
|
|
348
319
|
return transformedData;
|
|
349
320
|
}
|
|
350
|
-
|
|
351
|
-
|
|
321
|
+
/**
|
|
322
|
+
* Transforms Payload CMS document output to match BetterAuth schema expectations.
|
|
323
|
+
*
|
|
324
|
+
* This function handles several critical transformations:
|
|
325
|
+
*
|
|
326
|
+
* 1. ID Conversion: Ensures all ID fields are strings as required by BetterAuth
|
|
327
|
+
* (see: https://github.com/better-auth/better-auth/blob/main/packages/better-auth/src/db/schema.ts#L125)
|
|
328
|
+
*
|
|
329
|
+
* 2. Relationship Field Mapping: Aligns relationship fields with BetterAuth schema naming conventions
|
|
330
|
+
* and ensures proper ID type handling
|
|
331
|
+
*
|
|
332
|
+
* 3. Date Conversion: Transforms date strings from Payload into Date objects for BetterAuth
|
|
333
|
+
*
|
|
334
|
+
* Note: While setting depth: 1 in Payload operations simplifies this process by avoiding
|
|
335
|
+
* deeply nested objects, we maintain comprehensive checks for robustness.
|
|
336
|
+
*
|
|
337
|
+
* @param doc - The document returned from Payload CMS
|
|
338
|
+
* @param model - The model name in the BetterAuth schema
|
|
339
|
+
* @returns The transformed document compatible with BetterAuth
|
|
340
|
+
*/ function transformOutput({ doc, model }) {
|
|
341
|
+
if (!doc || typeof doc !== 'object') return doc;
|
|
352
342
|
const result = {
|
|
353
343
|
...doc
|
|
354
344
|
};
|
|
355
|
-
const schemaFields = schema[model]
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
[key]: value
|
|
359
|
-
}), {});
|
|
345
|
+
const schemaFields = schema?.[model]?.fields ?? {};
|
|
346
|
+
// Identify relationship fields with custom field name mappings
|
|
347
|
+
const relationshipFields = Object.fromEntries(Object.entries(schemaFields).filter(([key])=>isRelationshipField(key, schemaFields)));
|
|
360
348
|
Object.entries(doc).forEach(([key, value])=>{
|
|
361
349
|
if (value === null || value === undefined) return;
|
|
362
|
-
|
|
363
|
-
if (
|
|
364
|
-
|
|
350
|
+
// Convert ID fields to strings for BetterAuth compatibility
|
|
351
|
+
if ([
|
|
352
|
+
'id',
|
|
353
|
+
'_id'
|
|
354
|
+
].includes(key)) {
|
|
355
|
+
result[key] = String(value);
|
|
356
|
+
return;
|
|
365
357
|
}
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
358
|
+
// Handle relationship fields with renamed fieldNames
|
|
359
|
+
const originalRelatedFieldKey = Object.keys(relationshipFields).find((k)=>relationshipFields[k].fieldName === key);
|
|
360
|
+
if (originalRelatedFieldKey) {
|
|
361
|
+
normalizeDocumentIds(result, originalRelatedFieldKey, key, value);
|
|
362
|
+
return;
|
|
363
|
+
}
|
|
364
|
+
// Convert ISO date strings to Date objects for BetterAuth
|
|
365
|
+
if (isDateField(value)) {
|
|
370
366
|
result[key] = new Date(value);
|
|
367
|
+
return;
|
|
371
368
|
}
|
|
372
369
|
});
|
|
373
370
|
return result;
|
|
374
371
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
372
|
+
/**
|
|
373
|
+
* Normalizes ID fields for both primary and relationship documents.
|
|
374
|
+
*
|
|
375
|
+
* This function ensures consistent ID handling between BetterAuth and Payload CMS by:
|
|
376
|
+
* 1. Converting all IDs to strings for BetterAuth (stored in originalKey)
|
|
377
|
+
* 2. Preserving original ID types for Payload CMS (stored in fieldName)
|
|
378
|
+
*
|
|
379
|
+
* The function handles various ID formats:
|
|
380
|
+
* - Primitive values (string/number IDs)
|
|
381
|
+
* - Object references with ID properties
|
|
382
|
+
* - Arrays of either primitive IDs or object references
|
|
383
|
+
*
|
|
384
|
+
* @param result - The result object being transformed
|
|
385
|
+
* @param originalKey - The original field key from BetterAuth schema
|
|
386
|
+
* @param fieldName - The renamed field as used in Payload CMS
|
|
387
|
+
* @param value - The ID value to normalize (primitive, object, or array)
|
|
388
|
+
*/ function normalizeDocumentIds(result, originalKey, fieldName, value) {
|
|
389
|
+
// Case 1: Primitive ID value (string or number)
|
|
380
390
|
if (typeof value === 'string' || typeof value === 'number') {
|
|
381
|
-
|
|
391
|
+
// For BetterAuth: Always use string IDs
|
|
392
|
+
result[originalKey] = String(value);
|
|
393
|
+
// For Payload: Keep original type
|
|
394
|
+
result[fieldName] = value;
|
|
395
|
+
return;
|
|
396
|
+
}
|
|
397
|
+
// Case 2: Object with ID property
|
|
398
|
+
if (typeof value === 'object' && value !== null && 'id' in value) {
|
|
399
|
+
// For BetterAuth: Extract and stringify the ID
|
|
400
|
+
result[originalKey] = String(value.id);
|
|
401
|
+
// For Payload: Extract ID but preserve type
|
|
402
|
+
result[fieldName] = value.id;
|
|
382
403
|
return;
|
|
383
404
|
}
|
|
384
|
-
// Array of
|
|
405
|
+
// Case 3: Array of IDs or references
|
|
385
406
|
if (Array.isArray(value) && value.length > 0) {
|
|
386
|
-
|
|
387
|
-
|
|
407
|
+
// Check if array contains objects with ID properties
|
|
408
|
+
if (value.every((item)=>typeof item === 'object' && item !== null && 'id' in item)) {
|
|
409
|
+
// Array of objects with IDs
|
|
410
|
+
result[originalKey] = value.map((item)=>String(item.id));
|
|
388
411
|
result[fieldName] = value.map((item)=>item.id);
|
|
412
|
+
} else {
|
|
413
|
+
// Array of primitive IDs
|
|
414
|
+
result[originalKey] = value.map((item)=>String(item));
|
|
415
|
+
result[fieldName] = value.map((item)=>item);
|
|
389
416
|
}
|
|
390
417
|
return;
|
|
391
418
|
}
|
|
392
|
-
|
|
393
|
-
if (typeof value === 'object' && 'id' in value) {
|
|
394
|
-
result[originalKey] = value.id;
|
|
395
|
-
result[fieldName] = value.id;
|
|
396
|
-
}
|
|
419
|
+
// Note: If value doesn't match any expected format, no changes are made
|
|
397
420
|
}
|
|
398
|
-
|
|
421
|
+
/**
|
|
422
|
+
* Converts a BetterAuth operator to the equivalent Payload CMS query operator
|
|
423
|
+
*
|
|
424
|
+
* This function maps standard query operators from BetterAuth's format to
|
|
425
|
+
* the specific format expected by Payload CMS's query engine.
|
|
426
|
+
*
|
|
427
|
+
* @param operator - The BetterAuth operator string (e.g., 'eq', 'gt', 'contains')
|
|
428
|
+
* @param value - The value to be used with the operator
|
|
429
|
+
* @returns An object with the Payload-compatible operator and value
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
* // Returns { equals: 'test@example.com' }
|
|
433
|
+
* operatorToPayload('eq', 'test@example.com')
|
|
434
|
+
*
|
|
435
|
+
* @example
|
|
436
|
+
* // Returns { greater_than: 100 }
|
|
437
|
+
* operatorToPayload('gt', 100)
|
|
438
|
+
*/ function operatorToPayload(operator, value) {
|
|
399
439
|
switch(operator){
|
|
400
440
|
case 'eq':
|
|
401
441
|
return {
|
|
@@ -438,24 +478,45 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
438
478
|
like: `%${value}`
|
|
439
479
|
};
|
|
440
480
|
default:
|
|
481
|
+
// Fall back to equals for unrecognized operators
|
|
441
482
|
return {
|
|
442
483
|
equals: value
|
|
443
484
|
};
|
|
444
485
|
}
|
|
445
486
|
}
|
|
446
|
-
|
|
447
|
-
|
|
487
|
+
/**
|
|
488
|
+
* Converts a where clause value to the appropriate type based on field name and ID type configuration
|
|
489
|
+
*
|
|
490
|
+
* This function handles two main scenarios:
|
|
491
|
+
* 1. ID field conversion - ensures IDs match the database's expected type (number or string)
|
|
492
|
+
* 2. Object with embedded ID - extracts and converts the ID property from objects
|
|
493
|
+
*
|
|
494
|
+
* @param value - The value to convert (can be primitive, object with ID, or array)
|
|
495
|
+
* @param fieldName - The name of the field being queried
|
|
496
|
+
* @param idType - The expected ID type in the database
|
|
497
|
+
* @returns The converted value appropriate for the database query
|
|
498
|
+
*/ function convertWhereValue({ value, fieldName, idType }) {
|
|
499
|
+
// Check if field is an ID field (supporting both MongoDB-style _id and standard id)
|
|
500
|
+
if ([
|
|
501
|
+
'id',
|
|
502
|
+
'_id'
|
|
503
|
+
].includes(fieldName)) {
|
|
504
|
+
// Case 1: Value is an object containing an ID property
|
|
448
505
|
if (typeof value === 'object' && value !== null && 'id' in value) {
|
|
449
|
-
// Extract ID from object
|
|
506
|
+
// Extract ID from object
|
|
450
507
|
const id = value.id;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
508
|
+
// Use type conversion based on database configuration
|
|
509
|
+
if (idType === 'number' && typeof id === 'string') {
|
|
510
|
+
const numId = Number(id);
|
|
511
|
+
return !isNaN(numId) ? numId : id;
|
|
512
|
+
}
|
|
513
|
+
if (idType === 'text' && typeof id === 'number') {
|
|
454
514
|
return String(id);
|
|
455
515
|
}
|
|
456
516
|
return id;
|
|
457
517
|
}
|
|
458
|
-
//
|
|
518
|
+
// Case 2: Value is a standalone ID that needs type conversion
|
|
519
|
+
// Convert string ID to number if database expects numeric IDs
|
|
459
520
|
if (idType === 'number' && typeof value === 'string' && !isNaN(Number(value))) {
|
|
460
521
|
return Number(value);
|
|
461
522
|
} else if (idType === 'text' && typeof value === 'number') {
|
|
@@ -463,28 +524,51 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
463
524
|
}
|
|
464
525
|
return value;
|
|
465
526
|
}
|
|
527
|
+
// For non-ID fields, return the value unchanged
|
|
466
528
|
return value;
|
|
467
529
|
}
|
|
468
|
-
|
|
530
|
+
/**
|
|
531
|
+
* Converts Better Auth where clauses to Payload CMS compatible where conditions
|
|
532
|
+
*
|
|
533
|
+
* This function transforms the Better Auth query format into Payload's query format,
|
|
534
|
+
* handling field name mapping, value type conversion, and logical operators (AND/OR).
|
|
535
|
+
*
|
|
536
|
+
* The function handles three main cases:
|
|
537
|
+
* 1. Empty or undefined where clause - returns empty object
|
|
538
|
+
* 2. Single condition - converts to a simple field-value pair
|
|
539
|
+
* 3. Multiple conditions - groups by AND/OR connectors and builds a complex query
|
|
540
|
+
*
|
|
541
|
+
* @param idType - The database ID type ('number' or 'text')
|
|
542
|
+
* @param model - The model/collection name to query
|
|
543
|
+
* @param where - Array of Better Auth where conditions
|
|
544
|
+
* @returns A Payload-compatible where clause object
|
|
545
|
+
*/ function convertWhereClause({ idType, model, where }) {
|
|
546
|
+
// Handle empty where clause
|
|
469
547
|
if (!where) return {};
|
|
548
|
+
// Handle single condition case for optimization
|
|
470
549
|
if (where.length === 1) {
|
|
471
550
|
const w = where[0];
|
|
472
551
|
if (!w) {
|
|
473
552
|
return {};
|
|
474
553
|
}
|
|
554
|
+
// Map field name according to schema and convert value to appropriate type
|
|
475
555
|
const fieldName = getFieldName(model, w.field);
|
|
476
556
|
const value = convertWhereValue({
|
|
477
557
|
value: w.value,
|
|
478
558
|
fieldName,
|
|
479
559
|
idType
|
|
480
560
|
});
|
|
561
|
+
// Create the Payload where condition with proper operator
|
|
481
562
|
const res = {
|
|
482
563
|
[fieldName]: operatorToPayload(w.operator ?? '', value)
|
|
483
564
|
};
|
|
484
565
|
return res;
|
|
485
566
|
}
|
|
567
|
+
// Handle multiple conditions by separating AND/OR clauses
|
|
568
|
+
// Default to AND if no connector is specified
|
|
486
569
|
const and = where.filter((w)=>w.connector === 'AND' || !w.connector);
|
|
487
570
|
const or = where.filter((w)=>w.connector === 'OR');
|
|
571
|
+
// Process AND conditions
|
|
488
572
|
const andClause = and.map((w)=>{
|
|
489
573
|
const fieldName = getFieldName(model, w.field);
|
|
490
574
|
const value = convertWhereValue({
|
|
@@ -496,6 +580,7 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
496
580
|
[fieldName]: operatorToPayload(w.operator ?? '', value)
|
|
497
581
|
};
|
|
498
582
|
});
|
|
583
|
+
// Process OR conditions
|
|
499
584
|
const orClause = or.map((w)=>{
|
|
500
585
|
const fieldName = getFieldName(model, w.field);
|
|
501
586
|
const value = convertWhereValue({
|
|
@@ -507,6 +592,8 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
507
592
|
[fieldName]: operatorToPayload(w.operator ?? '', value)
|
|
508
593
|
};
|
|
509
594
|
});
|
|
595
|
+
// Combine AND and OR clauses into final Payload where object
|
|
596
|
+
// Only include non-empty clause arrays
|
|
510
597
|
return {
|
|
511
598
|
...andClause.length ? {
|
|
512
599
|
AND: andClause
|
|
@@ -516,22 +603,59 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
516
603
|
} : {}
|
|
517
604
|
};
|
|
518
605
|
}
|
|
519
|
-
|
|
606
|
+
/**
|
|
607
|
+
* Converts a better-auth select array to a Payload select object
|
|
608
|
+
*
|
|
609
|
+
* This function transforms the better-auth select array (which contains field names)
|
|
610
|
+
* into the format expected by Payload CMS's query API (an object with field names as keys
|
|
611
|
+
* and boolean true as values).
|
|
612
|
+
*
|
|
613
|
+
* It also handles field name mapping between better-auth schema and Payload collections
|
|
614
|
+
* by using the getFieldName helper to resolve the correct field names.
|
|
615
|
+
*
|
|
616
|
+
* @param model - The model/collection name to get field mappings from
|
|
617
|
+
* @param select - Optional array of field names to select
|
|
618
|
+
* @returns A Payload-compatible select object or undefined if no fields to select
|
|
619
|
+
* @example
|
|
620
|
+
* // Input: ['email', 'name']
|
|
621
|
+
* // Output: { email: true, name: true }
|
|
622
|
+
*/ function convertSelect(model, select) {
|
|
623
|
+
// Return undefined if select is empty or not provided
|
|
520
624
|
if (!select || select.length === 0) return undefined;
|
|
625
|
+
// Transform the array of field names into a Payload select object
|
|
626
|
+
// while also mapping any field names that might be different in Payload
|
|
521
627
|
return select.reduce((acc, field)=>({
|
|
522
628
|
...acc,
|
|
523
629
|
[getFieldName(model, field)]: true
|
|
524
630
|
}), {});
|
|
525
631
|
}
|
|
526
|
-
|
|
632
|
+
/**
|
|
633
|
+
* Converts a better-auth sort object to a Payload sort string
|
|
634
|
+
*
|
|
635
|
+
* This function transforms the better-auth sort object (which contains field name and direction)
|
|
636
|
+
* into the format expected by Payload CMS's query API (a string with optional '-' prefix for descending order).
|
|
637
|
+
*
|
|
638
|
+
* It also handles field name mapping between better-auth schema and Payload collections
|
|
639
|
+
* by using the getFieldName helper to resolve the correct field names.
|
|
640
|
+
*
|
|
641
|
+
* @param model - The model/collection name to get field mappings from
|
|
642
|
+
* @param sortBy - Optional object containing field name and sort direction
|
|
643
|
+
* @returns A Payload-compatible sort string or undefined if no sort specified
|
|
644
|
+
* @example
|
|
645
|
+
* // Input: { field: 'email', direction: 'desc' }
|
|
646
|
+
* // Output: '-email'
|
|
647
|
+
* // Input: { field: 'createdAt', direction: 'asc' }
|
|
648
|
+
* // Output: 'createdAt'
|
|
649
|
+
*/ function convertSort(model, sortBy) {
|
|
527
650
|
if (!sortBy) return undefined;
|
|
528
|
-
|
|
651
|
+
const fieldName = getFieldName(model, sortBy.field);
|
|
652
|
+
const prefix = sortBy.direction === 'desc' ? '-' : '';
|
|
653
|
+
return `${prefix}${fieldName}`;
|
|
529
654
|
}
|
|
530
655
|
return {
|
|
531
656
|
getFieldName,
|
|
532
|
-
|
|
657
|
+
getCollectionSlug,
|
|
533
658
|
singleIdQuery,
|
|
534
|
-
multipleIdsQuery,
|
|
535
659
|
transformInput,
|
|
536
660
|
transformOutput,
|
|
537
661
|
convertWhereClause,
|
|
@@ -540,4 +664,4 @@ export const createTransform = (options, enableDebugLogs)=>{
|
|
|
540
664
|
};
|
|
541
665
|
};
|
|
542
666
|
|
|
543
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9iZXR0ZXItYXV0aC9hZGFwdGVyL3RyYW5zZm9ybS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBCZXR0ZXJBdXRoRXJyb3IgfSBmcm9tICdiZXR0ZXItYXV0aCdcbmltcG9ydCB7IEZpZWxkQXR0cmlidXRlLCBGaWVsZFR5cGUsIGdldEF1dGhUYWJsZXMgfSBmcm9tICdiZXR0ZXItYXV0aC9kYidcbmltcG9ydCB0eXBlIHsgQmV0dGVyQXV0aE9wdGlvbnMsIFdoZXJlIH0gZnJvbSAnYmV0dGVyLWF1dGgnXG5pbXBvcnQgdHlwZSB7IENvbGxlY3Rpb25TbHVnLCBXaGVyZSBhcyBQYXlsb2FkV2hlcmUgfSBmcm9tICdwYXlsb2FkJ1xuXG5leHBvcnQgY29uc3QgY3JlYXRlVHJhbnNmb3JtID0gKG9wdGlvbnM6IEJldHRlckF1dGhPcHRpb25zLCBlbmFibGVEZWJ1Z0xvZ3M6IGJvb2xlYW4pID0+IHtcbiAgY29uc3Qgc2NoZW1hID0gZ2V0QXV0aFRhYmxlcyhvcHRpb25zKVxuXG4gIGZ1bmN0aW9uIGRlYnVnTG9nKG1lc3NhZ2U6IGFueVtdKSB7XG4gICAgaWYgKGVuYWJsZURlYnVnTG9ncykge1xuICAgICAgY29uc29sZS5sb2coYFtwYXlsb2FkLWRiLWFkYXB0ZXJdYCwgLi4ubWVzc2FnZSlcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBnZXRNb2RlbE5hbWUobW9kZWw6IHN0cmluZyk6IENvbGxlY3Rpb25TbHVnIHtcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gKHNjaGVtYSBhcyBSZWNvcmQ8c3RyaW5nLCBhbnk+KVttb2RlbF0/Lm1vZGVsTmFtZSB8fCBtb2RlbFxuICAgIGlmICghY29sbGVjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEJldHRlckF1dGhFcnJvcihgTW9kZWwgJHttb2RlbH0gZG9lcyBub3QgZXhpc3QgaW4gdGhlIGRhdGFiYXNlLmApXG4gICAgfVxuICAgIHJldHVybiBjb2xsZWN0aW9uIGFzIENvbGxlY3Rpb25TbHVnXG4gIH1cblxuICBmdW5jdGlvbiBnZXRGaWVsZE5hbWUobW9kZWw6IHN0cmluZywgZmllbGQ6IHN0cmluZykge1xuICAgIGlmIChmaWVsZCA9PT0gJ2lkJykge1xuICAgICAgcmV0dXJuIGZpZWxkXG4gICAgfVxuICAgIGNvbnN0IGYgPSBzY2hlbWFbbW9kZWxdPy5maWVsZHNbZmllbGRdXG4gICAgY29uc3QgZmllbGROYW1lID0gZj8uZmllbGROYW1lIHx8IGZpZWxkXG4gICAgZGVidWdMb2coWydnZXRGaWVsZDogJywgeyBtb2RlbCwgb3JpZ2luYWxGaWVsZDogZmllbGQsIGZpZWxkTmFtZSB9XSlcbiAgICByZXR1cm4gZmllbGROYW1lXG4gIH1cblxuICBmdW5jdGlvbiBpc1JlbGF0aW9uc2hpcEZpZWxkKGZpZWxkS2V5OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gZmllbGRLZXkuZW5kc1dpdGgoJ0lkJykgfHwgZmllbGRLZXkuZW5kc1dpdGgoJ0J5JylcbiAgfVxuXG4gIGZ1bmN0aW9uIGlzRGF0ZUZpZWxkKHsga2V5LCB2YWx1ZSB9OiB7IGtleT86IHN0cmluZzsgdmFsdWU6IGFueSB9KSB7XG4gICAgaWYgKGtleSkge1xuICAgICAgcmV0dXJuIChrZXkuZW5kc1dpdGgoJ0F0JykgfHwga2V5LmVuZHNXaXRoKCdEYXRlJykgfHwga2V5ID09PSAnZGF0ZScpICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgIWlzTmFOKERhdGUucGFyc2UodmFsdWUpKVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oRGF0ZS5wYXJzZSh2YWx1ZSkpXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gc2luZ2xlSWRRdWVyeSh3aGVyZTogUGF5bG9hZFdoZXJlKSB7XG4gICAgaWYgKCF3aGVyZSB8fCAnYW5kJyBpbiB3aGVyZSB8fCAnb3InIGluIHdoZXJlKSByZXR1cm4gbnVsbFxuXG4gICAgLy8gRm9yIGEgc2luZ2xlIGlkIHF1ZXJ5IGxpa2UgeyBpZDogeyBlcXVhbHM6IDE1IH0gfVxuICAgIC8vIEZpcnN0LCBjaGVjayBpZiB0aGVyZSdzIGFuIGlkIGZpZWxkIGluIHRoZSB3aGVyZSBjbGF1c2VcbiAgICBpZiAoJ2lkJyBpbiB3aGVyZSB8fCAnX2lkJyBpbiB3aGVyZSkge1xuICAgICAgY29uc3QgaWRGaWVsZCA9ICdpZCcgaW4gd2hlcmUgPyAnaWQnIDogJ19pZCdcbiAgICAgIGNvbnN0IGNvbmRpdGlvbiA9IHdoZXJlW2lkRmllbGRdXG5cbiAgICAgIC8vIENoZWNrIGlmIGNvbmRpdGlvbiBpcyBhbiBvYmplY3Qgd2l0aCBlcXVhbHMgb3BlcmF0b3JcbiAgICAgIGlmIChjb25kaXRpb24gJiYgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiYgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJiAnZXF1YWxzJyBpbiBjb25kaXRpb24pIHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBjb25kaXRpb24uZXF1YWxzXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBDaGVjayBmb3IgY29udGFpbnMgb3BlcmF0b3Igd2l0aCBzaW5nbGUgdmFsdWVcbiAgICAgIGlmIChcbiAgICAgICAgY29uZGl0aW9uICYmXG4gICAgICAgIHR5cGVvZiBjb25kaXRpb24gPT09ICdvYmplY3QnICYmXG4gICAgICAgICFBcnJheS5pc0FycmF5KGNvbmRpdGlvbikgJiZcbiAgICAgICAgJ2NvbnRhaW5zJyBpbiBjb25kaXRpb24gJiZcbiAgICAgICAgQXJyYXkuaXNBcnJheShjb25kaXRpb24uY29udGFpbnMpICYmXG4gICAgICAgIGNvbmRpdGlvbi5jb250YWlucy5sZW5ndGggPT09IDFcbiAgICAgICkge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbmRpdGlvbi5jb250YWluc1swXVxuICAgICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgcmV0dXJuIHZhbHVlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgZnVuY3Rpb24gbXVsdGlwbGVJZHNRdWVyeSh3aGVyZTogUGF5bG9hZFdoZXJlKSB7XG4gICAgaWYgKCF3aGVyZSB8fCAnYW5kJyBpbiB3aGVyZSB8fCAnb3InIGluIHdoZXJlKSByZXR1cm4gbnVsbFxuICAgIGlmICgnaWQnIGluIHdoZXJlIHx8ICdfaWQnIGluIHdoZXJlKSB7XG4gICAgICBjb25zdCBpZEZpZWxkID0gJ2lkJyBpbiB3aGVyZSA/ICdpZCcgOiAnX2lkJ1xuICAgICAgY29uc3QgY29uZGl0aW9uID0gd2hlcmVbaWRGaWVsZF1cblxuICAgICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiAnaW4nIG9wZXJhdG9yIHdpdGggaWQgZmllbGQgYW5kIGFycmF5IG9mIHZhbHVlc1xuICAgICAgaWYgKFxuICAgICAgICBjb25kaXRpb24gJiZcbiAgICAgICAgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJlxuICAgICAgICAnaW4nIGluIGNvbmRpdGlvbiAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbmRpdGlvbi5pbikgJiZcbiAgICAgICAgY29uZGl0aW9uLmluLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgY29uZGl0aW9uLmluLmV2ZXJ5KChpZDogdW5rbm93bikgPT4gdHlwZW9mIGlkID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgaWQgPT09ICdudW1iZXInKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBjb25kaXRpb24uaW4gYXMgKG51bWJlciB8IHN0cmluZylbXVxuICAgICAgfVxuXG4gICAgICAvLyBBbHNvIGNoZWNrIGZvciBjb250YWlucyBvcGVyYXRvciB3aXRoIGFycmF5IG9mIElEc1xuICAgICAgaWYgKFxuICAgICAgICBjb25kaXRpb24gJiZcbiAgICAgICAgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJlxuICAgICAgICAnY29udGFpbnMnIGluIGNvbmRpdGlvbiAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbmRpdGlvbi5jb250YWlucykgJiZcbiAgICAgICAgY29uZGl0aW9uLmNvbnRhaW5zLmxlbmd0aCA+IDEgJiZcbiAgICAgICAgY29uZGl0aW9uLmNvbnRhaW5zLmV2ZXJ5KChpZDogdW5rbm93bikgPT4gdHlwZW9mIGlkID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgaWQgPT09ICdudW1iZXInKVxuICAgICAgKSB7XG4gICAgICAgIHJldHVybiBjb25kaXRpb24uY29udGFpbnMgYXMgKG51bWJlciB8IHN0cmluZylbXVxuICAgICAgfVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgZnVuY3Rpb24gbm9ybWFsaXplRGF0YSh7XG4gICAgZmllbGRLZXksXG4gICAgaW5jb21pbmdWYWx1ZSxcbiAgICBzY2hlbWFGaWVsZHMsXG4gICAgcmVsYXRpb25zaGlwRmllbGQsXG4gICAgaWRUeXBlXG4gIH06IHtcbiAgICBmaWVsZEtleTogc3RyaW5nXG4gICAgaW5jb21pbmdWYWx1ZTogYW55XG4gICAgc2NoZW1hRmllbGRzOiBSZWNvcmQ8c3RyaW5nLCBGaWVsZEF0dHJpYnV0ZTxGaWVsZFR5cGU+PlxuICAgIHJlbGF0aW9uc2hpcEZpZWxkOiBib29sZWFuXG4gICAgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0J1xuICB9KSB7XG4gICAgLy8gRWFybHkgcmV0dXJuIGZvciBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAgICBpZiAoaW5jb21pbmdWYWx1ZSA9PT0gbnVsbCB8fCBpbmNvbWluZ1ZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgIHJldHVybiBpbmNvbWluZ1ZhbHVlXG4gICAgfVxuXG4gICAgLy9zcGVjaWFsIGNhc2UgZm9yIGFjY291bnRJZCBmaWVsZCBpbiBhY2NvdW50cyBjb2xsZWN0aW9uXG4gICAgaWYgKGZpZWxkS2V5ID09PSAnYWNjb3VudElkJykge1xuICAgICAgcmV0dXJuIFN0cmluZyhpbmNvbWluZ1ZhbHVlKVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSByZWxhdGlvbnNoaXAgZmllbGRzIChJRHMpIGJhc2VkIG9uIGlkVHlwZVxuICAgIGlmIChyZWxhdGlvbnNoaXBGaWVsZCkge1xuICAgICAgaWYgKGlkVHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGluY29taW5nVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KGluY29taW5nVmFsdWUsIDEwKVxuICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICBkZWJ1Z0xvZyhbYElEIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGNvbnZlcnRpbmcgc3RyaW5nIElEIHRvIG51bWJlcmAsIHsgb3JpZ2luYWw6IGluY29taW5nVmFsdWUsIGNvbnZlcnRlZDogcGFyc2VkIH1dKVxuICAgICAgICAgIHJldHVybiBwYXJzZWRcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmIChpZFR5cGUgPT09ICd0ZXh0JyAmJiB0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgY29uc3Qgc3RyaW5nSWQgPSBTdHJpbmcoaW5jb21pbmdWYWx1ZSlcbiAgICAgICAgZGVidWdMb2coW2BJRCBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBjb252ZXJ0aW5nIG51bWJlciBJRCB0byBzdHJpbmdgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQ6IHN0cmluZ0lkIH1dKVxuICAgICAgICByZXR1cm4gc3RyaW5nSWRcbiAgICAgIH1cblxuICAgICAgLy8gSGFuZGxlIGFycmF5IG9mIElEc1xuICAgICAgaWYgKEFycmF5LmlzQXJyYXkoaW5jb21pbmdWYWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIGluY29taW5nVmFsdWUubWFwKChpZCkgPT4ge1xuICAgICAgICAgIGlmIChpZFR5cGUgPT09ICdudW1iZXInICYmIHR5cGVvZiBpZCA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KGlkLCAxMClcbiAgICAgICAgICAgIHJldHVybiAhaXNOYU4ocGFyc2VkKSA/IHBhcnNlZCA6IGlkXG4gICAgICAgICAgfSBlbHNlIGlmIChpZFR5cGUgPT09ICd0ZXh0JyAmJiB0eXBlb2YgaWQgPT09ICdudW1iZXInKSB7XG4gICAgICAgICAgICByZXR1cm4gU3RyaW5nKGlkKVxuICAgICAgICAgIH1cbiAgICAgICAgICByZXR1cm4gaWRcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGluY29taW5nVmFsdWVcbiAgICB9XG5cbiAgICBjb25zdCBzY2hlbWFGaWVsZCA9IHNjaGVtYUZpZWxkc1tmaWVsZEtleV1cblxuICAgIC8vIElmIG5vIHNjaGVtYSBmaWVsZCBleGlzdHMsIHJldHVybiBhcyBpc1xuICAgIGlmICghc2NoZW1hRmllbGQpIHtcbiAgICAgIHJldHVybiBpbmNvbWluZ1ZhbHVlXG4gICAgfVxuXG4gICAgY29uc3QgZmllbGRUeXBlID0gc2NoZW1hRmllbGQudHlwZVxuXG4gICAgLy8gSGFuZGxlIHN0cmluZyB0eXBlXG4gICAgaWYgKGZpZWxkVHlwZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSAhPT0gJ3N0cmluZycpIHtcbiAgICAgICAgaWYgKGluY29taW5nVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSB7XG4gICAgICAgICAgY29uc3QgY29udmVydGVkID0gaW5jb21pbmdWYWx1ZS50b0lTT1N0cmluZygpXG4gICAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGV4cGVjdGVkIHN0cmluZyBidXQgZ290IERhdGVgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgICB9XG5cbiAgICAgICAgY29uc3QgY29udmVydGVkID0gU3RyaW5nKGluY29taW5nVmFsdWUpXG4gICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBzdHJpbmcgYnV0IGdvdCAke3R5cGVvZiBpbmNvbWluZ1ZhbHVlfWAsIHsgb3JpZ2luYWw6IGluY29taW5nVmFsdWUsIGNvbnZlcnRlZCB9XSlcbiAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgfVxuICAgICAgcmV0dXJuIGluY29taW5nVmFsdWVcbiAgICB9XG5cbiAgICAvLyBIYW5kbGUgbnVtYmVyIHR5cGVcbiAgICBpZiAoZmllbGRUeXBlID09PSAnbnVtYmVyJykge1xuICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlICE9PSAnbnVtYmVyJykge1xuICAgICAgICBpZiAoaW5jb21pbmdWYWx1ZSBpbnN0YW5jZW9mIERhdGUpIHtcbiAgICAgICAgICBjb25zdCBjb252ZXJ0ZWQgPSBpbmNvbWluZ1ZhbHVlLmdldFRpbWUoKVxuICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBudW1iZXIgYnV0IGdvdCBEYXRlYCwgeyBvcmlnaW5hbDogaW5jb21pbmdWYWx1ZSwgY29udmVydGVkIH1dKVxuICAgICAgICAgIHJldHVybiBjb252ZXJ0ZWRcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgICAgY29uc3QgY29udmVydGVkID0gaW5jb21pbmdWYWx1ZSA/IDEgOiAwXG4gICAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGV4cGVjdGVkIG51bWJlciBidXQgZ290IGJvb2xlYW5gLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlID09PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlRmxvYXQoaW5jb21pbmdWYWx1ZSlcbiAgICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBudW1iZXIgYnV0IGdvdCBzdHJpbmdgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICAgIHJldHVybiBwYXJzZWRcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBpbmNvbWluZ1ZhbHVlXG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIGJvb2xlYW4gdHlwZVxuICAgIGlmIChmaWVsZFR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlICE9PSAnYm9vbGVhbicpIHtcbiAgICAgICAgbGV0IGNvbnZlcnRlZFxuXG4gICAgICAgIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ3N0cmluZycpIHtcbiAgICAgICAgICBjb252ZXJ0ZWQgPSBpbmNvbWluZ1ZhbHVlLnRvTG93ZXJDYXNlKCkgPT09ICd0cnVlJyB8fCBpbmNvbWluZ1ZhbHVlID09PSAnMSdcbiAgICAgICAgfSBlbHNlIGlmICh0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBjb252ZXJ0ZWQgPSBpbmNvbWluZ1ZhbHVlICE9PSAwXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29udmVydGVkID0gISFpbmNvbWluZ1ZhbHVlXG4gICAgICAgIH1cblxuICAgICAgICBkZWJ1Z0xvZyhbYFR5cGUgY29udmVyc2lvbjogJHtmaWVsZEtleX0gZXhwZWN0ZWQgYm9vbGVhbiBidXQgZ290ICR7dHlwZW9mIGluY29taW5nVmFsdWV9YCwgeyBvcmlnaW5hbDogaW5jb21pbmdWYWx1ZSwgY29udmVydGVkIH1dKVxuICAgICAgICByZXR1cm4gY29udmVydGVkXG4gICAgICB9XG4gICAgICByZXR1cm4gaW5jb21pbmdWYWx1ZVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSBkYXRlIHR5cGVcbiAgICBpZiAoZmllbGRUeXBlID09PSAnZGF0ZScpIHtcbiAgICAgIGlmICghKGluY29taW5nVmFsdWUgaW5zdGFuY2VvZiBEYXRlKSkge1xuICAgICAgICBsZXQgY29udmVydGVkXG5cbiAgICAgICAgaWYgKHR5cGVvZiBpbmNvbWluZ1ZhbHVlID09PSAnc3RyaW5nJyB8fCB0eXBlb2YgaW5jb21pbmdWYWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICBjb252ZXJ0ZWQgPSBuZXcgRGF0ZShpbmNvbWluZ1ZhbHVlKVxuICAgICAgICAgIGlmICghaXNOYU4oY29udmVydGVkLmdldFRpbWUoKSkpIHtcbiAgICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBleHBlY3RlZCBEYXRlIGJ1dCBnb3QgJHt0eXBlb2YgaW5jb21pbmdWYWx1ZX1gLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgICByZXR1cm4gY29udmVydGVkXG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gaW5jb21pbmdWYWx1ZVxuICAgIH1cblxuICAgIC8vIEhhbmRsZSBhcnJheSB0eXBlcyAoc3RyaW5nW10gb3IgbnVtYmVyW10gb3IgTGl0ZXJhbFN0cmluZ1tdKVxuICAgIGlmICh0eXBlb2YgZmllbGRUeXBlID09PSAnc3RyaW5nJyAmJiBmaWVsZFR5cGUuZW5kc1dpdGgoJ1tdJykpIHtcbiAgICAgIGNvbnN0IGJhc2VUeXBlID0gZmllbGRUeXBlLnNsaWNlKDAsIC0yKVxuXG4gICAgICAvLyBDb252ZXJ0IHRvIGFycmF5IGlmIG5vdCBhbHJlYWR5XG4gICAgICBsZXQgYXJyYXlWYWx1ZSA9IGluY29taW5nVmFsdWVcbiAgICAgIGlmICghQXJyYXkuaXNBcnJheShpbmNvbWluZ1ZhbHVlKSkge1xuICAgICAgICBpZiAodHlwZW9mIGluY29taW5nVmFsdWUgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIC8vIFRyeSB0byBwYXJzZSBhcyBKU09OIGFycmF5XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBKU09OLnBhcnNlKGluY29taW5nVmFsdWUpXG4gICAgICAgICAgICBpZiAoQXJyYXkuaXNBcnJheShwYXJzZWQpKSB7XG4gICAgICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fSBwYXJzZWQgSlNPTiBzdHJpbmcgdG8gYXJyYXlgLCB7IG9yaWdpbmFsOiBpbmNvbWluZ1ZhbHVlLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICAgICAgYXJyYXlWYWx1ZSA9IHBhcnNlZFxuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgYXJyYXlWYWx1ZSA9IFtpbmNvbWluZ1ZhbHVlXVxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgICAgIC8vIElmIHBhcnNpbmcgZmFpbHMsIHdyYXAgaW4gYXJyYXlcbiAgICAgICAgICAgIGFycmF5VmFsdWUgPSBbaW5jb21pbmdWYWx1ZV1cbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgLy8gV3JhcCBub24tYXJyYXkgdmFsdWVzIGluIGFycmF5XG4gICAgICAgICAgYXJyYXlWYWx1ZSA9IFtpbmNvbWluZ1ZhbHVlXVxuICAgICAgICB9XG5cbiAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9IGNvbnZlcnRlZCB0byBhcnJheWAsIHsgb3JpZ2luYWw6IGluY29taW5nVmFsdWUsIGNvbnZlcnRlZDogYXJyYXlWYWx1ZSB9XSlcbiAgICAgIH1cblxuICAgICAgLy8gTm9ybWFsaXplIGVhY2ggYXJyYXkgZWxlbWVudCBiYXNlZCBvbiB0aGUgYmFzZSB0eXBlXG4gICAgICByZXR1cm4gYXJyYXlWYWx1ZS5tYXAoKGl0ZW06IGFueSwgaW5kZXg6IG51bWJlcikgPT4ge1xuICAgICAgICBpZiAoYmFzZVR5cGUgPT09ICdzdHJpbmcnICYmIHR5cGVvZiBpdGVtICE9PSAnc3RyaW5nJykge1xuICAgICAgICAgIGNvbnN0IGNvbnZlcnRlZCA9IFN0cmluZyhpdGVtKVxuICAgICAgICAgIGRlYnVnTG9nKFtgVHlwZSBjb252ZXJzaW9uOiAke2ZpZWxkS2V5fVske2luZGV4fV0gZXhwZWN0ZWQgc3RyaW5nIGJ1dCBnb3QgJHt0eXBlb2YgaXRlbX1gLCB7IG9yaWdpbmFsOiBpdGVtLCBjb252ZXJ0ZWQgfV0pXG4gICAgICAgICAgcmV0dXJuIGNvbnZlcnRlZFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGJhc2VUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgaXRlbSAhPT0gJ251bWJlcicpIHtcbiAgICAgICAgICBpZiAodHlwZW9mIGl0ZW0gPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUZsb2F0KGl0ZW0pXG4gICAgICAgICAgICBpZiAoIWlzTmFOKHBhcnNlZCkpIHtcbiAgICAgICAgICAgICAgZGVidWdMb2coW2BUeXBlIGNvbnZlcnNpb246ICR7ZmllbGRLZXl9WyR7aW5kZXh9XSBleHBlY3RlZCBudW1iZXIgYnV0IGdvdCBzdHJpbmdgLCB7IG9yaWdpbmFsOiBpdGVtLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICAgICAgcmV0dXJuIHBhcnNlZFxuICAgICAgICAgICAgfVxuICAgICAgICAgIH0gZWxzZSBpZiAodHlwZW9mIGl0ZW0gPT09ICdib29sZWFuJykge1xuICAgICAgICAgICAgcmV0dXJuIGl0ZW0gPyAxIDogMFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gaXRlbVxuICAgICAgfSlcbiAgICB9XG5cbiAgICAvLyBGb3IgYW55IG90aGVyIHR5cGVzIG9yIGlmIG5vIGNvbnZlcnNpb24gbmVlZGVkLCByZXR1cm4gYXMgaXNcbiAgICByZXR1cm4gaW5jb21pbmdWYWx1ZVxuICB9XG5cbiAgZnVuY3Rpb24gdHJhbnNmb3JtSW5wdXQoe1xuICAgIGRhdGEsXG4gICAgbW9kZWwsXG4gICAgaWRUeXBlLFxuICAgIGFjdGlvblxuICB9OiB7XG4gICAgZGF0YTogUmVjb3JkPHN0cmluZywgYW55PlxuICAgIG1vZGVsOiBzdHJpbmdcbiAgICBpZFR5cGU6ICdudW1iZXInIHwgJ3RleHQnXG4gICAgYWN0aW9uOiAnY3JlYXRlJyB8ICd1cGRhdGUnXG4gIH0pIHtcbiAgICBjb25zdCB0cmFuc2Zvcm1lZERhdGE6IFJlY29yZDxzdHJpbmcsIGFueT4gPSB7fVxuICAgIGNvbnN0IHNjaGVtYUZpZWxkcyA9IHNjaGVtYVttb2RlbF0uZmllbGRzXG4gICAgZm9yIChjb25zdCBmaWVsZEtleSBpbiBkYXRhKSB7XG4gICAgICBpZiAoZGF0YVtmaWVsZEtleV0gPT09IHVuZGVmaW5lZCAmJiBhY3Rpb24gPT09ICd1cGRhdGUnKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBjb25zdCByZWxhdGlvbnNoaXBGaWVsZCA9IGlzUmVsYXRpb25zaGlwRmllbGQoZmllbGRLZXkpXG4gICAgICBjb25zdCBzY2hlbWFGaWVsZE5hbWUgPSBzY2hlbWFGaWVsZHNbZmllbGRLZXldPy5maWVsZE5hbWVcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWREYXRhID0gbm9ybWFsaXplRGF0YSh7XG4gICAgICAgIGlkVHlwZSxcbiAgICAgICAgZmllbGRLZXksXG4gICAgICAgIGluY29taW5nVmFsdWU6IGRhdGFbZmllbGRLZXldLFxuICAgICAgICBzY2hlbWFGaWVsZHMsXG4gICAgICAgIHJlbGF0aW9uc2hpcEZpZWxkXG4gICAgICB9KVxuICAgICAgaWYgKHNjaGVtYUZpZWxkTmFtZSkge1xuICAgICAgICB0cmFuc2Zvcm1lZERhdGFbc2NoZW1hRmllbGROYW1lXSA9IG5vcm1hbGl6ZWREYXRhXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0cmFuc2Zvcm1lZERhdGFbZmllbGRLZXldID0gbm9ybWFsaXplZERhdGFcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gdHJhbnNmb3JtZWREYXRhXG4gIH1cblxuICBmdW5jdGlvbiB0cmFuc2Zvcm1PdXRwdXQ8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIGFueT4gfCBudWxsPih7IGRvYywgbW9kZWwgfTogeyBkb2M6IFQ7IG1vZGVsOiBzdHJpbmcgfSk6IFQge1xuICAgIGlmIChkb2MgPT09IG51bGwgfHwgZG9jID09PSB1bmRlZmluZWQgfHwgdHlwZW9mIGRvYyAhPT0gJ29iamVjdCcpIHJldHVybiBkb2NcblxuICAgIGNvbnN0IHJlc3VsdCA9IHsgLi4uZG9jIH0gYXMgYW55XG4gICAgY29uc3Qgc2NoZW1hRmllbGRzID0gc2NoZW1hW21vZGVsXS5maWVsZHNcbiAgICBjb25zdCByZWxhdGlvbnNoaXBGaWVsZHMgPSBPYmplY3QuZW50cmllcyhzY2hlbWFGaWVsZHMpXG4gICAgICAuZmlsdGVyKChba2V5XSkgPT4gaXNSZWxhdGlvbnNoaXBGaWVsZChrZXkpKVxuICAgICAgLnJlZHVjZSgoYWNjLCBba2V5LCB2YWx1ZV0pID0+ICh7IC4uLmFjYywgW2tleV06IHZhbHVlIH0pLCB7fSBhcyBSZWNvcmQ8c3RyaW5nLCBGaWVsZEF0dHJpYnV0ZTxGaWVsZFR5cGU+PilcblxuICAgIE9iamVjdC5lbnRyaWVzKGRvYykuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkgcmV0dXJuXG5cbiAgICAgIGNvbnN0IG9yaWdpbmFsS2V5ID0gZmluZFJlbGF0aW9uc2hpcE9yaWdpbmFsS2V5KGtleSwgcmVsYXRpb25zaGlwRmllbGRzKVxuICAgICAgaWYgKG9yaWdpbmFsS2V5KSB7XG4gICAgICAgIHByb2Nlc3NSZWxhdGlvbnNoaXBGaWVsZChyZXN1bHQsIG9yaWdpbmFsS2V5LCBrZXksIHZhbHVlKVxuICAgICAgfVxuXG4gICAgICBpZiAoaXNEYXRlRmllbGQoeyBrZXksIHZhbHVlIH0pKSB7XG4gICAgICAgIHJlc3VsdFtrZXldID0gbmV3IERhdGUodmFsdWUpXG4gICAgICB9XG4gICAgfSlcblxuICAgIHJldHVybiByZXN1bHQgYXMgVFxuICB9XG5cbiAgZnVuY3Rpb24gZmluZFJlbGF0aW9uc2hpcE9yaWdpbmFsS2V5KFxuICAgIGZpZWxkTmFtZTogc3RyaW5nLFxuICAgIHJlbGF0aW9uc2hpcEZpZWxkczogUmVjb3JkPHN0cmluZywgRmllbGRBdHRyaWJ1dGU8RmllbGRUeXBlPj5cbiAgKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gT2JqZWN0LmtleXMocmVsYXRpb25zaGlwRmllbGRzKS5maW5kKChrZXkpID0+IHJlbGF0aW9uc2hpcEZpZWxkc1trZXldLmZpZWxkTmFtZSA9PT0gZmllbGROYW1lKVxuICB9XG5cbiAgZnVuY3Rpb24gcHJvY2Vzc1JlbGF0aW9uc2hpcEZpZWxkKHJlc3VsdDogUmVjb3JkPHN0cmluZywgYW55Piwgb3JpZ2luYWxLZXk6IHN0cmluZywgZmllbGROYW1lOiBzdHJpbmcsIHZhbHVlOiBhbnkpOiB2b2lkIHtcbiAgICAvLyBTaW1wbGUgSUQgdmFsdWUgKHN0cmluZyBvciBudW1iZXIpXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IHZhbHVlXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBBcnJheSBvZiByZWxhdGlvbnNoaXBzXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIGlmICh2YWx1ZS5ldmVyeSgoaXRlbSkgPT4gdHlwZW9mIGl0ZW0gPT09ICdvYmplY3QnICYmICdpZCcgaW4gaXRlbSkpIHtcbiAgICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IHZhbHVlLm1hcCgoaXRlbSkgPT4gaXRlbS5pZClcbiAgICAgICAgcmVzdWx0W2ZpZWxkTmFtZV0gPSB2YWx1ZS5tYXAoKGl0ZW0pID0+IGl0ZW0uaWQpXG4gICAgICB9XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBTaW5nbGUgcmVsYXRpb25zaGlwIG9iamVjdCB3aXRoIElEXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgJiYgJ2lkJyBpbiB2YWx1ZSkge1xuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IHZhbHVlLmlkXG4gICAgICByZXN1bHRbZmllbGROYW1lXSA9IHZhbHVlLmlkXG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gb3BlcmF0b3JUb1BheWxvYWQob3BlcmF0b3I6IHN0cmluZywgdmFsdWU6IGFueSkge1xuICAgIHN3aXRjaCAob3BlcmF0b3IpIHtcbiAgICAgIGNhc2UgJ2VxJzpcbiAgICAgICAgcmV0dXJuIHsgZXF1YWxzOiB2YWx1ZSB9XG4gICAgICBjYXNlICduZSc6XG4gICAgICAgIHJldHVybiB7IG5vdF9lcXVhbHM6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2d0JzpcbiAgICAgICAgcmV0dXJuIHsgZ3JlYXRlcl90aGFuOiB2YWx1ZSB9XG4gICAgICBjYXNlICdndGUnOlxuICAgICAgICByZXR1cm4geyBncmVhdGVyX3RoYW5fZXF1YWw6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2x0JzpcbiAgICAgICAgcmV0dXJuIHsgbGVzc190aGFuOiB2YWx1ZSB9XG4gICAgICBjYXNlICdsdGUnOlxuICAgICAgICByZXR1cm4geyBsZXNzX3RoYW5fZXF1YWw6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2NvbnRhaW5zJzpcbiAgICAgICAgcmV0dXJuIHsgY29udGFpbnM6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2luJzpcbiAgICAgICAgcmV0dXJuIHsgaW46IHZhbHVlIH1cbiAgICAgIGNhc2UgJ3N0YXJ0c193aXRoJzpcbiAgICAgICAgcmV0dXJuIHsgbGlrZTogYCR7dmFsdWV9JWAgfVxuICAgICAgY2FzZSAnZW5kc193aXRoJzpcbiAgICAgICAgcmV0dXJuIHsgbGlrZTogYCUke3ZhbHVlfWAgfVxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIHsgZXF1YWxzOiB2YWx1ZSB9XG4gICAgfVxuICB9XG5cbiAgZnVuY3Rpb24gY29udmVydFdoZXJlVmFsdWUoeyB2YWx1ZSwgZmllbGROYW1lLCBpZFR5cGUgfTogeyB2YWx1ZTogYW55OyBmaWVsZE5hbWU6IHN0cmluZzsgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0JyB9KSB7XG4gICAgaWYgKGZpZWxkTmFtZSA9PT0gJ2lkJyB8fCBmaWVsZE5hbWUgPT09ICdfaWQnKSB7XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAnaWQnIGluIHZhbHVlKSB7XG4gICAgICAgIC8vIEV4dHJhY3QgSUQgZnJvbSBvYmplY3QgYW5kIGVuc3VyZSBpdCBtYXRjaGVzIHRoZSBleHBlY3RlZCB0eXBlXG4gICAgICAgIGNvbnN0IGlkID0gdmFsdWUuaWRcbiAgICAgICAgaWYgKGlkVHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIGlkID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oTnVtYmVyKGlkKSkpIHtcbiAgICAgICAgICByZXR1cm4gTnVtYmVyKGlkKVxuICAgICAgICB9IGVsc2UgaWYgKGlkVHlwZSA9PT0gJ3RleHQnICYmIHR5cGVvZiBpZCA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICByZXR1cm4gU3RyaW5nKGlkKVxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBpZFxuICAgICAgfVxuICAgICAgLy8gQ29udmVydCBzdGFuZGFsb25lIElEIHZhbHVlIHRvIG1hdGNoIGV4cGVjdGVkIHR5cGVcbiAgICAgIGlmIChpZFR5cGUgPT09ICdudW1iZXInICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgIWlzTmFOKE51bWJlcih2YWx1ZSkpKSB7XG4gICAgICAgIHJldHVybiBOdW1iZXIodmFsdWUpXG4gICAgICB9IGVsc2UgaWYgKGlkVHlwZSA9PT0gJ3RleHQnICYmIHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgcmV0dXJuIFN0cmluZyh2YWx1ZSlcbiAgICAgIH1cbiAgICAgIHJldHVybiB2YWx1ZVxuICAgIH1cbiAgICByZXR1cm4gdmFsdWVcbiAgfVxuXG4gIGZ1bmN0aW9uIGNvbnZlcnRXaGVyZUNsYXVzZSh7IGlkVHlwZSwgbW9kZWwsIHdoZXJlIH06IHsgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0JzsgbW9kZWw6IHN0cmluZzsgd2hlcmU/OiBXaGVyZVtdIH0pOiBQYXlsb2FkV2hlcmUge1xuICAgIGlmICghd2hlcmUpIHJldHVybiB7fVxuICAgIGlmICh3aGVyZS5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IHcgPSB3aGVyZVswXVxuICAgICAgaWYgKCF3KSB7XG4gICAgICAgIHJldHVybiB7fVxuICAgICAgfVxuXG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBnZXRGaWVsZE5hbWUobW9kZWwsIHcuZmllbGQpXG4gICAgICBjb25zdCB2YWx1ZSA9IGNvbnZlcnRXaGVyZVZhbHVlKHtcbiAgICAgICAgdmFsdWU6IHcudmFsdWUsXG4gICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgaWRUeXBlXG4gICAgICB9KVxuXG4gICAgICBjb25zdCByZXMgPSB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiBvcGVyYXRvclRvUGF5bG9hZCh3Lm9wZXJhdG9yID8/ICcnLCB2YWx1ZSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHJlc1xuICAgIH1cbiAgICBjb25zdCBhbmQgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnQU5EJyB8fCAhdy5jb25uZWN0b3IpXG4gICAgY29uc3Qgb3IgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnT1InKVxuICAgIGNvbnN0IGFuZENsYXVzZSA9IGFuZC5tYXAoKHcpID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgdy5maWVsZClcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFdoZXJlVmFsdWUoe1xuICAgICAgICB2YWx1ZTogdy52YWx1ZSxcbiAgICAgICAgZmllbGROYW1lLFxuICAgICAgICBpZFR5cGVcbiAgICAgIH0pXG4gICAgICByZXR1cm4ge1xuICAgICAgICBbZmllbGROYW1lXTogb3BlcmF0b3JUb1BheWxvYWQody5vcGVyYXRvciA/PyAnJywgdmFsdWUpXG4gICAgICB9XG4gICAgfSlcbiAgICBjb25zdCBvckNsYXVzZSA9IG9yLm1hcCgodykgPT4ge1xuICAgICAgY29uc3QgZmllbGROYW1lID0gZ2V0RmllbGROYW1lKG1vZGVsLCB3LmZpZWxkKVxuICAgICAgY29uc3QgdmFsdWUgPSBjb252ZXJ0V2hlcmVWYWx1ZSh7XG4gICAgICAgIHZhbHVlOiB3LnZhbHVlLFxuICAgICAgICBmaWVsZE5hbWUsXG4gICAgICAgIGlkVHlwZVxuICAgICAgfSlcbiAgICAgIHJldHVybiB7XG4gICAgICAgIFtmaWVsZE5hbWVdOiBvcGVyYXRvclRvUGF5bG9hZCh3Lm9wZXJhdG9yID8/ICcnLCB2YWx1ZSlcbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLihhbmRDbGF1c2UubGVuZ3RoID8geyBBTkQ6IGFuZENsYXVzZSB9IDoge30pLFxuICAgICAgLi4uKG9yQ2xhdXNlLmxlbmd0aCA/IHsgT1I6IG9yQ2xhdXNlIH0gOiB7fSlcbiAgICB9XG4gIH1cblxuICBmdW5jdGlvbiBjb252ZXJ0U2VsZWN0KG1vZGVsOiBzdHJpbmcsIHNlbGVjdD86IHN0cmluZ1tdKSB7XG4gICAgaWYgKCFzZWxlY3QgfHwgc2VsZWN0Lmxlbmd0aCA9PT0gMCkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiBzZWxlY3QucmVkdWNlKChhY2MsIGZpZWxkKSA9PiAoeyAuLi5hY2MsIFtnZXRGaWVsZE5hbWUobW9kZWwsIGZpZWxkKV06IHRydWUgfSksIHt9KVxuICB9XG5cbiAgZnVuY3Rpb24gY29udmVydFNvcnQobW9kZWw6IHN0cmluZywgc29ydEJ5PzogeyBmaWVsZDogc3RyaW5nOyBkaXJlY3Rpb246ICdhc2MnIHwgJ2Rlc2MnIH0pIHtcbiAgICBpZiAoIXNvcnRCeSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIHJldHVybiBgJHtzb3J0QnkuZGlyZWN0aW9uID09PSAnZGVzYycgPyAnLScgOiAnJ30ke2dldEZpZWxkTmFtZShtb2RlbCwgc29ydEJ5LmZpZWxkKX1gXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdldEZpZWxkTmFtZSxcbiAgICBnZXRNb2RlbE5hbWUsXG4gICAgc2luZ2xlSWRRdWVyeSxcbiAgICBtdWx0aXBsZUlkc1F1ZXJ5LFxuICAgIHRyYW5zZm9ybUlucHV0LFxuICAgIHRyYW5zZm9ybU91dHB1dCxcbiAgICBjb252ZXJ0V2hlcmVDbGF1c2UsXG4gICAgY29udmVydFNlbGVjdCxcbiAgICBjb252ZXJ0U29ydFxuICB9XG59XG4iXSwibmFtZXMiOlsiQmV0dGVyQXV0aEVycm9yIiwiZ2V0QXV0aFRhYmxlcyIsImNyZWF0ZVRyYW5zZm9ybSIsIm9wdGlvbnMiLCJlbmFibGVEZWJ1Z0xvZ3MiLCJzY2hlbWEiLCJkZWJ1Z0xvZyIsIm1lc3NhZ2UiLCJjb25zb2xlIiwibG9nIiwiZ2V0TW9kZWxOYW1lIiwibW9kZWwiLCJjb2xsZWN0aW9uIiwibW9kZWxOYW1lIiwiZ2V0RmllbGROYW1lIiwiZmllbGQiLCJmIiwiZmllbGRzIiwiZmllbGROYW1lIiwib3JpZ2luYWxGaWVsZCIsImlzUmVsYXRpb25zaGlwRmllbGQiLCJmaWVsZEtleSIsImVuZHNXaXRoIiwiaXNEYXRlRmllbGQiLCJrZXkiLCJ2YWx1ZSIsImlzTmFOIiwiRGF0ZSIsInBhcnNlIiwic2luZ2xlSWRRdWVyeSIsIndoZXJlIiwiaWRGaWVsZCIsImNvbmRpdGlvbiIsIkFycmF5IiwiaXNBcnJheSIsImVxdWFscyIsImNvbnRhaW5zIiwibGVuZ3RoIiwibXVsdGlwbGVJZHNRdWVyeSIsImluIiwiZXZlcnkiLCJpZCIsIm5vcm1hbGl6ZURhdGEiLCJpbmNvbWluZ1ZhbHVlIiwic2NoZW1hRmllbGRzIiwicmVsYXRpb25zaGlwRmllbGQiLCJpZFR5cGUiLCJ1bmRlZmluZWQiLCJTdHJpbmciLCJwYXJzZWQiLCJwYXJzZUludCIsIm9yaWdpbmFsIiwiY29udmVydGVkIiwic3RyaW5nSWQiLCJtYXAiLCJzY2hlbWFGaWVsZCIsImZpZWxkVHlwZSIsInR5cGUiLCJ0b0lTT1N0cmluZyIsImdldFRpbWUiLCJwYXJzZUZsb2F0IiwidG9Mb3dlckNhc2UiLCJiYXNlVHlwZSIsInNsaWNlIiwiYXJyYXlWYWx1ZSIsIkpTT04iLCJlIiwiaXRlbSIsImluZGV4IiwidHJhbnNmb3JtSW5wdXQiLCJkYXRhIiwiYWN0aW9uIiwidHJhbnNmb3JtZWREYXRhIiwic2NoZW1hRmllbGROYW1lIiwibm9ybWFsaXplZERhdGEiLCJ0cmFuc2Zvcm1PdXRwdXQiLCJkb2MiLCJyZXN1bHQiLCJyZWxhdGlvbnNoaXBGaWVsZHMiLCJPYmplY3QiLCJlbnRyaWVzIiwiZmlsdGVyIiwicmVkdWNlIiwiYWNjIiwiZm9yRWFjaCIsIm9yaWdpbmFsS2V5IiwiZmluZFJlbGF0aW9uc2hpcE9yaWdpbmFsS2V5IiwicHJvY2Vzc1JlbGF0aW9uc2hpcEZpZWxkIiwia2V5cyIsImZpbmQiLCJvcGVyYXRvclRvUGF5bG9hZCIsIm9wZXJhdG9yIiwibm90X2VxdWFscyIsImdyZWF0ZXJfdGhhbiIsImdyZWF0ZXJfdGhhbl9lcXVhbCIsImxlc3NfdGhhbiIsImxlc3NfdGhhbl9lcXVhbCIsImxpa2UiLCJjb252ZXJ0V2hlcmVWYWx1ZSIsIk51bWJlciIsImNvbnZlcnRXaGVyZUNsYXVzZSIsInciLCJyZXMiLCJhbmQiLCJjb25uZWN0b3IiLCJvciIsImFuZENsYXVzZSIsIm9yQ2xhdXNlIiwiQU5EIiwiT1IiLCJjb252ZXJ0U2VsZWN0Iiwic2VsZWN0IiwiY29udmVydFNvcnQiLCJzb3J0QnkiLCJkaXJlY3Rpb24iXSwibWFwcGluZ3MiOiJBQUFBLFNBQVNBLGVBQWUsUUFBUSxjQUFhO0FBQzdDLFNBQW9DQyxhQUFhLFFBQVEsaUJBQWdCO0FBSXpFLE9BQU8sTUFBTUMsa0JBQWtCLENBQUNDLFNBQTRCQztJQUMxRCxNQUFNQyxTQUFTSixjQUFjRTtJQUU3QixTQUFTRyxTQUFTQyxPQUFjO1FBQzlCLElBQUlILGlCQUFpQjtZQUNuQkksUUFBUUMsR0FBRyxDQUFDLENBQUMsb0JBQW9CLENBQUMsS0FBS0Y7UUFDekM7SUFDRjtJQUVBLFNBQVNHLGFBQWFDLEtBQWE7UUFDakMsTUFBTUMsYUFBYSxBQUFDUCxNQUE4QixDQUFDTSxNQUFNLEVBQUVFLGFBQWFGO1FBQ3hFLElBQUksQ0FBQ0MsWUFBWTtZQUNmLE1BQU0sSUFBSVosZ0JBQWdCLENBQUMsTUFBTSxFQUFFVyxNQUFNLGdDQUFnQyxDQUFDO1FBQzVFO1FBQ0EsT0FBT0M7SUFDVDtJQUVBLFNBQVNFLGFBQWFILEtBQWEsRUFBRUksS0FBYTtRQUNoRCxJQUFJQSxVQUFVLE1BQU07WUFDbEIsT0FBT0E7UUFDVDtRQUNBLE1BQU1DLElBQUlYLE1BQU0sQ0FBQ00sTUFBTSxFQUFFTSxNQUFNLENBQUNGLE1BQU07UUFDdEMsTUFBTUcsWUFBWUYsR0FBR0UsYUFBYUg7UUFDbENULFNBQVM7WUFBQztZQUFjO2dCQUFFSztnQkFBT1EsZUFBZUo7Z0JBQU9HO1lBQVU7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
|
|
667
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uL3NyYy9iZXR0ZXItYXV0aC9hZGFwdGVyL3RyYW5zZm9ybS9pbmRleC50cyJdLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBGaWVsZEF0dHJpYnV0ZSwgRmllbGRUeXBlLCBnZXRBdXRoVGFibGVzIH0gZnJvbSAnYmV0dGVyLWF1dGgvZGInXG5pbXBvcnQgdHlwZSB7IEJldHRlckF1dGhPcHRpb25zLCBXaGVyZSB9IGZyb20gJ2JldHRlci1hdXRoJ1xuaW1wb3J0IHR5cGUgeyBDb2xsZWN0aW9uU2x1ZywgV2hlcmUgYXMgUGF5bG9hZFdoZXJlIH0gZnJvbSAncGF5bG9hZCdcblxuZXhwb3J0IGNvbnN0IGNyZWF0ZVRyYW5zZm9ybSA9IChvcHRpb25zOiBCZXR0ZXJBdXRoT3B0aW9ucywgZW5hYmxlRGVidWdMb2dzOiBib29sZWFuKSA9PiB7XG4gIGNvbnN0IHNjaGVtYSA9IGdldEF1dGhUYWJsZXMob3B0aW9ucylcblxuICBmdW5jdGlvbiBkZWJ1Z0xvZyhtZXNzYWdlOiBhbnlbXSkge1xuICAgIGlmIChlbmFibGVEZWJ1Z0xvZ3MpIHtcbiAgICAgIGNvbnNvbGUubG9nKGBbcGF5bG9hZC1kYi1hZGFwdGVyXWAsIC4uLm1lc3NhZ2UpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1hcHMgYSBCZXR0ZXJBdXRoIHNjaGVtYSBtb2RlbCBuYW1lIHRvIGl0cyBjb3JyZXNwb25kaW5nIFBheWxvYWQgQ01TIGNvbGxlY3Rpb24gc2x1Zy5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiByZXNvbHZlcyB0aGUgYXBwcm9wcmlhdGUgY29sbGVjdGlvbiBzbHVnIGJ5OlxuICAgKiAxLiBMb29raW5nIHVwIHRoZSBtb2RlbCBpbiB0aGUgQmV0dGVyQXV0aCBzY2hlbWEgdG8gZmluZCBpdHMgY29uZmlndXJlZCBtb2RlbE5hbWVcbiAgICogMi4gRmFsbGluZyBiYWNrIHRvIHRoZSBvcmlnaW5hbCBtb2RlbCBuYW1lIGlmIG5vIG1hcHBpbmcgZXhpc3RzXG4gICAqXG4gICAqIENvbGxlY3Rpb24gc2x1ZyByZXNvbHV0aW9uIGZvbGxvd3MgdGhlc2UgcnVsZXM6XG4gICAqIC0gRm9yIGJhc2UgY29sbGVjdGlvbnM6IFRoZSBzYW5pdGl6ZUJldHRlckF1dGhPcHRpb25zIGZ1bmN0aW9uIGVuc3VyZXMgdGhlIGNvbGxlY3Rpb24gc2x1Z1xuICAgKiAgIGZyb20gcGx1Z2luIG9wdGlvbnMgaXMgc2V0IGFzIHRoZSBtb2RlbCBuYW1lIGluIHRoZSBzY2hlbWFcbiAgICogLSBGb3IgcGx1Z2luczogVGhlIGJldHRlckF1dGhQbHVnaW5TbHVncyBjb25zdGFudCBpcyB1c2VkIGFzIHRoZSBtb2RlbE5hbWVcbiAgICpcbiAgICogQHBhcmFtIG1vZGVsIC0gVGhlIEJldHRlckF1dGggbW9kZWwgbmFtZSB0byByZXNvbHZlXG4gICAqIEByZXR1cm5zIFRoZSBjb3JyZXNwb25kaW5nIFBheWxvYWQgQ01TIGNvbGxlY3Rpb24gc2x1Z1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJZiBzY2hlbWFbJ3VzZXInXS5tb2RlbE5hbWUgaXMgJ3VzZXJzJ1xuICAgKiBnZXRDb2xsZWN0aW9uU2x1ZygndXNlcicpIC8vIFJldHVybnMgJ3VzZXJzJ1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJZiBtb2RlbCBkb2Vzbid0IGV4aXN0IGluIHNjaGVtYVxuICAgKiBnZXRDb2xsZWN0aW9uU2x1ZygnY3VzdG9tJykgLy8gUmV0dXJucyAnY3VzdG9tJ1xuICAgKlxuICAgKiBAd2FybmluZyBJZiBhIGNvbGxlY3Rpb24gaXMgb3ZlcnJpZGRlbiB1c2luZyB0aGUgY29sbGVjdGlvbk92ZXJyaWRlIG9wdGlvblxuICAgKiB3aXRob3V0IHVwZGF0aW5nIHRoZSBzY2hlbWEgbWFwcGluZywgdGhpcyBmdW5jdGlvbiBtYXkgcmV0dXJuIGluY29ycmVjdCBzbHVnc1xuICAgKi9cbiAgZnVuY3Rpb24gZ2V0Q29sbGVjdGlvblNsdWcobW9kZWw6IHN0cmluZyk6IENvbGxlY3Rpb25TbHVnIHtcbiAgICAvLyBGaXJzdCB0cnkgdG8gZ2V0IHRoZSBtb2RlbE5hbWUgZnJvbSBzY2hlbWEsIG90aGVyd2lzZSBmYWxsIGJhY2sgdG8gdGhlIG9yaWdpbmFsIG1vZGVsIG5hbWVcbiAgICBjb25zdCBjb2xsZWN0aW9uID0gc2NoZW1hW21vZGVsXT8ubW9kZWxOYW1lIHx8IG1vZGVsXG4gICAgZGVidWdMb2coWydnZXRDb2xsZWN0aW9uU2x1ZzonLCB7IG1vZGVsLCByZXNvbHZlZFNsdWc6IGNvbGxlY3Rpb24gfV0pXG4gICAgcmV0dXJuIGNvbGxlY3Rpb24gYXMgQ29sbGVjdGlvblNsdWdcbiAgfVxuXG4gIC8qKlxuICAgKiBNYXBzIGEgQmV0dGVyQXV0aCBzY2hlbWEgZmllbGQgdG8gaXRzIGNvcnJlc3BvbmRpbmcgUGF5bG9hZCBDTVMgZmllbGQgbmFtZS5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiByZXNvbHZlcyB0aGUgYXBwcm9wcmlhdGUgZmllbGQgbmFtZSBieTpcbiAgICogMS4gUHJlc2VydmluZyAnaWQnIG9yICdfaWQnIGZpZWxkcyBhcy1pcyAoc3BlY2lhbCBjYXNlIGhhbmRsaW5nKVxuICAgKiAyLiBMb29raW5nIHVwIHRoZSBmaWVsZCBpbiB0aGUgQmV0dGVyQXV0aCBzY2hlbWEgdG8gZmluZCBpdHMgY29uZmlndXJlZCBmaWVsZE5hbWVcbiAgICogMy4gRmFsbGluZyBiYWNrIHRvIHRoZSBvcmlnaW5hbCBmaWVsZCBuYW1lIGlmIG5vIG1hcHBpbmcgZXhpc3RzXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBCZXR0ZXJBdXRoIG1vZGVsIG5hbWUgY29udGFpbmluZyB0aGUgZmllbGRcbiAgICogQHBhcmFtIGZpZWxkIC0gVGhlIG9yaWdpbmFsIGZpZWxkIG5hbWUgdG8gcmVzb2x2ZVxuICAgKiBAcmV0dXJucyBUaGUgY29ycmVzcG9uZGluZyBQYXlsb2FkIENNUyBmaWVsZCBuYW1lXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElmIHNjaGVtYVsndXNlciddLmZpZWxkc1snZW1haWwnXS5maWVsZE5hbWUgaXMgJ2VtYWlsQWRkcmVzcydcbiAgICogZ2V0RmllbGROYW1lKCd1c2VyJywgJ2VtYWlsJykgLy8gUmV0dXJucyAnZW1haWxBZGRyZXNzJ1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBTcGVjaWFsIGNhc2UgZm9yIElEIGZpZWxkc1xuICAgKiBnZXRGaWVsZE5hbWUoJ3VzZXInLCAnaWQnKSAvLyBBbHdheXMgcmV0dXJucyAnaWQnXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElmIGZpZWxkIGRvZXNuJ3QgZXhpc3QgaW4gc2NoZW1hIG9yIGhhcyBubyBmaWVsZE5hbWUgbWFwcGluZ1xuICAgKiBnZXRGaWVsZE5hbWUoJ3VzZXInLCAnY3VzdG9tJykgLy8gUmV0dXJucyAnY3VzdG9tJ1xuICAgKlxuICAgKiBAd2FybmluZyBJZiBhIGZpZWxkTmFtZSBpcyBvdmVycmlkZGVuIGluIHRoZSBwYXlsb2FkIGNvbGxlY3Rpb24gY29uZmlnIHVzaW5nIHRoZSBjb2xsZWN0aW9uT3ZlcnJpZGUgb3B0aW9uXG4gICAqIHdpdGhvdXQgdXBkYXRpbmcgdGhlIHNjaGVtYSBtYXBwaW5nLCB0aGlzIGZ1bmN0aW9uIG1heSByZXR1cm4gaW5jb3JyZWN0IGZpZWxkIG5hbWVzXG4gICAqL1xuICBmdW5jdGlvbiBnZXRGaWVsZE5hbWUobW9kZWw6IHN0cmluZywgZmllbGQ6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgLy8gU3BlY2lhbCBjYXNlOiAnaWQnIG9yICdfaWQnIGlzIGFsd2F5cyBwcmVzZXJ2ZWQgYXMtaXNcbiAgICBpZiAoWydpZCcsICdfaWQnXS5pbmNsdWRlcyhmaWVsZCkpIHtcbiAgICAgIHJldHVybiBmaWVsZFxuICAgIH1cblxuICAgIC8vIExvb2sgdXAgdGhlIGZpZWxkIGluIHRoZSBzY2hlbWFcbiAgICBjb25zdCBmaWVsZERlZmluaXRpb24gPSBzY2hlbWFbbW9kZWxdPy5maWVsZHNbZmllbGRdXG5cbiAgICAvLyBVc2UgdGhlIGNvbmZpZ3VyZWQgZmllbGROYW1lIGlmIGF2YWlsYWJsZSwgb3RoZXJ3aXNlIGZhbGwgYmFjayB0byBvcmlnaW5hbFxuICAgIGNvbnN0IGZpZWxkTmFtZSA9IGZpZWxkRGVmaW5pdGlvbj8uZmllbGROYW1lIHx8IGZpZWxkXG5cbiAgICAvLyBMb2cgdGhlIGZpZWxkIHJlc29sdXRpb24gZm9yIGRlYnVnZ2luZ1xuICAgIGRlYnVnTG9nKFsnZ2V0RmllbGQ6ICcsIHsgbW9kZWwsIG9yaWdpbmFsRmllbGQ6IGZpZWxkLCBmaWVsZE5hbWUgfV0pXG5cbiAgICByZXR1cm4gZmllbGROYW1lXG4gIH1cblxuICAvKipcbiAgICogRGV0ZXJtaW5lcyBpZiBhIGZpZWxkIGlzIGEgcmVsYXRpb25zaGlwIGZpZWxkIGJ5IGNoZWNraW5nIGZvciBhIHJlZmVyZW5jZXMgcHJvcGVydHkuXG4gICAqXG4gICAqIFJlbGF0aW9uc2hpcCBmaWVsZHMgaW4gdGhlIHNjaGVtYSBoYXZlIGEgJ3JlZmVyZW5jZXMnIHByb3BlcnR5IHRoYXQgcG9pbnRzIHRvIGFub3RoZXIgbW9kZWwuXG4gICAqIFRoaXMgZnVuY3Rpb24gY2hlY2tzIGlmIHRoaXMgcHJvcGVydHkgZXhpc3RzIHRvIGlkZW50aWZ5IHJlbGF0aW9uc2hpcCBmaWVsZHMuXG4gICAqXG4gICAqIEBwYXJhbSBmaWVsZEtleSAtIFRoZSBrZXkgb2YgdGhlIGZpZWxkIHRvIGNoZWNrIGluIHRoZSBzY2hlbWFcbiAgICogQHBhcmFtIHNjaGVtYUZpZWxkcyAtIE9iamVjdCBjb250YWluaW5nIGFsbCBmaWVsZHMgZnJvbSB0aGUgc2NoZW1hIGZvciBhIHNwZWNpZmljIG1vZGVsXG4gICAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGZpZWxkIGlzIGEgcmVsYXRpb25zaGlwIGZpZWxkIChoYXMgcmVmZXJlbmNlcyksIGZhbHNlIG90aGVyd2lzZVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJZiBzY2hlbWEudXNlci5maWVsZHMucG9zdHMgaGFzIHsgcmVmZXJlbmNlczoge30gfVxuICAgKiBpc1JlbGF0aW9uc2hpcEZpZWxkKCdwb3N0cycsIHNjaGVtYS51c2VyLmZpZWxkcykgLy8gUmV0dXJucyB0cnVlXG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElmIHNjaGVtYS51c2VyLmZpZWxkcy5lbWFpbCBoYXMgbm8gcmVmZXJlbmNlcyBwcm9wZXJ0eVxuICAgKiBpc1JlbGF0aW9uc2hpcEZpZWxkKCdlbWFpbCcsIHNjaGVtYS51c2VyLmZpZWxkcykgLy8gUmV0dXJucyBmYWxzZVxuICAgKi9cbiAgZnVuY3Rpb24gaXNSZWxhdGlvbnNoaXBGaWVsZChmaWVsZEtleTogc3RyaW5nLCBzY2hlbWFGaWVsZHM6IFJlY29yZDxzdHJpbmcsIEZpZWxkQXR0cmlidXRlPEZpZWxkVHlwZT4+KTogYm9vbGVhbiB7XG4gICAgLy8gQSBmaWVsZCBpcyBhIHJlbGF0aW9uc2hpcCBmaWVsZCBpZiBpdCBoYXMgYSAncmVmZXJlbmNlcycgcHJvcGVydHkgZGVmaW5lZFxuICAgIHJldHVybiBzY2hlbWFGaWVsZHNbZmllbGRLZXldPy5yZWZlcmVuY2VzICE9PSB1bmRlZmluZWRcbiAgfVxuXG4gIC8qKlxuICAgKiBEZXRlcm1pbmVzIGlmIGEgdmFsdWUgaXMgYSB2YWxpZCBkYXRlIHN0cmluZyB0aGF0IGNhbiBiZSBwYXJzZWQgaW50byBhIERhdGUgb2JqZWN0LlxuICAgKlxuICAgKiBUaGlzIHV0aWxpdHkgZnVuY3Rpb24gY2hlY2tzIGlmIGEgdmFsdWUgaXMgYSBzdHJpbmcgYW5kIGNhbiBiZSBzdWNjZXNzZnVsbHkgcGFyc2VkXG4gICAqIGludG8gYSBKYXZhU2NyaXB0IERhdGUgb2JqZWN0IHVzaW5nIERhdGUucGFyc2UoKS4gSXQncyB1c2VkIHRvIGlkZW50aWZ5IGRhdGUgZmllbGRzXG4gICAqIGR1cmluZyBkYXRhIHRyYW5zZm9ybWF0aW9uIHByb2Nlc3Nlcy5cbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGNoZWNrIGlmIGl0J3MgYSB2YWxpZCBkYXRlIHN0cmluZ1xuICAgKiBAcmV0dXJucyBUcnVlIGlmIHRoZSB2YWx1ZSBpcyBhIHN0cmluZyB0aGF0IGNhbiBiZSBwYXJzZWQgYXMgYSBkYXRlLCBmYWxzZSBvdGhlcndpc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyB0cnVlIGZvciBJU08gZGF0ZSBzdHJpbmdzXG4gICAqIGlzRGF0ZUZpZWxkKCcyMDIzLTAxLTAxVDEyOjAwOjAwWicpIC8vIHRydWVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyBmYWxzZSBmb3Igbm9uLWRhdGUgc3RyaW5ncyBvciBvdGhlciB0eXBlc1xuICAgKiBpc0RhdGVGaWVsZCgnbm90IGEgZGF0ZScpIC8vIGZhbHNlXG4gICAqIGlzRGF0ZUZpZWxkKDEyMykgLy8gZmFsc2VcbiAgICovXG4gIGZ1bmN0aW9uIGlzRGF0ZUZpZWxkKHZhbHVlOiBhbnkpOiBib29sZWFuIHtcbiAgICAvLyBDaGVjayBpZiB2YWx1ZSBpcyBhIHN0cmluZyBhbmQgY2FuIGJlIHBhcnNlZCBhcyBhIHZhbGlkIGRhdGVcbiAgICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oRGF0ZS5wYXJzZSh2YWx1ZSkpXG4gIH1cblxuICAvKipcbiAgICogRXh0cmFjdHMgYSBzaW5nbGUgSUQgdmFsdWUgZnJvbSBhIFBheWxvYWQgd2hlcmUgY2xhdXNlIGlmIGl0IHJlcHJlc2VudHMgYSBzaW1wbGUgSUQgcXVlcnkuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gYW5hbHl6ZXMgYSBQYXlsb2FkIHdoZXJlIGNsYXVzZSB0byBkZXRlcm1pbmUgaWYgaXQncyBhIHNpbXBsZSBxdWVyeSBmb3IgYVxuICAgKiBzaW5nbGUgZG9jdW1lbnQgYnkgSUQuIEl0IHN1cHBvcnRzIGJvdGggJ2lkJyBhbmQgJ19pZCcgZmllbGRzIHdpdGggJ2VxdWFscycgb3IgJ2NvbnRhaW5zJ1xuICAgKiBvcGVyYXRvcnMuIFRoaXMgaXMgdXNlZnVsIGZvciBvcHRpbWl6aW5nIHF1ZXJpZXMgd2hlbiB3ZSBvbmx5IG5lZWQgdG8gZmV0Y2ggYSBzaW5nbGUgZG9jdW1lbnQuXG4gICAqXG4gICAqIEBwYXJhbSB3aGVyZSAtIFRoZSBQYXlsb2FkIHdoZXJlIGNsYXVzZSB0byBhbmFseXplXG4gICAqIEByZXR1cm5zIFRoZSBJRCB2YWx1ZSAoc3RyaW5nIG9yIG51bWJlcikgaWYgdGhlIHdoZXJlIGNsYXVzZSBpcyBhIHNpbXBsZSBJRCBxdWVyeSwgbnVsbCBvdGhlcndpc2VcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyAnMTIzJyBmb3IgYSBzaW1wbGUgZXF1YWxzIHF1ZXJ5XG4gICAqIHNpbmdsZUlkUXVlcnkoeyBpZDogeyBlcXVhbHM6ICcxMjMnIH0gfSkgLy8gJzEyMydcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyA0NTYgZm9yIGEgc2ltcGxlIGVxdWFscyBxdWVyeSB3aXRoIG51bWJlciBJRFxuICAgKiBzaW5nbGVJZFF1ZXJ5KHsgX2lkOiB7IGVxdWFsczogNDU2IH0gfSkgLy8gNDU2XG4gICAqXG4gICAqIEBleGFtcGxlXG4gICAqIC8vIFJldHVybnMgJzc4OScgZm9yIGEgY29udGFpbnMgcXVlcnkgd2l0aCBhIHNpbmdsZSB2YWx1ZVxuICAgKiBzaW5nbGVJZFF1ZXJ5KHsgaWQ6IHsgY29udGFpbnM6IFsnNzg5J10gfSB9KSAvLyAnNzg5J1xuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBSZXR1cm5zIG51bGwgZm9yIGNvbXBsZXggcXVlcmllc1xuICAgKiBzaW5nbGVJZFF1ZXJ5KHsgYW5kOiBbeyBpZDogeyBlcXVhbHM6ICcxMjMnIH0gfV0gfSkgLy8gbnVsbFxuICAgKi9cbiAgZnVuY3Rpb24gc2luZ2xlSWRRdWVyeSh3aGVyZTogUGF5bG9hZFdoZXJlKSB7XG4gICAgLy8gUmV0dXJuIG51bGwgZm9yIGVtcHR5IHdoZXJlIGNsYXVzZXMgb3IgY29tcGxleCBxdWVyaWVzIHdpdGggJ2FuZCcvJ29yJyBvcGVyYXRvcnNcbiAgICBpZiAoIXdoZXJlIHx8ICdhbmQnIGluIHdoZXJlIHx8ICdvcicgaW4gd2hlcmUpIHJldHVybiBudWxsXG5cbiAgICAvLyBDaGVjayBpZiB0aGUgd2hlcmUgY2xhdXNlIGNvbnRhaW5zIGVpdGhlciAnaWQnIG9yICdfaWQnIGZpZWxkXG4gICAgaWYgKFsnaWQnLCAnX2lkJ10uc29tZSgoZmllbGQpID0+IGZpZWxkIGluIHdoZXJlKSkge1xuICAgICAgLy8gRGV0ZXJtaW5lIHdoaWNoIElEIGZpZWxkIGlzIGJlaW5nIHVzZWQgKHN1cHBvcnQgYm90aCAnaWQnIGFuZCAnX2lkJylcbiAgICAgIGNvbnN0IGlkRmllbGQgPSAnaWQnIGluIHdoZXJlID8gJ2lkJyA6ICdfaWQnXG4gICAgICBjb25zdCBjb25kaXRpb24gPSB3aGVyZVtpZEZpZWxkXVxuXG4gICAgICAvLyBQcm9jZXNzIHRoZSBlcXVhbHMgb3BlcmF0b3IgY2FzZVxuICAgICAgaWYgKGNvbmRpdGlvbiAmJiB0eXBlb2YgY29uZGl0aW9uID09PSAnb2JqZWN0JyAmJiAhQXJyYXkuaXNBcnJheShjb25kaXRpb24pICYmICdlcXVhbHMnIGluIGNvbmRpdGlvbikge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IGNvbmRpdGlvbi5lcXVhbHNcbiAgICAgICAgLy8gT25seSByZXR1cm4gc3RyaW5nIG9yIG51bWJlciBJRCB2YWx1ZXNcbiAgICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIHJldHVybiB2YWx1ZVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIC8vIFByb2Nlc3MgdGhlIGNvbnRhaW5zIG9wZXJhdG9yIGNhc2Ugd2l0aCBhIHNpbmdsZSB2YWx1ZVxuICAgICAgaWYgKFxuICAgICAgICBjb25kaXRpb24gJiZcbiAgICAgICAgdHlwZW9mIGNvbmRpdGlvbiA9PT0gJ29iamVjdCcgJiZcbiAgICAgICAgIUFycmF5LmlzQXJyYXkoY29uZGl0aW9uKSAmJlxuICAgICAgICAnY29udGFpbnMnIGluIGNvbmRpdGlvbiAmJlxuICAgICAgICBBcnJheS5pc0FycmF5KGNvbmRpdGlvbi5jb250YWlucykgJiZcbiAgICAgICAgY29uZGl0aW9uLmNvbnRhaW5zLmxlbmd0aCA9PT0gMVxuICAgICAgKSB7XG4gICAgICAgIGNvbnN0IHZhbHVlID0gY29uZGl0aW9uLmNvbnRhaW5zWzBdXG4gICAgICAgIC8vIE9ubHkgcmV0dXJuIHN0cmluZyBvciBudW1iZXIgSUQgdmFsdWVzXG4gICAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHtcbiAgICAgICAgICByZXR1cm4gdmFsdWVcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIFJldHVybiBudWxsIGlmIG5vIHZhbGlkIElEIHF1ZXJ5IHdhcyBmb3VuZFxuICAgIHJldHVybiBudWxsXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyBkYXRhIHZhbHVlcyBiYXNlZCBvbiBmaWVsZCB0eXBlIGFuZCByZXF1aXJlZCBJRCB0eXBlXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyB0eXBlIGNvbnZlcnNpb24gZm9yIHJlbGF0aW9uc2hpcCBmaWVsZHMgdG8gZW5zdXJlXG4gICAqIElEcyBhcmUgaW4gdGhlIGNvcnJlY3QgZm9ybWF0IChzdHJpbmcgb3IgbnVtYmVyKSBiYXNlZCBvbiB0aGUgY29uZmlndXJhdGlvbi5cbiAgICpcbiAgICogQHBhcmFtIGtleSAtIFRoZSBmaWVsZCBrZXkvbmFtZVxuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgdmFsdWUgdG8gbm9ybWFsaXplXG4gICAqIEBwYXJhbSBpc1JlbGF0ZWRGaWVsZCAtIFdoZXRoZXIgdGhpcyBmaWVsZCBpcyBhIHJlbGF0aW9uc2hpcCBmaWVsZFxuICAgKiBAcGFyYW0gaWRUeXBlIC0gVGhlIGV4cGVjdGVkIElEIHR5cGUgKCdudW1iZXInIG9yICd0ZXh0JylcbiAgICogQHJldHVybnMgVGhlIG5vcm1hbGl6ZWQgdmFsdWVcbiAgICovXG4gIGZ1bmN0aW9uIG5vcm1hbGl6ZURhdGEoe1xuICAgIGtleSxcbiAgICB2YWx1ZSxcbiAgICBpc1JlbGF0ZWRGaWVsZCxcbiAgICBpZFR5cGVcbiAgfToge1xuICAgIGtleTogc3RyaW5nXG4gICAgdmFsdWU6IGFueVxuICAgIGlzUmVsYXRlZEZpZWxkOiBib29sZWFuXG4gICAgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0J1xuICB9KSB7XG4gICAgLy8gU2tpcCBwcm9jZXNzaW5nIGZvciBudWxsL3VuZGVmaW5lZCB2YWx1ZXNcbiAgICBpZiAodmFsdWUgPT09IG51bGwgfHwgdmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfVxuXG4gICAgaWYgKFsnaWQnLCAnX2lkJ10uaW5jbHVkZXMoa2V5KSkge1xuICAgICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgJiYgaWRUeXBlID09PSAnbnVtYmVyJykge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludCh2YWx1ZSwgMTApXG4gICAgICAgIGlmICghaXNOYU4ocGFyc2VkKSkge1xuICAgICAgICAgIGRlYnVnTG9nKFtgSUQgY29udmVyc2lvbjogJHtrZXl9IGNvbnZlcnRpbmcgc3RyaW5nIElEIHRvIG51bWJlcmAsIHsgb3JpZ2luYWw6IHZhbHVlLCBjb252ZXJ0ZWQ6IHBhcnNlZCB9XSlcbiAgICAgICAgICByZXR1cm4gcGFyc2VkXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmIGlkVHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgIGNvbnN0IHN0cmluZ0lkID0gU3RyaW5nKHZhbHVlKVxuICAgICAgICBkZWJ1Z0xvZyhbYElEIGNvbnZlcnNpb246ICR7a2V5fSBjb252ZXJ0aW5nIG51bWJlciBJRCB0byBzdHJpbmdgLCB7IG9yaWdpbmFsOiB2YWx1ZSwgY29udmVydGVkOiBzdHJpbmdJZCB9XSlcbiAgICAgICAgcmV0dXJuIHN0cmluZ0lkXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gT25seSBwcm9jZXNzIHJlbGF0aW9uc2hpcCBmaWVsZHMgdGhhdCBuZWVkIHR5cGUgY29udmVyc2lvblxuICAgIGlmIChpc1JlbGF0ZWRGaWVsZCkge1xuICAgICAgLy8gSGFuZGxlIHNpbmdsZSBJRCB2YWx1ZSBjb252ZXJzaW9uXG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiBpZFR5cGUgPT09ICdudW1iZXInKSB7XG4gICAgICAgIGNvbnN0IHBhcnNlZCA9IHBhcnNlSW50KHZhbHVlLCAxMClcbiAgICAgICAgaWYgKCFpc05hTihwYXJzZWQpKSB7XG4gICAgICAgICAgZGVidWdMb2coW2BJRCBjb252ZXJzaW9uOiAke2tleX0gY29udmVydGluZyBzdHJpbmcgSUQgdG8gbnVtYmVyYCwgeyBvcmlnaW5hbDogdmFsdWUsIGNvbnZlcnRlZDogcGFyc2VkIH1dKVxuICAgICAgICAgIHJldHVybiBwYXJzZWRcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInICYmIGlkVHlwZSA9PT0gJ3RleHQnKSB7XG4gICAgICAgIGNvbnN0IHN0cmluZ0lkID0gU3RyaW5nKHZhbHVlKVxuICAgICAgICBkZWJ1Z0xvZyhbYElEIGNvbnZlcnNpb246ICR7a2V5fSBjb252ZXJ0aW5nIG51bWJlciBJRCB0byBzdHJpbmdgLCB7IG9yaWdpbmFsOiB2YWx1ZSwgY29udmVydGVkOiBzdHJpbmdJZCB9XSlcbiAgICAgICAgcmV0dXJuIHN0cmluZ0lkXG4gICAgICB9XG5cbiAgICAgIC8vIEhhbmRsZSBhcnJheSBvZiBJRHMgLSBtYXAgZWFjaCB2YWx1ZSB0byB0aGUgY29ycmVjdCB0eXBlXG4gICAgICBpZiAoQXJyYXkuaXNBcnJheSh2YWx1ZSkpIHtcbiAgICAgICAgcmV0dXJuIHZhbHVlLm1hcCgoaWQpID0+IHtcbiAgICAgICAgICAvLyBTa2lwIG51bGwvdW5kZWZpbmVkIHZhbHVlcyBpbiBhcnJheXNcbiAgICAgICAgICBpZiAoaWQgPT09IG51bGwgfHwgaWQgPT09IHVuZGVmaW5lZCkgcmV0dXJuIGlkXG5cbiAgICAgICAgICBpZiAoaWRUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgICBjb25zdCBwYXJzZWQgPSBwYXJzZUludChpZCwgMTApXG4gICAgICAgICAgICByZXR1cm4gIWlzTmFOKHBhcnNlZCkgPyBwYXJzZWQgOiBpZFxuICAgICAgICAgIH0gZWxzZSBpZiAoaWRUeXBlID09PSAndGV4dCcgJiYgdHlwZW9mIGlkID09PSAnbnVtYmVyJykge1xuICAgICAgICAgICAgcmV0dXJuIFN0cmluZyhpZClcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGlkXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfVxuXG4gICAgLy8gUmV0dXJuIG9yaWdpbmFsIHZhbHVlIGlmIG5vIGNvbnZlcnNpb24gd2FzIG5lZWRlZCBvciBhcHBsaWNhYmxlXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogVHJhbnNmb3JtcyBpbnB1dCBkYXRhIGZyb20gYmV0dGVyLWF1dGggdG8gUGF5bG9hZCBDTVMgZm9ybWF0XG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlczpcbiAgICogMS4gRmllbGQgbmFtZSBtYXBwaW5nIGFjY29yZGluZyB0byBzY2hlbWEgZGVmaW5pdGlvbnNcbiAgICogMi4gSUQgdHlwZSBjb252ZXJzaW9uIGZvciByZWxhdGlvbnNoaXAgZmllbGRzXG4gICAqIDMuIFByb3BlciBkYXRhIG5vcm1hbGl6YXRpb24gYmFzZWQgb24gZmllbGQgdHlwZXNcbiAgICpcbiAgICogQHBhcmFtIGRhdGEgLSBUaGUgaW5wdXQgZGF0YSBmcm9tIGJldHRlci1hdXRoXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbCBuYW1lIGluIHRoZSBzY2hlbWFcbiAgICogQHBhcmFtIGlkVHlwZSAtIFRoZSBleHBlY3RlZCBJRCB0eXBlICgnbnVtYmVyJyBvciAndGV4dCcpXG4gICAqIEByZXR1cm5zIFRyYW5zZm9ybWVkIGRhdGEgY29tcGF0aWJsZSB3aXRoIFBheWxvYWQgQ01TXG4gICAqL1xuICBmdW5jdGlvbiB0cmFuc2Zvcm1JbnB1dCh7XG4gICAgZGF0YSxcbiAgICBtb2RlbCxcbiAgICBpZFR5cGVcbiAgfToge1xuICAgIGRhdGE6IFJlY29yZDxzdHJpbmcsIGFueT5cbiAgICBtb2RlbDogc3RyaW5nXG4gICAgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0J1xuICB9KTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgY29uc3QgdHJhbnNmb3JtZWREYXRhOiBSZWNvcmQ8c3RyaW5nLCBhbnk+ID0ge31cbiAgICBjb25zdCBzY2hlbWFGaWVsZHMgPSBzY2hlbWE/Llttb2RlbF0/LmZpZWxkcyA/PyB7fVxuXG4gICAgLy8gUHJvY2VzcyBlYWNoIGZpZWxkIGluIHRoZSBpbnB1dCBkYXRhXG4gICAgT2JqZWN0LmVudHJpZXMoZGF0YSkuZm9yRWFjaCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAvLyBTa2lwIG51bGwvdW5kZWZpbmVkIHZhbHVlc1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG5cbiAgICAgIC8vIERldGVybWluZSBpZiB0aGlzIGlzIGEgcmVsYXRpb25zaGlwIGZpZWxkXG4gICAgICBjb25zdCBpc1JlbGF0ZWRGaWVsZCA9IGlzUmVsYXRpb25zaGlwRmllbGQoa2V5LCBzY2hlbWFGaWVsZHMpXG5cbiAgICAgIC8vIEdldCB0aGUgbWFwcGVkIGZpZWxkIG5hbWUgZnJvbSBzY2hlbWEgKGlmIGFueSlcbiAgICAgIGNvbnN0IHNjaGVtYUZpZWxkTmFtZSA9IHNjaGVtYUZpZWxkc1trZXldPy5maWVsZE5hbWVcblxuICAgICAgLy8gTm9ybWFsaXplIHRoZSBkYXRhIHZhbHVlIGJhc2VkIG9uIGZpZWxkIHR5cGUgYW5kIElEIHR5cGVcbiAgICAgIGNvbnN0IG5vcm1hbGl6ZWREYXRhID0gbm9ybWFsaXplRGF0YSh7XG4gICAgICAgIGlkVHlwZSxcbiAgICAgICAga2V5LFxuICAgICAgICB2YWx1ZSxcbiAgICAgICAgaXNSZWxhdGVkRmllbGRcbiAgICAgIH0pXG5cbiAgICAgIC8vIFVzZSB0aGUgc2NoZW1hLWRlZmluZWQgZmllbGQgbmFtZSBpZiBhdmFpbGFibGUsIG90aGVyd2lzZSB1c2Ugb3JpZ2luYWwga2V5XG4gICAgICBjb25zdCB0YXJnZXRGaWVsZE5hbWUgPSBzY2hlbWFGaWVsZE5hbWUgfHwga2V5XG4gICAgICB0cmFuc2Zvcm1lZERhdGFbdGFyZ2V0RmllbGROYW1lXSA9IG5vcm1hbGl6ZWREYXRhXG4gICAgfSlcblxuICAgIHJldHVybiB0cmFuc2Zvcm1lZERhdGFcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFuc2Zvcm1zIFBheWxvYWQgQ01TIGRvY3VtZW50IG91dHB1dCB0byBtYXRjaCBCZXR0ZXJBdXRoIHNjaGVtYSBleHBlY3RhdGlvbnMuXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gaGFuZGxlcyBzZXZlcmFsIGNyaXRpY2FsIHRyYW5zZm9ybWF0aW9uczpcbiAgICpcbiAgICogMS4gSUQgQ29udmVyc2lvbjogRW5zdXJlcyBhbGwgSUQgZmllbGRzIGFyZSBzdHJpbmdzIGFzIHJlcXVpcmVkIGJ5IEJldHRlckF1dGhcbiAgICogICAgKHNlZTogaHR0cHM6Ly9naXRodWIuY29tL2JldHRlci1hdXRoL2JldHRlci1hdXRoL2Jsb2IvbWFpbi9wYWNrYWdlcy9iZXR0ZXItYXV0aC9zcmMvZGIvc2NoZW1hLnRzI0wxMjUpXG4gICAqXG4gICAqIDIuIFJlbGF0aW9uc2hpcCBGaWVsZCBNYXBwaW5nOiBBbGlnbnMgcmVsYXRpb25zaGlwIGZpZWxkcyB3aXRoIEJldHRlckF1dGggc2NoZW1hIG5hbWluZyBjb252ZW50aW9uc1xuICAgKiAgICBhbmQgZW5zdXJlcyBwcm9wZXIgSUQgdHlwZSBoYW5kbGluZ1xuICAgKlxuICAgKiAzLiBEYXRlIENvbnZlcnNpb246IFRyYW5zZm9ybXMgZGF0ZSBzdHJpbmdzIGZyb20gUGF5bG9hZCBpbnRvIERhdGUgb2JqZWN0cyBmb3IgQmV0dGVyQXV0aFxuICAgKlxuICAgKiBOb3RlOiBXaGlsZSBzZXR0aW5nIGRlcHRoOiAxIGluIFBheWxvYWQgb3BlcmF0aW9ucyBzaW1wbGlmaWVzIHRoaXMgcHJvY2VzcyBieSBhdm9pZGluZ1xuICAgKiBkZWVwbHkgbmVzdGVkIG9iamVjdHMsIHdlIG1haW50YWluIGNvbXByZWhlbnNpdmUgY2hlY2tzIGZvciByb2J1c3RuZXNzLlxuICAgKlxuICAgKiBAcGFyYW0gZG9jIC0gVGhlIGRvY3VtZW50IHJldHVybmVkIGZyb20gUGF5bG9hZCBDTVNcbiAgICogQHBhcmFtIG1vZGVsIC0gVGhlIG1vZGVsIG5hbWUgaW4gdGhlIEJldHRlckF1dGggc2NoZW1hXG4gICAqIEByZXR1cm5zIFRoZSB0cmFuc2Zvcm1lZCBkb2N1bWVudCBjb21wYXRpYmxlIHdpdGggQmV0dGVyQXV0aFxuICAgKi9cbiAgZnVuY3Rpb24gdHJhbnNmb3JtT3V0cHV0PFQgZXh0ZW5kcyBSZWNvcmQ8c3RyaW5nLCBhbnk+IHwgbnVsbD4oeyBkb2MsIG1vZGVsIH06IHsgZG9jOiBUOyBtb2RlbDogc3RyaW5nIH0pOiBUIHtcbiAgICBpZiAoIWRvYyB8fCB0eXBlb2YgZG9jICE9PSAnb2JqZWN0JykgcmV0dXJuIGRvY1xuXG4gICAgY29uc3QgcmVzdWx0ID0geyAuLi5kb2MgfVxuICAgIGNvbnN0IHNjaGVtYUZpZWxkcyA9IHNjaGVtYT8uW21vZGVsXT8uZmllbGRzID8/IHt9XG5cbiAgICAvLyBJZGVudGlmeSByZWxhdGlvbnNoaXAgZmllbGRzIHdpdGggY3VzdG9tIGZpZWxkIG5hbWUgbWFwcGluZ3NcbiAgICBjb25zdCByZWxhdGlvbnNoaXBGaWVsZHMgPSBPYmplY3QuZnJvbUVudHJpZXMoT2JqZWN0LmVudHJpZXMoc2NoZW1hRmllbGRzKS5maWx0ZXIoKFtrZXldKSA9PiBpc1JlbGF0aW9uc2hpcEZpZWxkKGtleSwgc2NoZW1hRmllbGRzKSkpXG5cbiAgICBPYmplY3QuZW50cmllcyhkb2MpLmZvckVhY2goKFtrZXksIHZhbHVlXSkgPT4ge1xuICAgICAgaWYgKHZhbHVlID09PSBudWxsIHx8IHZhbHVlID09PSB1bmRlZmluZWQpIHJldHVyblxuXG4gICAgICAvLyBDb252ZXJ0IElEIGZpZWxkcyB0byBzdHJpbmdzIGZvciBCZXR0ZXJBdXRoIGNvbXBhdGliaWxpdHlcbiAgICAgIGlmIChbJ2lkJywgJ19pZCddLmluY2x1ZGVzKGtleSkpIHtcbiAgICAgICAgcmVzdWx0W2tleV0gPSBTdHJpbmcodmFsdWUpXG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICAvLyBIYW5kbGUgcmVsYXRpb25zaGlwIGZpZWxkcyB3aXRoIHJlbmFtZWQgZmllbGROYW1lc1xuICAgICAgY29uc3Qgb3JpZ2luYWxSZWxhdGVkRmllbGRLZXkgPSBPYmplY3Qua2V5cyhyZWxhdGlvbnNoaXBGaWVsZHMpLmZpbmQoKGspID0+IHJlbGF0aW9uc2hpcEZpZWxkc1trXS5maWVsZE5hbWUgPT09IGtleSlcbiAgICAgIGlmIChvcmlnaW5hbFJlbGF0ZWRGaWVsZEtleSkge1xuICAgICAgICBub3JtYWxpemVEb2N1bWVudElkcyhyZXN1bHQsIG9yaWdpbmFsUmVsYXRlZEZpZWxkS2V5LCBrZXksIHZhbHVlKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgLy8gQ29udmVydCBJU08gZGF0ZSBzdHJpbmdzIHRvIERhdGUgb2JqZWN0cyBmb3IgQmV0dGVyQXV0aFxuICAgICAgaWYgKGlzRGF0ZUZpZWxkKHZhbHVlKSkge1xuICAgICAgICByZXN1bHRba2V5XSA9IG5ldyBEYXRlKHZhbHVlKVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cbiAgICB9KVxuXG4gICAgcmV0dXJuIHJlc3VsdCBhcyBUXG4gIH1cblxuICAvKipcbiAgICogTm9ybWFsaXplcyBJRCBmaWVsZHMgZm9yIGJvdGggcHJpbWFyeSBhbmQgcmVsYXRpb25zaGlwIGRvY3VtZW50cy5cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBlbnN1cmVzIGNvbnNpc3RlbnQgSUQgaGFuZGxpbmcgYmV0d2VlbiBCZXR0ZXJBdXRoIGFuZCBQYXlsb2FkIENNUyBieTpcbiAgICogMS4gQ29udmVydGluZyBhbGwgSURzIHRvIHN0cmluZ3MgZm9yIEJldHRlckF1dGggKHN0b3JlZCBpbiBvcmlnaW5hbEtleSlcbiAgICogMi4gUHJlc2VydmluZyBvcmlnaW5hbCBJRCB0eXBlcyBmb3IgUGF5bG9hZCBDTVMgKHN0b3JlZCBpbiBmaWVsZE5hbWUpXG4gICAqXG4gICAqIFRoZSBmdW5jdGlvbiBoYW5kbGVzIHZhcmlvdXMgSUQgZm9ybWF0czpcbiAgICogLSBQcmltaXRpdmUgdmFsdWVzIChzdHJpbmcvbnVtYmVyIElEcylcbiAgICogLSBPYmplY3QgcmVmZXJlbmNlcyB3aXRoIElEIHByb3BlcnRpZXNcbiAgICogLSBBcnJheXMgb2YgZWl0aGVyIHByaW1pdGl2ZSBJRHMgb3Igb2JqZWN0IHJlZmVyZW5jZXNcbiAgICpcbiAgICogQHBhcmFtIHJlc3VsdCAtIFRoZSByZXN1bHQgb2JqZWN0IGJlaW5nIHRyYW5zZm9ybWVkXG4gICAqIEBwYXJhbSBvcmlnaW5hbEtleSAtIFRoZSBvcmlnaW5hbCBmaWVsZCBrZXkgZnJvbSBCZXR0ZXJBdXRoIHNjaGVtYVxuICAgKiBAcGFyYW0gZmllbGROYW1lIC0gVGhlIHJlbmFtZWQgZmllbGQgYXMgdXNlZCBpbiBQYXlsb2FkIENNU1xuICAgKiBAcGFyYW0gdmFsdWUgLSBUaGUgSUQgdmFsdWUgdG8gbm9ybWFsaXplIChwcmltaXRpdmUsIG9iamVjdCwgb3IgYXJyYXkpXG4gICAqL1xuICBmdW5jdGlvbiBub3JtYWxpemVEb2N1bWVudElkcyhyZXN1bHQ6IFJlY29yZDxzdHJpbmcsIGFueT4sIG9yaWdpbmFsS2V5OiBzdHJpbmcsIGZpZWxkTmFtZTogc3RyaW5nLCB2YWx1ZTogYW55KTogdm9pZCB7XG4gICAgLy8gQ2FzZSAxOiBQcmltaXRpdmUgSUQgdmFsdWUgKHN0cmluZyBvciBudW1iZXIpXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgLy8gRm9yIEJldHRlckF1dGg6IEFsd2F5cyB1c2Ugc3RyaW5nIElEc1xuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IFN0cmluZyh2YWx1ZSlcbiAgICAgIC8vIEZvciBQYXlsb2FkOiBLZWVwIG9yaWdpbmFsIHR5cGVcbiAgICAgIHJlc3VsdFtmaWVsZE5hbWVdID0gdmFsdWVcbiAgICAgIHJldHVyblxuICAgIH1cblxuICAgIC8vIENhc2UgMjogT2JqZWN0IHdpdGggSUQgcHJvcGVydHlcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAnaWQnIGluIHZhbHVlKSB7XG4gICAgICAvLyBGb3IgQmV0dGVyQXV0aDogRXh0cmFjdCBhbmQgc3RyaW5naWZ5IHRoZSBJRFxuICAgICAgcmVzdWx0W29yaWdpbmFsS2V5XSA9IFN0cmluZyh2YWx1ZS5pZClcbiAgICAgIC8vIEZvciBQYXlsb2FkOiBFeHRyYWN0IElEIGJ1dCBwcmVzZXJ2ZSB0eXBlXG4gICAgICByZXN1bHRbZmllbGROYW1lXSA9IHZhbHVlLmlkXG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICAvLyBDYXNlIDM6IEFycmF5IG9mIElEcyBvciByZWZlcmVuY2VzXG4gICAgaWYgKEFycmF5LmlzQXJyYXkodmFsdWUpICYmIHZhbHVlLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIENoZWNrIGlmIGFycmF5IGNvbnRhaW5zIG9iamVjdHMgd2l0aCBJRCBwcm9wZXJ0aWVzXG4gICAgICBpZiAodmFsdWUuZXZlcnkoKGl0ZW0pID0+IHR5cGVvZiBpdGVtID09PSAnb2JqZWN0JyAmJiBpdGVtICE9PSBudWxsICYmICdpZCcgaW4gaXRlbSkpIHtcbiAgICAgICAgLy8gQXJyYXkgb2Ygb2JqZWN0cyB3aXRoIElEc1xuICAgICAgICByZXN1bHRbb3JpZ2luYWxLZXldID0gdmFsdWUubWFwKChpdGVtKSA9PiBTdHJpbmcoaXRlbS5pZCkpXG4gICAgICAgIHJlc3VsdFtmaWVsZE5hbWVdID0gdmFsdWUubWFwKChpdGVtKSA9PiBpdGVtLmlkKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gQXJyYXkgb2YgcHJpbWl0aXZlIElEc1xuICAgICAgICByZXN1bHRbb3JpZ2luYWxLZXldID0gdmFsdWUubWFwKChpdGVtKSA9PiBTdHJpbmcoaXRlbSkpXG4gICAgICAgIHJlc3VsdFtmaWVsZE5hbWVdID0gdmFsdWUubWFwKChpdGVtKSA9PiBpdGVtKVxuICAgICAgfVxuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgLy8gTm90ZTogSWYgdmFsdWUgZG9lc24ndCBtYXRjaCBhbnkgZXhwZWN0ZWQgZm9ybWF0LCBubyBjaGFuZ2VzIGFyZSBtYWRlXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBCZXR0ZXJBdXRoIG9wZXJhdG9yIHRvIHRoZSBlcXVpdmFsZW50IFBheWxvYWQgQ01TIHF1ZXJ5IG9wZXJhdG9yXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gbWFwcyBzdGFuZGFyZCBxdWVyeSBvcGVyYXRvcnMgZnJvbSBCZXR0ZXJBdXRoJ3MgZm9ybWF0IHRvXG4gICAqIHRoZSBzcGVjaWZpYyBmb3JtYXQgZXhwZWN0ZWQgYnkgUGF5bG9hZCBDTVMncyBxdWVyeSBlbmdpbmUuXG4gICAqXG4gICAqIEBwYXJhbSBvcGVyYXRvciAtIFRoZSBCZXR0ZXJBdXRoIG9wZXJhdG9yIHN0cmluZyAoZS5nLiwgJ2VxJywgJ2d0JywgJ2NvbnRhaW5zJylcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGJlIHVzZWQgd2l0aCB0aGUgb3BlcmF0b3JcbiAgICogQHJldHVybnMgQW4gb2JqZWN0IHdpdGggdGhlIFBheWxvYWQtY29tcGF0aWJsZSBvcGVyYXRvciBhbmQgdmFsdWVcbiAgICpcbiAgICogQGV4YW1wbGVcbiAgICogLy8gUmV0dXJucyB7IGVxdWFsczogJ3Rlc3RAZXhhbXBsZS5jb20nIH1cbiAgICogb3BlcmF0b3JUb1BheWxvYWQoJ2VxJywgJ3Rlc3RAZXhhbXBsZS5jb20nKVxuICAgKlxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBSZXR1cm5zIHsgZ3JlYXRlcl90aGFuOiAxMDAgfVxuICAgKiBvcGVyYXRvclRvUGF5bG9hZCgnZ3QnLCAxMDApXG4gICAqL1xuICBmdW5jdGlvbiBvcGVyYXRvclRvUGF5bG9hZChvcGVyYXRvcjogc3RyaW5nLCB2YWx1ZTogYW55KTogUmVjb3JkPHN0cmluZywgYW55PiB7XG4gICAgc3dpdGNoIChvcGVyYXRvcikge1xuICAgICAgY2FzZSAnZXEnOlxuICAgICAgICByZXR1cm4geyBlcXVhbHM6IHZhbHVlIH1cbiAgICAgIGNhc2UgJ25lJzpcbiAgICAgICAgcmV0dXJuIHsgbm90X2VxdWFsczogdmFsdWUgfVxuICAgICAgY2FzZSAnZ3QnOlxuICAgICAgICByZXR1cm4geyBncmVhdGVyX3RoYW46IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2d0ZSc6XG4gICAgICAgIHJldHVybiB7IGdyZWF0ZXJfdGhhbl9lcXVhbDogdmFsdWUgfVxuICAgICAgY2FzZSAnbHQnOlxuICAgICAgICByZXR1cm4geyBsZXNzX3RoYW46IHZhbHVlIH1cbiAgICAgIGNhc2UgJ2x0ZSc6XG4gICAgICAgIHJldHVybiB7IGxlc3NfdGhhbl9lcXVhbDogdmFsdWUgfVxuICAgICAgY2FzZSAnY29udGFpbnMnOlxuICAgICAgICByZXR1cm4geyBjb250YWluczogdmFsdWUgfVxuICAgICAgY2FzZSAnaW4nOlxuICAgICAgICByZXR1cm4geyBpbjogdmFsdWUgfVxuICAgICAgY2FzZSAnc3RhcnRzX3dpdGgnOlxuICAgICAgICByZXR1cm4geyBsaWtlOiBgJHt2YWx1ZX0lYCB9XG4gICAgICBjYXNlICdlbmRzX3dpdGgnOlxuICAgICAgICByZXR1cm4geyBsaWtlOiBgJSR7dmFsdWV9YCB9XG4gICAgICBkZWZhdWx0OlxuICAgICAgICAvLyBGYWxsIGJhY2sgdG8gZXF1YWxzIGZvciB1bnJlY29nbml6ZWQgb3BlcmF0b3JzXG4gICAgICAgIHJldHVybiB7IGVxdWFsczogdmFsdWUgfVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBDb252ZXJ0cyBhIHdoZXJlIGNsYXVzZSB2YWx1ZSB0byB0aGUgYXBwcm9wcmlhdGUgdHlwZSBiYXNlZCBvbiBmaWVsZCBuYW1lIGFuZCBJRCB0eXBlIGNvbmZpZ3VyYXRpb25cbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiBoYW5kbGVzIHR3byBtYWluIHNjZW5hcmlvczpcbiAgICogMS4gSUQgZmllbGQgY29udmVyc2lvbiAtIGVuc3VyZXMgSURzIG1hdGNoIHRoZSBkYXRhYmFzZSdzIGV4cGVjdGVkIHR5cGUgKG51bWJlciBvciBzdHJpbmcpXG4gICAqIDIuIE9iamVjdCB3aXRoIGVtYmVkZGVkIElEIC0gZXh0cmFjdHMgYW5kIGNvbnZlcnRzIHRoZSBJRCBwcm9wZXJ0eSBmcm9tIG9iamVjdHNcbiAgICpcbiAgICogQHBhcmFtIHZhbHVlIC0gVGhlIHZhbHVlIHRvIGNvbnZlcnQgKGNhbiBiZSBwcmltaXRpdmUsIG9iamVjdCB3aXRoIElELCBvciBhcnJheSlcbiAgICogQHBhcmFtIGZpZWxkTmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBmaWVsZCBiZWluZyBxdWVyaWVkXG4gICAqIEBwYXJhbSBpZFR5cGUgLSBUaGUgZXhwZWN0ZWQgSUQgdHlwZSBpbiB0aGUgZGF0YWJhc2VcbiAgICogQHJldHVybnMgVGhlIGNvbnZlcnRlZCB2YWx1ZSBhcHByb3ByaWF0ZSBmb3IgdGhlIGRhdGFiYXNlIHF1ZXJ5XG4gICAqL1xuICBmdW5jdGlvbiBjb252ZXJ0V2hlcmVWYWx1ZSh7IHZhbHVlLCBmaWVsZE5hbWUsIGlkVHlwZSB9OiB7IHZhbHVlOiBhbnk7IGZpZWxkTmFtZTogc3RyaW5nOyBpZFR5cGU6ICdudW1iZXInIHwgJ3RleHQnIH0pIHtcbiAgICAvLyBDaGVjayBpZiBmaWVsZCBpcyBhbiBJRCBmaWVsZCAoc3VwcG9ydGluZyBib3RoIE1vbmdvREItc3R5bGUgX2lkIGFuZCBzdGFuZGFyZCBpZClcbiAgICBpZiAoWydpZCcsICdfaWQnXS5pbmNsdWRlcyhmaWVsZE5hbWUpKSB7XG4gICAgICAvLyBDYXNlIDE6IFZhbHVlIGlzIGFuIG9iamVjdCBjb250YWluaW5nIGFuIElEIHByb3BlcnR5XG4gICAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnb2JqZWN0JyAmJiB2YWx1ZSAhPT0gbnVsbCAmJiAnaWQnIGluIHZhbHVlKSB7XG4gICAgICAgIC8vIEV4dHJhY3QgSUQgZnJvbSBvYmplY3RcbiAgICAgICAgY29uc3QgaWQgPSB2YWx1ZS5pZFxuXG4gICAgICAgIC8vIFVzZSB0eXBlIGNvbnZlcnNpb24gYmFzZWQgb24gZGF0YWJhc2UgY29uZmlndXJhdGlvblxuICAgICAgICBpZiAoaWRUeXBlID09PSAnbnVtYmVyJyAmJiB0eXBlb2YgaWQgPT09ICdzdHJpbmcnKSB7XG4gICAgICAgICAgY29uc3QgbnVtSWQgPSBOdW1iZXIoaWQpXG4gICAgICAgICAgcmV0dXJuICFpc05hTihudW1JZCkgPyBudW1JZCA6IGlkXG4gICAgICAgIH1cblxuICAgICAgICBpZiAoaWRUeXBlID09PSAndGV4dCcgJiYgdHlwZW9mIGlkID09PSAnbnVtYmVyJykge1xuICAgICAgICAgIHJldHVybiBTdHJpbmcoaWQpXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gaWRcbiAgICAgIH1cbiAgICAgIC8vIENhc2UgMjogVmFsdWUgaXMgYSBzdGFuZGFsb25lIElEIHRoYXQgbmVlZHMgdHlwZSBjb252ZXJzaW9uXG4gICAgICAvLyBDb252ZXJ0IHN0cmluZyBJRCB0byBudW1iZXIgaWYgZGF0YWJhc2UgZXhwZWN0cyBudW1lcmljIElEc1xuICAgICAgaWYgKGlkVHlwZSA9PT0gJ251bWJlcicgJiYgdHlwZW9mIHZhbHVlID09PSAnc3RyaW5nJyAmJiAhaXNOYU4oTnVtYmVyKHZhbHVlKSkpIHtcbiAgICAgICAgcmV0dXJuIE51bWJlcih2YWx1ZSlcbiAgICAgIH1cbiAgICAgIC8vIENvbnZlcnQgbnVtZXJpYyBJRCB0byBzdHJpbmcgaWYgZGF0YWJhc2UgZXhwZWN0cyB0ZXh0IElEc1xuICAgICAgZWxzZSBpZiAoaWRUeXBlID09PSAndGV4dCcgJiYgdHlwZW9mIHZhbHVlID09PSAnbnVtYmVyJykge1xuICAgICAgICByZXR1cm4gU3RyaW5nKHZhbHVlKVxuICAgICAgfVxuICAgICAgcmV0dXJuIHZhbHVlXG4gICAgfVxuXG4gICAgLy8gRm9yIG5vbi1JRCBmaWVsZHMsIHJldHVybiB0aGUgdmFsdWUgdW5jaGFuZ2VkXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgQmV0dGVyIEF1dGggd2hlcmUgY2xhdXNlcyB0byBQYXlsb2FkIENNUyBjb21wYXRpYmxlIHdoZXJlIGNvbmRpdGlvbnNcbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB0cmFuc2Zvcm1zIHRoZSBCZXR0ZXIgQXV0aCBxdWVyeSBmb3JtYXQgaW50byBQYXlsb2FkJ3MgcXVlcnkgZm9ybWF0LFxuICAgKiBoYW5kbGluZyBmaWVsZCBuYW1lIG1hcHBpbmcsIHZhbHVlIHR5cGUgY29udmVyc2lvbiwgYW5kIGxvZ2ljYWwgb3BlcmF0b3JzIChBTkQvT1IpLlxuICAgKlxuICAgKiBUaGUgZnVuY3Rpb24gaGFuZGxlcyB0aHJlZSBtYWluIGNhc2VzOlxuICAgKiAxLiBFbXB0eSBvciB1bmRlZmluZWQgd2hlcmUgY2xhdXNlIC0gcmV0dXJucyBlbXB0eSBvYmplY3RcbiAgICogMi4gU2luZ2xlIGNvbmRpdGlvbiAtIGNvbnZlcnRzIHRvIGEgc2ltcGxlIGZpZWxkLXZhbHVlIHBhaXJcbiAgICogMy4gTXVsdGlwbGUgY29uZGl0aW9ucyAtIGdyb3VwcyBieSBBTkQvT1IgY29ubmVjdG9ycyBhbmQgYnVpbGRzIGEgY29tcGxleCBxdWVyeVxuICAgKlxuICAgKiBAcGFyYW0gaWRUeXBlIC0gVGhlIGRhdGFiYXNlIElEIHR5cGUgKCdudW1iZXInIG9yICd0ZXh0JylcbiAgICogQHBhcmFtIG1vZGVsIC0gVGhlIG1vZGVsL2NvbGxlY3Rpb24gbmFtZSB0byBxdWVyeVxuICAgKiBAcGFyYW0gd2hlcmUgLSBBcnJheSBvZiBCZXR0ZXIgQXV0aCB3aGVyZSBjb25kaXRpb25zXG4gICAqIEByZXR1cm5zIEEgUGF5bG9hZC1jb21wYXRpYmxlIHdoZXJlIGNsYXVzZSBvYmplY3RcbiAgICovXG4gIGZ1bmN0aW9uIGNvbnZlcnRXaGVyZUNsYXVzZSh7IGlkVHlwZSwgbW9kZWwsIHdoZXJlIH06IHsgaWRUeXBlOiAnbnVtYmVyJyB8ICd0ZXh0JzsgbW9kZWw6IHN0cmluZzsgd2hlcmU/OiBXaGVyZVtdIH0pOiBQYXlsb2FkV2hlcmUge1xuICAgIC8vIEhhbmRsZSBlbXB0eSB3aGVyZSBjbGF1c2VcbiAgICBpZiAoIXdoZXJlKSByZXR1cm4ge31cblxuICAgIC8vIEhhbmRsZSBzaW5nbGUgY29uZGl0aW9uIGNhc2UgZm9yIG9wdGltaXphdGlvblxuICAgIGlmICh3aGVyZS5sZW5ndGggPT09IDEpIHtcbiAgICAgIGNvbnN0IHcgPSB3aGVyZVswXVxuICAgICAgaWYgKCF3KSB7XG4gICAgICAgIHJldHVybiB7fVxuICAgICAgfVxuXG4gICAgICAvLyBNYXAgZmllbGQgbmFtZSBhY2NvcmRpbmcgdG8gc2NoZW1hIGFuZCBjb252ZXJ0IHZhbHVlIHRvIGFwcHJvcHJpYXRlIHR5cGVcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgdy5maWVsZClcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFdoZXJlVmFsdWUoe1xuICAgICAgICB2YWx1ZTogdy52YWx1ZSxcbiAgICAgICAgZmllbGROYW1lLFxuICAgICAgICBpZFR5cGVcbiAgICAgIH0pXG5cbiAgICAgIC8vIENyZWF0ZSB0aGUgUGF5bG9hZCB3aGVyZSBjb25kaXRpb24gd2l0aCBwcm9wZXIgb3BlcmF0b3JcbiAgICAgIGNvbnN0IHJlcyA9IHtcbiAgICAgICAgW2ZpZWxkTmFtZV06IG9wZXJhdG9yVG9QYXlsb2FkKHcub3BlcmF0b3IgPz8gJycsIHZhbHVlKVxuICAgICAgfVxuXG4gICAgICByZXR1cm4gcmVzXG4gICAgfVxuXG4gICAgLy8gSGFuZGxlIG11bHRpcGxlIGNvbmRpdGlvbnMgYnkgc2VwYXJhdGluZyBBTkQvT1IgY2xhdXNlc1xuICAgIC8vIERlZmF1bHQgdG8gQU5EIGlmIG5vIGNvbm5lY3RvciBpcyBzcGVjaWZpZWRcbiAgICBjb25zdCBhbmQgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnQU5EJyB8fCAhdy5jb25uZWN0b3IpXG4gICAgY29uc3Qgb3IgPSB3aGVyZS5maWx0ZXIoKHcpID0+IHcuY29ubmVjdG9yID09PSAnT1InKVxuXG4gICAgLy8gUHJvY2VzcyBBTkQgY29uZGl0aW9uc1xuICAgIGNvbnN0IGFuZENsYXVzZSA9IGFuZC5tYXAoKHcpID0+IHtcbiAgICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgdy5maWVsZClcbiAgICAgIGNvbnN0IHZhbHVlID0gY29udmVydFdoZXJlVmFsdWUoe1xuICAgICAgICB2YWx1ZTogdy52YWx1ZSxcbiAgICAgICAgZmllbGROYW1lLFxuICAgICAgICBpZFR5cGVcbiAgICAgIH0pXG4gICAgICByZXR1cm4ge1xuICAgICAgICBbZmllbGROYW1lXTogb3BlcmF0b3JUb1BheWxvYWQody5vcGVyYXRvciA/PyAnJywgdmFsdWUpXG4gICAgICB9XG4gICAgfSlcblxuICAgIC8vIFByb2Nlc3MgT1IgY29uZGl0aW9uc1xuICAgIGNvbnN0IG9yQ2xhdXNlID0gb3IubWFwKCh3KSA9PiB7XG4gICAgICBjb25zdCBmaWVsZE5hbWUgPSBnZXRGaWVsZE5hbWUobW9kZWwsIHcuZmllbGQpXG4gICAgICBjb25zdCB2YWx1ZSA9IGNvbnZlcnRXaGVyZVZhbHVlKHtcbiAgICAgICAgdmFsdWU6IHcudmFsdWUsXG4gICAgICAgIGZpZWxkTmFtZSxcbiAgICAgICAgaWRUeXBlXG4gICAgICB9KVxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgW2ZpZWxkTmFtZV06IG9wZXJhdG9yVG9QYXlsb2FkKHcub3BlcmF0b3IgPz8gJycsIHZhbHVlKVxuICAgICAgfVxuICAgIH0pXG5cbiAgICAvLyBDb21iaW5lIEFORCBhbmQgT1IgY2xhdXNlcyBpbnRvIGZpbmFsIFBheWxvYWQgd2hlcmUgb2JqZWN0XG4gICAgLy8gT25seSBpbmNsdWRlIG5vbi1lbXB0eSBjbGF1c2UgYXJyYXlzXG4gICAgcmV0dXJuIHtcbiAgICAgIC4uLihhbmRDbGF1c2UubGVuZ3RoID8geyBBTkQ6IGFuZENsYXVzZSB9IDoge30pLFxuICAgICAgLi4uKG9yQ2xhdXNlLmxlbmd0aCA/IHsgT1I6IG9yQ2xhdXNlIH0gOiB7fSlcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydHMgYSBiZXR0ZXItYXV0aCBzZWxlY3QgYXJyYXkgdG8gYSBQYXlsb2FkIHNlbGVjdCBvYmplY3RcbiAgICpcbiAgICogVGhpcyBmdW5jdGlvbiB0cmFuc2Zvcm1zIHRoZSBiZXR0ZXItYXV0aCBzZWxlY3QgYXJyYXkgKHdoaWNoIGNvbnRhaW5zIGZpZWxkIG5hbWVzKVxuICAgKiBpbnRvIHRoZSBmb3JtYXQgZXhwZWN0ZWQgYnkgUGF5bG9hZCBDTVMncyBxdWVyeSBBUEkgKGFuIG9iamVjdCB3aXRoIGZpZWxkIG5hbWVzIGFzIGtleXNcbiAgICogYW5kIGJvb2xlYW4gdHJ1ZSBhcyB2YWx1ZXMpLlxuICAgKlxuICAgKiBJdCBhbHNvIGhhbmRsZXMgZmllbGQgbmFtZSBtYXBwaW5nIGJldHdlZW4gYmV0dGVyLWF1dGggc2NoZW1hIGFuZCBQYXlsb2FkIGNvbGxlY3Rpb25zXG4gICAqIGJ5IHVzaW5nIHRoZSBnZXRGaWVsZE5hbWUgaGVscGVyIHRvIHJlc29sdmUgdGhlIGNvcnJlY3QgZmllbGQgbmFtZXMuXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbC9jb2xsZWN0aW9uIG5hbWUgdG8gZ2V0IGZpZWxkIG1hcHBpbmdzIGZyb21cbiAgICogQHBhcmFtIHNlbGVjdCAtIE9wdGlvbmFsIGFycmF5IG9mIGZpZWxkIG5hbWVzIHRvIHNlbGVjdFxuICAgKiBAcmV0dXJucyBBIFBheWxvYWQtY29tcGF0aWJsZSBzZWxlY3Qgb2JqZWN0IG9yIHVuZGVmaW5lZCBpZiBubyBmaWVsZHMgdG8gc2VsZWN0XG4gICAqIEBleGFtcGxlXG4gICAqIC8vIElucHV0OiBbJ2VtYWlsJywgJ25hbWUnXVxuICAgKiAvLyBPdXRwdXQ6IHsgZW1haWw6IHRydWUsIG5hbWU6IHRydWUgfVxuICAgKi9cbiAgZnVuY3Rpb24gY29udmVydFNlbGVjdChtb2RlbDogc3RyaW5nLCBzZWxlY3Q/OiBzdHJpbmdbXSkge1xuICAgIC8vIFJldHVybiB1bmRlZmluZWQgaWYgc2VsZWN0IGlzIGVtcHR5IG9yIG5vdCBwcm92aWRlZFxuICAgIGlmICghc2VsZWN0IHx8IHNlbGVjdC5sZW5ndGggPT09IDApIHJldHVybiB1bmRlZmluZWRcblxuICAgIC8vIFRyYW5zZm9ybSB0aGUgYXJyYXkgb2YgZmllbGQgbmFtZXMgaW50byBhIFBheWxvYWQgc2VsZWN0IG9iamVjdFxuICAgIC8vIHdoaWxlIGFsc28gbWFwcGluZyBhbnkgZmllbGQgbmFtZXMgdGhhdCBtaWdodCBiZSBkaWZmZXJlbnQgaW4gUGF5bG9hZFxuICAgIHJldHVybiBzZWxlY3QucmVkdWNlKChhY2MsIGZpZWxkKSA9PiAoeyAuLi5hY2MsIFtnZXRGaWVsZE5hbWUobW9kZWwsIGZpZWxkKV06IHRydWUgfSksIHt9KVxuICB9XG5cbiAgLyoqXG4gICAqIENvbnZlcnRzIGEgYmV0dGVyLWF1dGggc29ydCBvYmplY3QgdG8gYSBQYXlsb2FkIHNvcnQgc3RyaW5nXG4gICAqXG4gICAqIFRoaXMgZnVuY3Rpb24gdHJhbnNmb3JtcyB0aGUgYmV0dGVyLWF1dGggc29ydCBvYmplY3QgKHdoaWNoIGNvbnRhaW5zIGZpZWxkIG5hbWUgYW5kIGRpcmVjdGlvbilcbiAgICogaW50byB0aGUgZm9ybWF0IGV4cGVjdGVkIGJ5IFBheWxvYWQgQ01TJ3MgcXVlcnkgQVBJIChhIHN0cmluZyB3aXRoIG9wdGlvbmFsICctJyBwcmVmaXggZm9yIGRlc2NlbmRpbmcgb3JkZXIpLlxuICAgKlxuICAgKiBJdCBhbHNvIGhhbmRsZXMgZmllbGQgbmFtZSBtYXBwaW5nIGJldHdlZW4gYmV0dGVyLWF1dGggc2NoZW1hIGFuZCBQYXlsb2FkIGNvbGxlY3Rpb25zXG4gICAqIGJ5IHVzaW5nIHRoZSBnZXRGaWVsZE5hbWUgaGVscGVyIHRvIHJlc29sdmUgdGhlIGNvcnJlY3QgZmllbGQgbmFtZXMuXG4gICAqXG4gICAqIEBwYXJhbSBtb2RlbCAtIFRoZSBtb2RlbC9jb2xsZWN0aW9uIG5hbWUgdG8gZ2V0IGZpZWxkIG1hcHBpbmdzIGZyb21cbiAgICogQHBhcmFtIHNvcnRCeSAtIE9wdGlvbmFsIG9iamVjdCBjb250YWluaW5nIGZpZWxkIG5hbWUgYW5kIHNvcnQgZGlyZWN0aW9uXG4gICAqIEByZXR1cm5zIEEgUGF5bG9hZC1jb21wYXRpYmxlIHNvcnQgc3RyaW5nIG9yIHVuZGVmaW5lZCBpZiBubyBzb3J0IHNwZWNpZmllZFxuICAgKiBAZXhhbXBsZVxuICAgKiAvLyBJbnB1dDogeyBmaWVsZDogJ2VtYWlsJywgZGlyZWN0aW9uOiAnZGVzYycgfVxuICAgKiAvLyBPdXRwdXQ6ICctZW1haWwnXG4gICAqIC8vIElucHV0OiB7IGZpZWxkOiAnY3JlYXRlZEF0JywgZGlyZWN0aW9uOiAnYXNjJyB9XG4gICAqIC8vIE91dHB1dDogJ2NyZWF0ZWRBdCdcbiAgICovXG4gIGZ1bmN0aW9uIGNvbnZlcnRTb3J0KG1vZGVsOiBzdHJpbmcsIHNvcnRCeT86IHsgZmllbGQ6IHN0cmluZzsgZGlyZWN0aW9uOiAnYXNjJyB8ICdkZXNjJyB9KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICBpZiAoIXNvcnRCeSkgcmV0dXJuIHVuZGVmaW5lZFxuICAgIGNvbnN0IGZpZWxkTmFtZSA9IGdldEZpZWxkTmFtZShtb2RlbCwgc29ydEJ5LmZpZWxkKVxuICAgIGNvbnN0IHByZWZpeCA9IHNvcnRCeS5kaXJlY3Rpb24gPT09ICdkZXNjJyA/ICctJyA6ICcnXG4gICAgcmV0dXJuIGAke3ByZWZpeH0ke2ZpZWxkTmFtZX1gXG4gIH1cblxuICByZXR1cm4ge1xuICAgIGdldEZpZWxkTmFtZSxcbiAgICBnZXRDb2xsZWN0aW9uU2x1ZyxcbiAgICBzaW5nbGVJZFF1ZXJ5LFxuICAgIHRyYW5zZm9ybUlucHV0LFxuICAgIHRyYW5zZm9ybU91dHB1dCxcbiAgICBjb252ZXJ0V2hlcmVDbGF1c2UsXG4gICAgY29udmVydFNlbGVjdCxcbiAgICBjb252ZXJ0U29ydFxuICB9XG59XG4iXSwibmFtZXMiOlsiZ2V0QXV0aFRhYmxlcyIsImNyZWF0ZVRyYW5zZm9ybSIsIm9wdGlvbnMiLCJlbmFibGVEZWJ1Z0xvZ3MiLCJzY2hlbWEiLCJkZWJ1Z0xvZyIsIm1lc3NhZ2UiLCJjb25zb2xlIiwibG9nIiwiZ2V0Q29sbGVjdGlvblNsdWciLCJtb2RlbCIsImNvbGxlY3Rpb24iLCJtb2RlbE5hbWUiLCJyZXNvbHZlZFNsdWciLCJnZXRGaWVsZE5hbWUiLCJmaWVsZCIsImluY2x1ZGVzIiwiZmllbGREZWZpbml0aW9uIiwiZmllbGRzIiwiZmllbGROYW1lIiwib3JpZ2luYWxGaWVsZCIsImlzUmVsYXRpb25zaGlwRmllbGQiLCJmaWVsZEtleSIsInNjaGVtYUZpZWxkcyIsInJlZmVyZW5jZXMiLCJ1bmRlZmluZWQiLCJpc0RhdGVGaWVsZCIsInZhbHVlIiwiaXNOYU4iLCJEYXRlIiwicGFyc2UiLCJzaW5nbGVJZFF1ZXJ5Iiwid2hlcmUiLCJzb21lIiwiaWRGaWVsZCIsImNvbmRpdGlvbiIsIkFycmF5IiwiaXNBcnJheSIsImVxdWFscyIsImNvbnRhaW5zIiwibGVuZ3RoIiwibm9ybWFsaXplRGF0YSIsImtleSIsImlzUmVsYXRlZEZpZWxkIiwiaWRUeXBlIiwicGFyc2VkIiwicGFyc2VJbnQiLCJvcmlnaW5hbCIsImNvbnZlcnRlZCIsInN0cmluZ0lkIiwiU3RyaW5nIiwibWFwIiwiaWQiLCJ0cmFuc2Zvcm1JbnB1dCIsImRhdGEiLCJ0cmFuc2Zvcm1lZERhdGEiLCJPYmplY3QiLCJlbnRyaWVzIiwiZm9yRWFjaCIsInNjaGVtYUZpZWxkTmFtZSIsIm5vcm1hbGl6ZWREYXRhIiwidGFyZ2V0RmllbGROYW1lIiwidHJhbnNmb3JtT3V0cHV0IiwiZG9jIiwicmVzdWx0IiwicmVsYXRpb25zaGlwRmllbGRzIiwiZnJvbUVudHJpZXMiLCJmaWx0ZXIiLCJvcmlnaW5hbFJlbGF0ZWRGaWVsZEtleSIsImtleXMiLCJmaW5kIiwiayIsIm5vcm1hbGl6ZURvY3VtZW50SWRzIiwib3JpZ2luYWxLZXkiLCJldmVyeSIsIml0ZW0iLCJvcGVyYXRvclRvUGF5bG9hZCIsIm9wZXJhdG9yIiwibm90X2VxdWFscyIsImdyZWF0ZXJfdGhhbiIsImdyZWF0ZXJfdGhhbl9lcXVhbCIsImxlc3NfdGhhbiIsImxlc3NfdGhhbl9lcXVhbCIsImluIiwibGlrZSIsImNvbnZlcnRXaGVyZVZhbHVlIiwibnVtSWQiLCJOdW1iZXIiLCJjb252ZXJ0V2hlcmVDbGF1c2UiLCJ3IiwicmVzIiwiYW5kIiwiY29ubmVjdG9yIiwib3IiLCJhbmRDbGF1c2UiLCJvckNsYXVzZSIsIkFORCIsIk9SIiwiY29udmVydFNlbGVjdCIsInNlbGVjdCIsInJlZHVjZSIsImFjYyIsImNvbnZlcnRTb3J0Iiwic29ydEJ5IiwicHJlZml4IiwiZGlyZWN0aW9uIl0sIm1hcHBpbmdzIjoiQUFBQSxTQUFvQ0EsYUFBYSxRQUFRLGlCQUFnQjtBQUl6RSxPQUFPLE1BQU1DLGtCQUFrQixDQUFDQyxTQUE0QkM7SUFDMUQsTUFBTUMsU0FBU0osY0FBY0U7SUFFN0IsU0FBU0csU0FBU0MsT0FBYztRQUM5QixJQUFJSCxp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
|