@rockcarver/frodo-lib 2.0.0-3 → 2.0.0-4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (149) hide show
  1. package/CHANGELOG.md +5 -1
  2. package/cjs/api/AgentApi.js +64 -16
  3. package/cjs/api/AgentApi.js.map +1 -1
  4. package/cjs/api/ApiTypes.js +0 -55
  5. package/cjs/api/ApiTypes.js.map +1 -1
  6. package/cjs/api/BaseApi.js +21 -11
  7. package/cjs/api/BaseApi.js.map +1 -1
  8. package/cjs/api/cloud/SecretsApi.js +7 -14
  9. package/cjs/api/cloud/SecretsApi.js.map +1 -1
  10. package/cjs/api/cloud/SecretsApi.test.js.map +1 -1
  11. package/cjs/ops/AdminOps.js +254 -60
  12. package/cjs/ops/AdminOps.js.map +1 -1
  13. package/cjs/ops/AgentOps.js +352 -108
  14. package/cjs/ops/AgentOps.js.map +1 -1
  15. package/cjs/ops/AuthenticateOps.js +253 -60
  16. package/cjs/ops/AuthenticateOps.js.map +1 -1
  17. package/cjs/ops/CirclesOfTrustOps.js +16 -4
  18. package/cjs/ops/CirclesOfTrustOps.js.map +1 -1
  19. package/cjs/ops/ConnectionProfileOps.js +163 -40
  20. package/cjs/ops/ConnectionProfileOps.js.map +1 -1
  21. package/cjs/ops/EmailTemplateOps.js +7 -1
  22. package/cjs/ops/EmailTemplateOps.js.map +1 -1
  23. package/cjs/ops/IdpOps.js +55 -12
  24. package/cjs/ops/IdpOps.js.map +1 -1
  25. package/cjs/ops/JourneyOps.js +645 -136
  26. package/cjs/ops/JourneyOps.js.map +1 -1
  27. package/cjs/ops/NodeOps.js +96 -24
  28. package/cjs/ops/NodeOps.js.map +1 -1
  29. package/cjs/ops/OAuth2ClientOps.js +45 -11
  30. package/cjs/ops/OAuth2ClientOps.js.map +1 -1
  31. package/cjs/ops/OpsTypes.js +0 -23
  32. package/cjs/ops/OpsTypes.js.map +1 -1
  33. package/cjs/ops/OrganizationOps.js +44 -10
  34. package/cjs/ops/OrganizationOps.js.map +1 -1
  35. package/cjs/ops/PolicyOps.js +86 -24
  36. package/cjs/ops/PolicyOps.js.map +1 -1
  37. package/cjs/ops/PolicySetOps.js +72 -18
  38. package/cjs/ops/PolicySetOps.js.map +1 -1
  39. package/cjs/ops/ResourceTypeOps.js +24 -6
  40. package/cjs/ops/ResourceTypeOps.js.map +1 -1
  41. package/cjs/ops/Saml2Ops.js +120 -33
  42. package/cjs/ops/Saml2Ops.js.map +1 -1
  43. package/cjs/ops/Saml2Ops.test.js.map +1 -1
  44. package/cjs/ops/ScriptOps.js +73 -17
  45. package/cjs/ops/ScriptOps.js.map +1 -1
  46. package/cjs/ops/ServiceOps.js +152 -35
  47. package/cjs/ops/ServiceOps.js.map +1 -1
  48. package/cjs/ops/ThemeOps.js +20 -5
  49. package/cjs/ops/ThemeOps.js.map +1 -1
  50. package/cjs/ops/cloud/FeatureOps.js +4 -1
  51. package/cjs/ops/cloud/FeatureOps.js.map +1 -1
  52. package/cjs/ops/cloud/SecretsOps.js.map +1 -1
  53. package/cjs/ops/cloud/ServiceAccountOps.js +24 -6
  54. package/cjs/ops/cloud/ServiceAccountOps.js.map +1 -1
  55. package/cjs/ops/cloud/StartupOps.js +55 -11
  56. package/cjs/ops/cloud/StartupOps.js.map +1 -1
  57. package/cjs/ops/utils/Console.js +47 -22
  58. package/cjs/ops/utils/Console.js.map +1 -1
  59. package/cjs/ops/utils/DataProtection.js +12 -5
  60. package/cjs/ops/utils/DataProtection.js.map +1 -1
  61. package/cjs/ops/utils/DataProtection.test.js.map +1 -1
  62. package/cjs/ops/utils/ExportImportUtils.js +15 -8
  63. package/cjs/ops/utils/ExportImportUtils.js.map +1 -1
  64. package/cjs/ops/utils/ScriptValidationUtils.js +33 -8
  65. package/cjs/ops/utils/ScriptValidationUtils.js.map +1 -1
  66. package/cjs/ops/utils/ScriptValidationUtils.test.js.map +1 -1
  67. package/cjs/utils/SetupPollyForFrodoLib.js +67 -19
  68. package/cjs/utils/SetupPollyForFrodoLib.js.map +1 -1
  69. package/esm/api/AgentApi.mjs +64 -16
  70. package/esm/api/ApiTypes.mjs +1 -50
  71. package/esm/api/BaseApi.mjs +21 -11
  72. package/esm/api/cloud/SecretsApi.mjs +0 -5
  73. package/esm/api/cloud/SecretsApi.test.mjs +3 -3
  74. package/esm/ops/AdminOps.mjs +254 -60
  75. package/esm/ops/AgentOps.mjs +352 -104
  76. package/esm/ops/AuthenticateOps.mjs +253 -60
  77. package/esm/ops/CirclesOfTrustOps.mjs +16 -4
  78. package/esm/ops/ConnectionProfileOps.mjs +163 -40
  79. package/esm/ops/EmailTemplateOps.mjs +5 -0
  80. package/esm/ops/IdpOps.mjs +55 -12
  81. package/esm/ops/JourneyOps.mjs +639 -132
  82. package/esm/ops/NodeOps.mjs +90 -19
  83. package/esm/ops/OAuth2ClientOps.mjs +45 -11
  84. package/esm/ops/OpsTypes.mjs +1 -22
  85. package/esm/ops/OrganizationOps.mjs +44 -10
  86. package/esm/ops/PolicyOps.mjs +86 -24
  87. package/esm/ops/PolicySetOps.mjs +72 -18
  88. package/esm/ops/ResourceTypeOps.mjs +24 -6
  89. package/esm/ops/Saml2Ops.mjs +120 -33
  90. package/esm/ops/Saml2Ops.test.mjs +10 -11
  91. package/esm/ops/ScriptOps.mjs +73 -17
  92. package/esm/ops/ServiceOps.mjs +152 -35
  93. package/esm/ops/ThemeOps.mjs +20 -5
  94. package/esm/ops/cloud/FeatureOps.mjs +4 -1
  95. package/esm/ops/cloud/ServiceAccountOps.mjs +24 -6
  96. package/esm/ops/cloud/StartupOps.mjs +55 -11
  97. package/esm/ops/utils/Console.mjs +33 -9
  98. package/esm/ops/utils/DataProtection.mjs +9 -2
  99. package/esm/ops/utils/DataProtection.test.mjs +8 -2
  100. package/esm/ops/utils/ExportImportUtils.mjs +15 -8
  101. package/esm/ops/utils/ScriptValidationUtils.mjs +30 -8
  102. package/esm/ops/utils/ScriptValidationUtils.test.mjs +14 -3
  103. package/esm/utils/SetupPollyForFrodoLib.mjs +64 -18
  104. package/package.json +1 -1
  105. package/types/api/AgentApi.d.ts +6 -6
  106. package/types/api/AgentApi.d.ts.map +1 -1
  107. package/types/api/ApiTypes.d.ts +12 -49
  108. package/types/api/ApiTypes.d.ts.map +1 -1
  109. package/types/api/BaseApi.d.ts.map +1 -1
  110. package/types/api/cloud/SecretsApi.d.ts +1 -4
  111. package/types/api/cloud/SecretsApi.d.ts.map +1 -1
  112. package/types/ops/AdminOps.d.ts.map +1 -1
  113. package/types/ops/AgentOps.d.ts +3 -6
  114. package/types/ops/AgentOps.d.ts.map +1 -1
  115. package/types/ops/AuthenticateOps.d.ts.map +1 -1
  116. package/types/ops/CirclesOfTrustOps.d.ts.map +1 -1
  117. package/types/ops/ConnectionProfileOps.d.ts.map +1 -1
  118. package/types/ops/EmailTemplateOps.d.ts +4 -0
  119. package/types/ops/EmailTemplateOps.d.ts.map +1 -1
  120. package/types/ops/IdpOps.d.ts.map +1 -1
  121. package/types/ops/JourneyOps.d.ts +10 -4
  122. package/types/ops/JourneyOps.d.ts.map +1 -1
  123. package/types/ops/NodeOps.d.ts +10 -4
  124. package/types/ops/NodeOps.d.ts.map +1 -1
  125. package/types/ops/OAuth2ClientOps.d.ts.map +1 -1
  126. package/types/ops/OpsTypes.d.ts +2 -12
  127. package/types/ops/OpsTypes.d.ts.map +1 -1
  128. package/types/ops/OrganizationOps.d.ts.map +1 -1
  129. package/types/ops/PolicyOps.d.ts.map +1 -1
  130. package/types/ops/PolicySetOps.d.ts.map +1 -1
  131. package/types/ops/ResourceTypeOps.d.ts.map +1 -1
  132. package/types/ops/Saml2Ops.d.ts.map +1 -1
  133. package/types/ops/ScriptOps.d.ts.map +1 -1
  134. package/types/ops/ServiceOps.d.ts.map +1 -1
  135. package/types/ops/ThemeOps.d.ts.map +1 -1
  136. package/types/ops/cloud/FeatureOps.d.ts.map +1 -1
  137. package/types/ops/cloud/SecretsOps.d.ts +1 -1
  138. package/types/ops/cloud/SecretsOps.d.ts.map +1 -1
  139. package/types/ops/cloud/ServiceAccountOps.d.ts.map +1 -1
  140. package/types/ops/cloud/StartupOps.d.ts.map +1 -1
  141. package/types/ops/utils/Console.d.ts +34 -7
  142. package/types/ops/utils/Console.d.ts.map +1 -1
  143. package/types/ops/utils/DataProtection.d.ts +5 -1
  144. package/types/ops/utils/DataProtection.d.ts.map +1 -1
  145. package/types/ops/utils/ExportImportUtils.d.ts.map +1 -1
  146. package/types/ops/utils/ScriptValidationUtils.d.ts +14 -4
  147. package/types/ops/utils/ScriptValidationUtils.d.ts.map +1 -1
  148. package/types/utils/SetupPollyForFrodoLib.d.ts +5 -1
  149. package/types/utils/SetupPollyForFrodoLib.d.ts.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ops/cloud/StartupOps.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,MAAM,oBAAoB,CAAC;AAEvC,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,KAAK,EAAE,KAAK,CAAC;gBACD,KAAK,EAAE,KAAK;IAIxB;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;;;OAKG;IACG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,MAAuB;CAOnE;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,EACpC,KAAK,GACN,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,OAAO,CAAC,OAAO,CAAC,CA8BnB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EACjC,IAAI,EACJ,OAAwB,EACxB,KAAK,GACN,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACd,oBAoEA","file":"StartupOps.d.ts","sourcesContent":["import {\n createProgressIndicator,\n updateProgressIndicator,\n stopProgressIndicator,\n} from '../utils/Console';\nimport { getSecrets } from '../../api/cloud/SecretsApi';\nimport {\n getStatus,\n initiateRestart,\n RestartStatus,\n} from '../../api/cloud/StartupApi';\nimport { getVariables } from '../../api/cloud/VariablesApi';\nimport State from '../../shared/State';\n\nexport default class StartupOps {\n state: State;\n constructor(state: State) {\n this.state = state;\n }\n\n /**\n * Check for updates that need applying\n * @returns {Promise<Updates>} true if there are updates that need to be applied, false otherwise\n */\n async checkForUpdates(): Promise<Updates> {\n return checkForUpdates({ state: this.state });\n }\n\n /**\n * Apply updates\n * @param {boolean} wait wait for the operation to complete or not\n * @param {number} timeout timeout in milliseconds\n * @returns {Promise<boolean>} true if successful, false otherwise\n */\n async applyUpdates(wait: boolean, timeout: number = 10 * 60 * 1000) {\n return applyUpdates({\n wait,\n timeout,\n state: this.state,\n });\n }\n}\n\n/**\n * Updates that need to be applied.\n */\nexport interface Updates {\n /**\n * Array of secrets that need applying\n */\n secrets?: unknown[];\n /**\n * Array of variables that need applying\n */\n variables?: unknown[];\n}\n\n/**\n * Check for updates that need applying\n * @returns {Promise<boolean>} true if there are updates that need to be applied, false otherwise\n */\nexport async function checkForUpdates({\n state,\n}: {\n state: State;\n}): Promise<Updates> {\n const updates: Updates = { secrets: [], variables: [] };\n createProgressIndicator(\n undefined,\n `Checking for updates to apply...`,\n 'indeterminate'\n );\n try {\n updates.secrets = (await getSecrets({ state })).result.filter(\n (secret: { loaded: unknown }) => !secret.loaded\n );\n updates.variables = (await getVariables({ state })).result.filter(\n (variable: { loaded: unknown }) => !variable.loaded\n );\n } catch (error) {\n stopProgressIndicator(\n `Error: ${error.response.data.code} - ${error.response.data.message}`,\n 'fail'\n );\n }\n const updateCount = updates.secrets?.length + updates.variables?.length || 0;\n if (updateCount > 0) {\n stopProgressIndicator(\n `${updateCount} update(s) need to be applied`,\n 'success'\n );\n } else {\n stopProgressIndicator(`No updates need to be applied`, 'success');\n }\n return updates;\n}\n\n/**\n * Apply updates\n * @param {boolean} wait wait for the operation to complete or not\n * @param {number} timeout timeout in milliseconds\n * @returns {Promise<boolean>} true if successful, false otherwise\n */\nexport async function applyUpdates({\n wait,\n timeout = 10 * 60 * 1000,\n state,\n}: {\n wait: boolean;\n timeout?: number;\n state: State;\n}) {\n createProgressIndicator(undefined, `Applying updates...`, 'indeterminate');\n try {\n let status = await initiateRestart({ state });\n if (wait) {\n const start = new Date().getTime();\n let runtime = 0;\n let errors = 0;\n const maxErrors = 3;\n while (\n status !== RestartStatus.ready &&\n start + timeout > new Date().getTime()\n ) {\n await new Promise((resolve) => setTimeout(resolve, 5000));\n try {\n status = await getStatus({ state });\n\n // reset errors after successful status call\n if (errors) errors = 0;\n\n runtime = new Date().getTime() - start;\n updateProgressIndicator(`${status} (${Math.round(runtime / 1000)}s)`);\n } catch (error) {\n errors++;\n if (errors > maxErrors) {\n throw error;\n }\n runtime = new Date().getTime() - start;\n updateProgressIndicator(\n `${error.message} - retry ${errors}/${maxErrors} (${Math.round(\n runtime / 1000\n )}s)`\n );\n }\n }\n if (runtime < timeout) {\n stopProgressIndicator(\n `Updates applied in ${Math.round(\n runtime / 1000\n )}s with final status: ${status}`,\n 'success'\n );\n return true;\n } else {\n stopProgressIndicator(\n `Updates timed out after ${Math.round(\n runtime / 1000\n )}s with final status: ${status}`,\n 'warn'\n );\n return false;\n }\n } else {\n stopProgressIndicator(\n `Updates are being applied. Changes may take up to 10 minutes to propagate, during which time you will not be able to make further updates.`,\n 'success'\n );\n return true;\n }\n } catch (error) {\n stopProgressIndicator(\n `Error: ${error.response?.data?.code || error} - ${\n error.response?.data?.message\n }`,\n 'fail'\n );\n return false;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/ops/cloud/StartupOps.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,MAAM,oBAAoB,CAAC;AAEvC,MAAM,CAAC,OAAO,OAAO,UAAU;IAC7B,KAAK,EAAE,KAAK,CAAC;gBACD,KAAK,EAAE,KAAK;IAIxB;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC;IAIzC;;;;;OAKG;IACG,YAAY,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,MAAuB;CAOnE;AAED;;GAEG;AACH,MAAM,WAAW,OAAO;IACtB;;OAEG;IACH,OAAO,CAAC,EAAE,OAAO,EAAE,CAAC;IACpB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,EAAE,CAAC;CACvB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CAAC,EACpC,KAAK,GACN,EAAE;IACD,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,OAAO,CAAC,OAAO,CAAC,CAqCnB;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,EACjC,IAAI,EACJ,OAAwB,EACxB,KAAK,GACN,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACd,oBAiFA","file":"StartupOps.d.ts","sourcesContent":["import {\n createProgressIndicator,\n updateProgressIndicator,\n stopProgressIndicator,\n} from '../utils/Console';\nimport { getSecrets } from '../../api/cloud/SecretsApi';\nimport {\n getStatus,\n initiateRestart,\n RestartStatus,\n} from '../../api/cloud/StartupApi';\nimport { getVariables } from '../../api/cloud/VariablesApi';\nimport State from '../../shared/State';\n\nexport default class StartupOps {\n state: State;\n constructor(state: State) {\n this.state = state;\n }\n\n /**\n * Check for updates that need applying\n * @returns {Promise<Updates>} true if there are updates that need to be applied, false otherwise\n */\n async checkForUpdates(): Promise<Updates> {\n return checkForUpdates({ state: this.state });\n }\n\n /**\n * Apply updates\n * @param {boolean} wait wait for the operation to complete or not\n * @param {number} timeout timeout in milliseconds\n * @returns {Promise<boolean>} true if successful, false otherwise\n */\n async applyUpdates(wait: boolean, timeout: number = 10 * 60 * 1000) {\n return applyUpdates({\n wait,\n timeout,\n state: this.state,\n });\n }\n}\n\n/**\n * Updates that need to be applied.\n */\nexport interface Updates {\n /**\n * Array of secrets that need applying\n */\n secrets?: unknown[];\n /**\n * Array of variables that need applying\n */\n variables?: unknown[];\n}\n\n/**\n * Check for updates that need applying\n * @returns {Promise<boolean>} true if there are updates that need to be applied, false otherwise\n */\nexport async function checkForUpdates({\n state,\n}: {\n state: State;\n}): Promise<Updates> {\n const updates: Updates = { secrets: [], variables: [] };\n createProgressIndicator({\n total: undefined,\n message: `Checking for updates to apply...`,\n type: 'indeterminate',\n state,\n });\n try {\n updates.secrets = (await getSecrets({ state })).result.filter(\n (secret: { loaded: unknown }) => !secret.loaded\n );\n updates.variables = (await getVariables({ state })).result.filter(\n (variable: { loaded: unknown }) => !variable.loaded\n );\n } catch (error) {\n stopProgressIndicator({\n message: `Error: ${error.response.data.code} - ${error.response.data.message}`,\n status: 'fail',\n state,\n });\n }\n const updateCount = updates.secrets?.length + updates.variables?.length || 0;\n if (updateCount > 0) {\n stopProgressIndicator({\n message: `${updateCount} update(s) need to be applied`,\n status: 'success',\n state,\n });\n } else {\n stopProgressIndicator({\n message: `No updates need to be applied`,\n status: 'success',\n state,\n });\n }\n return updates;\n}\n\n/**\n * Apply updates\n * @param {boolean} wait wait for the operation to complete or not\n * @param {number} timeout timeout in milliseconds\n * @returns {Promise<boolean>} true if successful, false otherwise\n */\nexport async function applyUpdates({\n wait,\n timeout = 10 * 60 * 1000,\n state,\n}: {\n wait: boolean;\n timeout?: number;\n state: State;\n}) {\n createProgressIndicator({\n total: undefined,\n message: `Applying updates...`,\n type: 'indeterminate',\n state,\n });\n try {\n let status = await initiateRestart({ state });\n if (wait) {\n const start = new Date().getTime();\n let runtime = 0;\n let errors = 0;\n const maxErrors = 3;\n while (\n status !== RestartStatus.ready &&\n start + timeout > new Date().getTime()\n ) {\n await new Promise((resolve) => setTimeout(resolve, 5000));\n try {\n status = await getStatus({ state });\n\n // reset errors after successful status call\n if (errors) errors = 0;\n\n runtime = new Date().getTime() - start;\n updateProgressIndicator({\n message: `${status} (${Math.round(runtime / 1000)}s)`,\n state,\n });\n } catch (error) {\n errors++;\n if (errors > maxErrors) {\n throw error;\n }\n runtime = new Date().getTime() - start;\n updateProgressIndicator({\n message: `${\n error.message\n } - retry ${errors}/${maxErrors} (${Math.round(runtime / 1000)}s)`,\n state,\n });\n }\n }\n if (runtime < timeout) {\n stopProgressIndicator({\n message: `Updates applied in ${Math.round(\n runtime / 1000\n )}s with final status: ${status}`,\n status: 'success',\n state,\n });\n return true;\n } else {\n stopProgressIndicator({\n message: `Updates timed out after ${Math.round(\n runtime / 1000\n )}s with final status: ${status}`,\n status: 'warn',\n state,\n });\n return false;\n }\n } else {\n stopProgressIndicator({\n message: `Updates are being applied. Changes may take up to 10 minutes to propagate, during which time you will not be able to make further updates.`,\n status: 'success',\n state,\n });\n return true;\n }\n } catch (error) {\n stopProgressIndicator({\n message: `Error: ${error.response?.data?.code || error} - ${\n error.response?.data?.message\n }`,\n status: 'fail',\n state,\n });\n return false;\n }\n}\n"]}
@@ -1,4 +1,5 @@
1
1
  import Table from 'cli-table3';
2
+ import State from '../../shared/State';
2
3
  /**
3
4
  * Handles data / messages output. The caller decides and implements how
4
5
  * the data and messages are handled, by implementing the handler function
@@ -11,7 +12,12 @@ import Table from 'cli-table3';
11
12
  * @param {boolean} [newline=true] Whether to add a newline at the end of message
12
13
  * messages returned
13
14
  */
14
- export declare function printMessage(message: string | object, type?: string, newline?: boolean): void;
15
+ export declare function printMessage({ message, type, newline, state, }: {
16
+ message: string | object;
17
+ type?: string;
18
+ newline?: boolean;
19
+ state: State;
20
+ }): void;
15
21
  /**
16
22
  * Handles verbose output. The caller decides and implements how
17
23
  * the messages are handled, by implementing the handler function
@@ -19,7 +25,10 @@ export declare function printMessage(message: string | object, type?: string, ne
19
25
  *
20
26
  * @param {string | unknown} message The verbose output message
21
27
  */
22
- export declare function verboseMessage(message: string | object): void;
28
+ export declare function verboseMessage({ message, state, }: {
29
+ message: string | object;
30
+ state: State;
31
+ }): void;
23
32
  /**
24
33
  * Handles debug output. The caller decides and implements how
25
34
  * the messages are handled, by implementing the handler function
@@ -27,7 +36,10 @@ export declare function verboseMessage(message: string | object): void;
27
36
  *
28
37
  * @param {string | object} message The debug output message
29
38
  */
30
- export declare function debugMessage(message: string | object): void;
39
+ export declare function debugMessage({ message, state, }: {
40
+ message: string | object;
41
+ state: State;
42
+ }): void;
31
43
  /**
32
44
  * Handles curlirize output. The caller decides and implements how
33
45
  * the messages are handled, by implementing the handler function
@@ -35,7 +47,10 @@ export declare function debugMessage(message: string | object): void;
35
47
  *
36
48
  * @param {string} message The curlirize output message
37
49
  */
38
- export declare function curlirizeMessage(message: string): void;
50
+ export declare function curlirizeMessage({ message, state, }: {
51
+ message: string;
52
+ state: State;
53
+ }): void;
39
54
  /**
40
55
  * Calls a callback on client to create a progress indicator.
41
56
  * The actual implementation of the indicator is left to the client
@@ -54,19 +69,31 @@ export declare function curlirizeMessage(message: string): void;
54
69
  * @param {String} type optional type of progress indicator. default is 'determinate'
55
70
  *
56
71
  */
57
- export declare function createProgressIndicator(total: any, message?: string, type?: string): void;
72
+ export declare function createProgressIndicator({ total, message, type, state, }: {
73
+ total: number;
74
+ message?: string;
75
+ type?: string;
76
+ state: State;
77
+ }): void;
58
78
  /**
59
79
  * Updates the progress indicator with new data/updated status.
60
80
  * @param {string} message optional message to show with the indicator
61
81
  *
62
82
  */
63
- export declare function updateProgressIndicator(message?: string): void;
83
+ export declare function updateProgressIndicator({ message, state, }: {
84
+ message?: string;
85
+ state: State;
86
+ }): void;
64
87
  /**
65
88
  * Stop and hide the progress indicator
66
89
  * @param {string} message optional message to show with the indicator
67
90
  * @param {string} status one of 'none', 'success', 'warn', 'fail'
68
91
  */
69
- export declare function stopProgressIndicator(message?: string, status?: string): void;
92
+ export declare function stopProgressIndicator({ message, status, state, }: {
93
+ message?: string;
94
+ status?: string;
95
+ state: State;
96
+ }): void;
70
97
  /**
71
98
  * Create an empty table
72
99
  * @param {[String]} head header row as an array of strings
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ops/utils/Console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAG/B;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,IAAI,SAAS,EACb,OAAO,UAAO,QAMf;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,QAKtD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,QAKpD;AAeD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,QAK/C;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,KAAA,EACL,OAAO,GAAE,MAAa,EACtB,IAAI,SAAgB,QAMrB;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,GAAE,MAAa,QAK7D;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,GAAE,MAAa,EAAE,MAAM,SAAS,QAK5E;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,KAAA,eAqB/B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,gBAqBlC;AA+ED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,KAAA,EAAE,MAAM,KAAK,eA2BpD","file":"Console.d.ts","sourcesContent":["import Table from 'cli-table3';\nimport { state } from '../../lib/FrodoLib';\n\n/**\n * Handles data / messages output. The caller decides and implements how\n * the data and messages are handled, by implementing the handler function\n * on its side. `handler` is optional, and if not included by the caller,\n * the data and messages will be lost.\n *\n * @param {string | unknown} message The string message to return\n * @param {string} [type=text] \"text\", \"info\", \"warn\", \"error\" or \"data\". All but\n * type=\"data\" will be written to stderr.\n * @param {boolean} [newline=true] Whether to add a newline at the end of message\n * messages returned\n */\nexport function printMessage(\n message: string | object,\n type = 'text',\n newline = true\n) {\n const handler = state.getPrintHandler();\n if (handler) {\n handler(message, type, newline);\n }\n}\n\n/**\n * Handles verbose output. The caller decides and implements how\n * the messages are handled, by implementing the handler function\n * on its side. Implementing and registering a `handler` is optional.\n *\n * @param {string | unknown} message The verbose output message\n */\nexport function verboseMessage(message: string | object) {\n const handler = state.getVerboseHandler();\n if (handler) {\n handler(message);\n }\n}\n\n/**\n * Handles debug output. The caller decides and implements how\n * the messages are handled, by implementing the handler function\n * on its side. Implementing and registering a `handler` is optional.\n *\n * @param {string | object} message The debug output message\n */\nexport function debugMessage(message: string | object) {\n const handler = state.getDebugHandler();\n if (handler) {\n handler(message);\n }\n}\n\n/**\n * Helper function to mask password header in curl command\n * @param curlCommand curl command to mask\n * @param {State} state library state\n * @returns masked curl command\n */\nfunction maskPasswordHeader(curlCommand: string) {\n const header = 'X-OpenAM-Password:';\n const mask = '<suppressed>';\n const regex = new RegExp('\"' + header + '.+?\"', 'g');\n return curlCommand.replace(regex, '\"' + header + mask + '\"');\n}\n\n/**\n * Handles curlirize output. The caller decides and implements how\n * the messages are handled, by implementing the handler function\n * on its side. Implementing and registering a `handler` is optional.\n *\n * @param {string} message The curlirize output message\n */\nexport function curlirizeMessage(message: string) {\n const handler = state.getCurlirizeHandler();\n if (handler) {\n handler(maskPasswordHeader(message));\n }\n}\n\n/**\n * Calls a callback on client to create a progress indicator.\n * The actual implementation of the indicator is left to the client\n * Two types of indicators are supported:\n * - determinate: should be used when the process completion rate\n * can be detected (example: progress bar showing percentage or count)\n * - indeterminate: used when progress isn’t detectable, or if\n * it’s not necessary to indicate how long an activity will take.\n * (example: spinner showing progress, but not quantifying the progress)\n *\n * Example:\n * [========================================] 100% | 49/49 | Analyzing journey - transactional_auth\n *\n * @param {Number} total The total number of entries to track progress for\n * @param {String} message optional progress bar message\n * @param {String} type optional type of progress indicator. default is 'determinate'\n *\n */\nexport function createProgressIndicator(\n total,\n message: string = null,\n type = 'determinate'\n) {\n const handler = state.getCreateProgressHandler();\n if (handler) {\n handler(type, total, message);\n }\n}\n\n/**\n * Updates the progress indicator with new data/updated status.\n * @param {string} message optional message to show with the indicator\n *\n */\nexport function updateProgressIndicator(message: string = null) {\n const handler = state.getUpdateProgressHandler();\n if (handler) {\n handler(message);\n }\n}\n\n/**\n * Stop and hide the progress indicator\n * @param {string} message optional message to show with the indicator\n * @param {string} status one of 'none', 'success', 'warn', 'fail'\n */\nexport function stopProgressIndicator(message: string = null, status = 'none') {\n const handler = state.getStopProgressHandler();\n if (handler) {\n handler(message, status);\n }\n}\n\n/**\n * Create an empty table\n * @param {[String]} head header row as an array of strings\n * @returns {CliTable3} an empty table\n */\nexport function createTable(head) {\n return new Table({\n head,\n chars: {\n top: '',\n 'top-mid': '',\n 'top-left': '',\n 'top-right': '',\n bottom: '',\n 'bottom-mid': '',\n 'bottom-left': '',\n 'bottom-right': '',\n left: '',\n 'left-mid': '',\n mid: '',\n 'mid-mid': '',\n right: '',\n 'right-mid': '',\n },\n style: { 'padding-left': 0, 'padding-right': 0, head: ['brightCyan'] },\n });\n}\n\n/**\n * Create a new key/value table\n * @returns {CliTable3} an empty key/value table\n */\nexport function createKeyValueTable() {\n return new Table({\n chars: {\n top: '',\n 'top-mid': '',\n 'top-left': '',\n 'top-right': '',\n bottom: '',\n 'bottom-mid': '',\n 'bottom-left': '',\n 'bottom-right': '',\n left: '',\n 'left-mid': '',\n mid: '',\n 'mid-mid': '',\n right: '',\n 'right-mid': '',\n },\n style: { 'padding-left': 0, 'padding-right': 0 },\n wordWrap: true,\n });\n}\n\n/**\n * Helper function to determine the total depth of an object\n * @param {Object} object input object\n * @returns {Number} total depth of the input object\n */\nfunction getObjectDepth(object) {\n return Object(object) === object\n ? 1 + Math.max(-1, ...Object.values(object).map(getObjectDepth))\n : 0;\n}\n\n/**\n * Helper function to determine if an object has values\n * @param {Object} object input object\n * @returns {boolean} true of the object or any of its sub-objects contain values, false otherwise\n */\nfunction hasValues(object) {\n let has = false;\n const keys = Object.keys(object);\n for (const key of keys) {\n if (Object(object[key]) !== object[key]) {\n return true;\n }\n has = has || hasValues(object[key]);\n }\n return has;\n}\n\n/**\n * Helper function (recursive) to add rows to an object table\n * @param {Object} object object to render\n * @param {Number} depth total depth of initial object\n * @param {Number} level current level\n * @param {CliTable3} table the object table to add the rows to\n * @returns the updated object table\n */\nfunction addRows(object, depth, level, table, keyMap) {\n const space = ' ';\n const keys = Object.keys(object);\n for (const key of keys) {\n if (Object(object[key]) !== object[key]) {\n if (level === 1) {\n table.push([\n keyMap[key] ? keyMap[key]['brightCyan'] : key['brightCyan'],\n object[key],\n ]);\n } else {\n table.push([\n {\n hAlign: 'right',\n content: keyMap[key] ? keyMap[key]['gray'] : key['gray'],\n },\n object[key],\n ]);\n }\n }\n }\n for (const key of keys) {\n if (Object(object[key]) === object[key]) {\n // only print header if there are any values below\n if (hasValues(object[key])) {\n let indention = new Array(level).fill(space).join('');\n if (level < 3) indention = `\\n${indention}`;\n table.push([\n indention.concat(\n keyMap[key] ? keyMap[key]['brightCyan'] : key['brightCyan']\n ),\n '',\n ]);\n }\n // eslint-disable-next-line no-param-reassign\n table = addRows(object[key], depth, level + 1, table, keyMap);\n }\n }\n return table;\n}\n\n/**\n * Create and populate an object table from any JSON object. Use for describe commands.\n * @param {Object} object JSON object to create\n * @returns {CliTable3} a table that can be printed to the console\n */\nexport function createObjectTable(object, keyMap = {}) {\n // eslint-disable-next-line no-param-reassign\n const depth = getObjectDepth(object);\n // eslint-disable-next-line no-param-reassign\n const level = 0;\n // eslint-disable-next-line no-param-reassign\n const table = new Table({\n chars: {\n top: '',\n 'top-mid': '',\n 'top-left': '',\n 'top-right': '',\n bottom: '',\n 'bottom-mid': '',\n 'bottom-left': '',\n 'bottom-right': '',\n left: '',\n 'left-mid': '',\n mid: '',\n 'mid-mid': '',\n right: '',\n 'right-mid': '',\n },\n style: { 'padding-left': 0, 'padding-right': 0, head: ['brightCyan'] },\n });\n addRows(object, depth, level + 1, table, keyMap);\n return table;\n}\n"]}
1
+ {"version":3,"sources":["../src/ops/utils/Console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,KAAK,MAAM,oBAAoB,CAAC;AAEvC;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,IAAa,EACb,OAAc,EACd,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,EAC7B,OAAO,EACP,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAC3B,OAAO,EACP,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAeD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,OAAO,EACP,KAAK,GACN,EAAE;IACD,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,KAAK,EACL,OAAmB,EACnB,IAAoB,EACpB,KAAK,GACN,EAAE;IACD,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,OAAmB,EACnB,KAAK,GACN,EAAE;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,OAAc,EACd,MAAe,EACf,KAAK,GACN,EAAE;IACD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,KAAK,CAAC;CACd,QAKA;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,KAAA,eAqB/B;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,gBAqBlC;AA+ED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,KAAA,EAAE,MAAM,KAAK,eA2BpD","file":"Console.d.ts","sourcesContent":["import Table from 'cli-table3';\nimport State from '../../shared/State';\n\n/**\n * Handles data / messages output. The caller decides and implements how\n * the data and messages are handled, by implementing the handler function\n * on its side. `handler` is optional, and if not included by the caller,\n * the data and messages will be lost.\n *\n * @param {string | unknown} message The string message to return\n * @param {string} [type=text] \"text\", \"info\", \"warn\", \"error\" or \"data\". All but\n * type=\"data\" will be written to stderr.\n * @param {boolean} [newline=true] Whether to add a newline at the end of message\n * messages returned\n */\nexport function printMessage({\n message,\n type = 'text',\n newline = true,\n state,\n}: {\n message: string | object;\n type?: string;\n newline?: boolean;\n state: State;\n}) {\n const handler = state.getPrintHandler();\n if (handler) {\n handler(message, type, newline);\n }\n}\n\n/**\n * Handles verbose output. The caller decides and implements how\n * the messages are handled, by implementing the handler function\n * on its side. Implementing and registering a `handler` is optional.\n *\n * @param {string | unknown} message The verbose output message\n */\nexport function verboseMessage({\n message,\n state,\n}: {\n message: string | object;\n state: State;\n}) {\n const handler = state.getVerboseHandler();\n if (handler) {\n handler(message);\n }\n}\n\n/**\n * Handles debug output. The caller decides and implements how\n * the messages are handled, by implementing the handler function\n * on its side. Implementing and registering a `handler` is optional.\n *\n * @param {string | object} message The debug output message\n */\nexport function debugMessage({\n message,\n state,\n}: {\n message: string | object;\n state: State;\n}) {\n const handler = state.getDebugHandler();\n if (handler) {\n handler(message);\n }\n}\n\n/**\n * Helper function to mask password header in curl command\n * @param curlCommand curl command to mask\n * @param {State} state library state\n * @returns masked curl command\n */\nfunction maskPasswordHeader(curlCommand: string) {\n const header = 'X-OpenAM-Password:';\n const mask = '<suppressed>';\n const regex = new RegExp('\"' + header + '.+?\"', 'g');\n return curlCommand.replace(regex, '\"' + header + mask + '\"');\n}\n\n/**\n * Handles curlirize output. The caller decides and implements how\n * the messages are handled, by implementing the handler function\n * on its side. Implementing and registering a `handler` is optional.\n *\n * @param {string} message The curlirize output message\n */\nexport function curlirizeMessage({\n message,\n state,\n}: {\n message: string;\n state: State;\n}) {\n const handler = state.getCurlirizeHandler();\n if (handler) {\n handler(maskPasswordHeader(message));\n }\n}\n\n/**\n * Calls a callback on client to create a progress indicator.\n * The actual implementation of the indicator is left to the client\n * Two types of indicators are supported:\n * - determinate: should be used when the process completion rate\n * can be detected (example: progress bar showing percentage or count)\n * - indeterminate: used when progress isn’t detectable, or if\n * it’s not necessary to indicate how long an activity will take.\n * (example: spinner showing progress, but not quantifying the progress)\n *\n * Example:\n * [========================================] 100% | 49/49 | Analyzing journey - transactional_auth\n *\n * @param {Number} total The total number of entries to track progress for\n * @param {String} message optional progress bar message\n * @param {String} type optional type of progress indicator. default is 'determinate'\n *\n */\nexport function createProgressIndicator({\n total,\n message = undefined,\n type = 'determinate',\n state,\n}: {\n total: number;\n message?: string;\n type?: string;\n state: State;\n}) {\n const handler = state.getCreateProgressHandler();\n if (handler) {\n handler(type, total, message);\n }\n}\n\n/**\n * Updates the progress indicator with new data/updated status.\n * @param {string} message optional message to show with the indicator\n *\n */\nexport function updateProgressIndicator({\n message = undefined,\n state,\n}: {\n message?: string;\n state: State;\n}) {\n const handler = state.getUpdateProgressHandler();\n if (handler) {\n handler(message);\n }\n}\n\n/**\n * Stop and hide the progress indicator\n * @param {string} message optional message to show with the indicator\n * @param {string} status one of 'none', 'success', 'warn', 'fail'\n */\nexport function stopProgressIndicator({\n message = null,\n status = 'none',\n state,\n}: {\n message?: string;\n status?: string;\n state: State;\n}) {\n const handler = state.getStopProgressHandler();\n if (handler) {\n handler(message, status);\n }\n}\n\n/**\n * Create an empty table\n * @param {[String]} head header row as an array of strings\n * @returns {CliTable3} an empty table\n */\nexport function createTable(head) {\n return new Table({\n head,\n chars: {\n top: '',\n 'top-mid': '',\n 'top-left': '',\n 'top-right': '',\n bottom: '',\n 'bottom-mid': '',\n 'bottom-left': '',\n 'bottom-right': '',\n left: '',\n 'left-mid': '',\n mid: '',\n 'mid-mid': '',\n right: '',\n 'right-mid': '',\n },\n style: { 'padding-left': 0, 'padding-right': 0, head: ['brightCyan'] },\n });\n}\n\n/**\n * Create a new key/value table\n * @returns {CliTable3} an empty key/value table\n */\nexport function createKeyValueTable() {\n return new Table({\n chars: {\n top: '',\n 'top-mid': '',\n 'top-left': '',\n 'top-right': '',\n bottom: '',\n 'bottom-mid': '',\n 'bottom-left': '',\n 'bottom-right': '',\n left: '',\n 'left-mid': '',\n mid: '',\n 'mid-mid': '',\n right: '',\n 'right-mid': '',\n },\n style: { 'padding-left': 0, 'padding-right': 0 },\n wordWrap: true,\n });\n}\n\n/**\n * Helper function to determine the total depth of an object\n * @param {Object} object input object\n * @returns {Number} total depth of the input object\n */\nfunction getObjectDepth(object) {\n return Object(object) === object\n ? 1 + Math.max(-1, ...Object.values(object).map(getObjectDepth))\n : 0;\n}\n\n/**\n * Helper function to determine if an object has values\n * @param {Object} object input object\n * @returns {boolean} true of the object or any of its sub-objects contain values, false otherwise\n */\nfunction hasValues(object) {\n let has = false;\n const keys = Object.keys(object);\n for (const key of keys) {\n if (Object(object[key]) !== object[key]) {\n return true;\n }\n has = has || hasValues(object[key]);\n }\n return has;\n}\n\n/**\n * Helper function (recursive) to add rows to an object table\n * @param {Object} object object to render\n * @param {Number} depth total depth of initial object\n * @param {Number} level current level\n * @param {CliTable3} table the object table to add the rows to\n * @returns the updated object table\n */\nfunction addRows(object, depth, level, table, keyMap) {\n const space = ' ';\n const keys = Object.keys(object);\n for (const key of keys) {\n if (Object(object[key]) !== object[key]) {\n if (level === 1) {\n table.push([\n keyMap[key] ? keyMap[key]['brightCyan'] : key['brightCyan'],\n object[key],\n ]);\n } else {\n table.push([\n {\n hAlign: 'right',\n content: keyMap[key] ? keyMap[key]['gray'] : key['gray'],\n },\n object[key],\n ]);\n }\n }\n }\n for (const key of keys) {\n if (Object(object[key]) === object[key]) {\n // only print header if there are any values below\n if (hasValues(object[key])) {\n let indention = new Array(level).fill(space).join('');\n if (level < 3) indention = `\\n${indention}`;\n table.push([\n indention.concat(\n keyMap[key] ? keyMap[key]['brightCyan'] : key['brightCyan']\n ),\n '',\n ]);\n }\n // eslint-disable-next-line no-param-reassign\n table = addRows(object[key], depth, level + 1, table, keyMap);\n }\n }\n return table;\n}\n\n/**\n * Create and populate an object table from any JSON object. Use for describe commands.\n * @param {Object} object JSON object to create\n * @returns {CliTable3} a table that can be printed to the console\n */\nexport function createObjectTable(object, keyMap = {}) {\n // eslint-disable-next-line no-param-reassign\n const depth = getObjectDepth(object);\n // eslint-disable-next-line no-param-reassign\n const level = 0;\n // eslint-disable-next-line no-param-reassign\n const table = new Table({\n chars: {\n top: '',\n 'top-mid': '',\n 'top-left': '',\n 'top-right': '',\n bottom: '',\n 'bottom-mid': '',\n 'bottom-left': '',\n 'bottom-right': '',\n left: '',\n 'left-mid': '',\n mid: '',\n 'mid-mid': '',\n right: '',\n 'right-mid': '',\n },\n style: { 'padding-left': 0, 'padding-right': 0, head: ['brightCyan'] },\n });\n addRows(object, depth, level + 1, table, keyMap);\n return table;\n}\n"]}
@@ -1,5 +1,9 @@
1
+ import State from '../../shared/State';
1
2
  declare class DataProtection {
2
- constructor(pathToMasterKey?: string);
3
+ constructor({ pathToMasterKey, state, }: {
4
+ pathToMasterKey?: string;
5
+ state: State;
6
+ });
3
7
  encrypt(data: any): Promise<any>;
4
8
  decrypt(data: any): Promise<any>;
5
9
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ops/utils/DataProtection.ts"],"names":[],"mappings":"AA6BA,cAAM,cAAc;gBACN,eAAe,GAAE,MAAa;IA+CpC,OAAO,CAAC,IAAI,KAAA;IAQZ,OAAO,CAAC,IAAI,KAAA;CAenB;AACD,eAAe,cAAc,CAAC","file":"DataProtection.d.ts","sourcesContent":["/**\n * Data is stored in base64 format. Initially it was binary data\n * Format used in this encryption module.\n * inspired by AndiDittrich\n * +--------------------+-----------------------+----------------+----------------+\n * | SALT | Initialization Vector | Auth Tag | Payload |\n * | Used to derive key | AES GCM XOR Init | Data Integrity | Encrypted Data |\n * | 64 Bytes, random | 16 Bytes, random | 16 Bytes | (N-96) Bytes |\n * +--------------------+-----------------------+----------------+----------------+\n * This module doesn't take care of data persistence, it's assumed the consuming method/class/package will do so.\n */\nimport fs, { promises as fsp } from 'fs';\nimport crypto from 'crypto';\nimport { homedir } from 'os';\nimport { promisify } from 'util';\nimport { printMessage } from './Console';\nimport {\n FRODO_MASTER_KEY_PATH_KEY,\n FRODO_MASTER_KEY_KEY,\n} from '../../storage/StaticStorage';\n\nconst scrypt = promisify(crypto.scrypt);\n// using WeakMaps for added security since it gets garbage collected\nconst _masterKey = new WeakMap();\nconst _nonce = new WeakMap();\nconst _salt = new WeakMap();\nconst _key = new WeakMap();\nconst _encrypt = new WeakMap();\n\nclass DataProtection {\n constructor(pathToMasterKey: string = null) {\n const masterKeyPath = () =>\n pathToMasterKey ||\n process.env[FRODO_MASTER_KEY_PATH_KEY] ||\n `${homedir()}/.frodo/masterkey.key`;\n // Generates a master key in base64 format. This master key will be used to derive the key for encryption. this key should be protected by an HSM or KMS\n _masterKey.set(this, async () => {\n try {\n if (process.env[FRODO_MASTER_KEY_KEY])\n return process.env[FRODO_MASTER_KEY_KEY];\n if (!fs.existsSync(masterKeyPath())) {\n const masterKey = crypto.randomBytes(32).toString('base64');\n await fsp.writeFile(masterKeyPath(), masterKey);\n }\n return await fsp.readFile(masterKeyPath(), 'utf8');\n } catch (err) {\n printMessage(err.message, 'error');\n return '';\n }\n });\n\n // the nonce for AES GCM\n _nonce.set(this, () => crypto.randomBytes(16));\n\n // The salt\n _salt.set(this, () => crypto.randomBytes(64));\n\n // The function that derives the key, this supports sync and async operations\n _key.set(\n this,\n // eslint-disable-next-line no-return-await\n async (masterKey, salt) => await scrypt(masterKey, salt, 32)\n );\n\n // private method to encrypt and return encrypted data. cleaner code\n _encrypt.set(this, (key, nonce, data, salt) => {\n const cipher = crypto.createCipheriv('aes-256-gcm', key, nonce);\n const encrypted = Buffer.concat([\n cipher.update(JSON.stringify(data), 'utf8'),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n const buffer = Buffer.concat([salt, nonce, tag, encrypted]);\n return buffer.toString('base64');\n });\n }\n\n async encrypt(data) {\n const nonce = _nonce.get(this)();\n const salt = _salt.get(this)();\n const masterKey = await _masterKey.get(this)();\n const key = await _key.get(this)(masterKey, salt);\n return _encrypt.get(this)(key, nonce, data, salt);\n }\n\n async decrypt(data) {\n const buffer = Buffer.from(data.toString(), 'base64');\n const salt = buffer.slice(0, 64);\n const nonce = buffer.slice(64, 80);\n const tag = buffer.slice(80, 96);\n const encrypted = buffer.slice(96);\n const masterKey = await _masterKey.get(this)();\n const key = await _key.get(this)(masterKey, salt);\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, nonce);\n decipher.setAuthTag(tag);\n return JSON.parse(\n decipher.update(encrypted.toString('binary'), 'binary', 'utf8') +\n decipher.final('utf8')\n );\n }\n}\nexport default DataProtection;\n"]}
1
+ {"version":3,"sources":["../src/ops/utils/DataProtection.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,MAAM,oBAAoB,CAAC;AAUvC,cAAM,cAAc;gBACN,EACV,eAA2B,EAC3B,KAAK,GACN,EAAE;QACD,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,KAAK,EAAE,KAAK,CAAC;KACd;IA+CK,OAAO,CAAC,IAAI,KAAA;IAQZ,OAAO,CAAC,IAAI,KAAA;CAenB;AACD,eAAe,cAAc,CAAC","file":"DataProtection.d.ts","sourcesContent":["/**\n * Data is stored in base64 format. Initially it was binary data\n * Format used in this encryption module.\n * inspired by AndiDittrich\n * +--------------------+-----------------------+----------------+----------------+\n * | SALT | Initialization Vector | Auth Tag | Payload |\n * | Used to derive key | AES GCM XOR Init | Data Integrity | Encrypted Data |\n * | 64 Bytes, random | 16 Bytes, random | 16 Bytes | (N-96) Bytes |\n * +--------------------+-----------------------+----------------+----------------+\n * This module doesn't take care of data persistence, it's assumed the consuming method/class/package will do so.\n */\nimport fs, { promises as fsp } from 'fs';\nimport crypto from 'crypto';\nimport { homedir } from 'os';\nimport { promisify } from 'util';\nimport { printMessage } from './Console';\nimport {\n FRODO_MASTER_KEY_PATH_KEY,\n FRODO_MASTER_KEY_KEY,\n} from '../../storage/StaticStorage';\nimport State from '../../shared/State';\n\nconst scrypt = promisify(crypto.scrypt);\n// using WeakMaps for added security since it gets garbage collected\nconst _masterKey = new WeakMap();\nconst _nonce = new WeakMap();\nconst _salt = new WeakMap();\nconst _key = new WeakMap();\nconst _encrypt = new WeakMap();\n\nclass DataProtection {\n constructor({\n pathToMasterKey = undefined,\n state,\n }: {\n pathToMasterKey?: string;\n state: State;\n }) {\n const masterKeyPath = () =>\n pathToMasterKey ||\n process.env[FRODO_MASTER_KEY_PATH_KEY] ||\n `${homedir()}/.frodo/masterkey.key`;\n // Generates a master key in base64 format. This master key will be used to derive the key for encryption. this key should be protected by an HSM or KMS\n _masterKey.set(this, async () => {\n try {\n if (process.env[FRODO_MASTER_KEY_KEY])\n return process.env[FRODO_MASTER_KEY_KEY];\n if (!fs.existsSync(masterKeyPath())) {\n const masterKey = crypto.randomBytes(32).toString('base64');\n await fsp.writeFile(masterKeyPath(), masterKey);\n }\n return await fsp.readFile(masterKeyPath(), 'utf8');\n } catch (err) {\n printMessage({ message: err.message, type: 'error', state });\n return '';\n }\n });\n\n // the nonce for AES GCM\n _nonce.set(this, () => crypto.randomBytes(16));\n\n // The salt\n _salt.set(this, () => crypto.randomBytes(64));\n\n // The function that derives the key, this supports sync and async operations\n _key.set(\n this,\n // eslint-disable-next-line no-return-await\n async (masterKey, salt) => await scrypt(masterKey, salt, 32)\n );\n\n // private method to encrypt and return encrypted data. cleaner code\n _encrypt.set(this, (key, nonce, data, salt) => {\n const cipher = crypto.createCipheriv('aes-256-gcm', key, nonce);\n const encrypted = Buffer.concat([\n cipher.update(JSON.stringify(data), 'utf8'),\n cipher.final(),\n ]);\n const tag = cipher.getAuthTag();\n const buffer = Buffer.concat([salt, nonce, tag, encrypted]);\n return buffer.toString('base64');\n });\n }\n\n async encrypt(data) {\n const nonce = _nonce.get(this)();\n const salt = _salt.get(this)();\n const masterKey = await _masterKey.get(this)();\n const key = await _key.get(this)(masterKey, salt);\n return _encrypt.get(this)(key, nonce, data, salt);\n }\n\n async decrypt(data) {\n const buffer = Buffer.from(data.toString(), 'base64');\n const salt = buffer.slice(0, 64);\n const nonce = buffer.slice(64, 80);\n const tag = buffer.slice(80, 96);\n const encrypted = buffer.slice(96);\n const masterKey = await _masterKey.get(this)();\n const key = await _key.get(this)(masterKey, salt);\n const decipher = crypto.createDecipheriv('aes-256-gcm', key, nonce);\n decipher.setAuthTag(tag);\n return JSON.parse(\n decipher.update(encrypted.toString('binary'), 'binary', 'utf8') +\n decipher.final('utf8')\n );\n }\n}\nexport default DataProtection;\n"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ops/utils/ExportImportUtils.ts"],"names":[],"mappings":"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","file":"ExportImportUtils.d.ts","sourcesContent":["import fs from 'fs';\nimport { lstat, readdir } from 'fs/promises';\nimport { join } from 'path';\nimport slugify from 'slugify';\nimport {\n decode,\n decodeBase64Url,\n encode,\n encodeBase64Url,\n} from '../../api/utils/Base64';\nimport State from '../../shared/State';\nimport { FRODO_METADATA_ID } from '../../storage/StaticStorage';\nimport { ExportMetaData } from '../OpsTypes';\nimport { debugMessage, printMessage } from './Console';\n\nexport default class ExportImportUtils {\n state: State;\n constructor(state: State) {\n this.state = state;\n }\n\n getMetadata(): ExportMetaData {\n return getMetadata({ state: this.state });\n }\n\n /*\n * Output str in title case\n *\n * e.g.: 'ALL UPPERCASE AND all lowercase' = 'All Uppercase And All Lowercase'\n */\n titleCase(input: string) {\n return titleCase(input);\n }\n\n getRealmString() {\n return getRealmString({ state: this.state });\n }\n\n convertBase64TextToArray(b64text: string) {\n return convertBase64TextToArray(b64text);\n }\n\n convertBase64UrlTextToArray(b64UTF8Text: string) {\n return convertBase64UrlTextToArray(b64UTF8Text);\n }\n\n convertTextArrayToBase64(textArray: string[]) {\n return convertTextArrayToBase64(textArray);\n }\n\n convertTextArrayToBase64Url(textArray: string[]) {\n return convertTextArrayToBase64Url(textArray);\n }\n\n validateImport(metadata): boolean {\n return validateImport(metadata);\n }\n\n getTypedFilename(name: string, type: string, suffix = 'json') {\n return getTypedFilename(name, type, suffix);\n }\n\n getWorkingDirectory() {\n return getWorkingDirectory({ state: this.state });\n }\n\n saveToFile(type: string, data: object, identifier: string, filename: string) {\n return saveToFile({ type, data, identifier, filename, state: this.state });\n }\n\n /**\n * Save JSON object to file\n * @param {Object} data data object\n * @param {String} filename file name\n * @return {boolean} true if successful, false otherwise\n */\n saveJsonToFile(data: object, filename: string, includeMeta = true): boolean {\n return saveJsonToFile({ data, filename, includeMeta, state: this.state });\n }\n\n /**\n * Append text data to file\n * @param {String} data text data\n * @param {String} filename file name\n */\n appendTextToFile(data: string, filename: string) {\n return appendTextToFile(data, filename);\n }\n\n /**\n * Find files by name\n * @param {string} fileName file name to search for\n * @param {boolean} fast return first result and stop search\n * @param {string} path path to directory where to start the search\n * @returns {string[]} array of found file paths relative to starting directory\n */\n findFilesByName(fileName: string, fast = true, path = './'): string[] {\n return findFilesByName(fileName, fast, path);\n }\n\n /**\n * find all (nested) files in a directory\n *\n * @param directory directory to search\n * @returns list of files\n */\n async readFilesRecursive(directory: string): Promise<string[]> {\n return readFilesRecursive(directory);\n }\n}\n\nexport function getMetadata({ state }: { state: State }): ExportMetaData {\n const metadata: ExportMetaData = {\n origin: state.getHost(),\n originAmVersion: state.getAmVersion(),\n exportedBy: state.getUsername(),\n exportDate: new Date().toISOString(),\n exportTool: FRODO_METADATA_ID,\n exportToolVersion: state.getFrodoVersion(),\n };\n return metadata;\n}\n\n/*\n * Output str in title case\n *\n * e.g.: 'ALL UPPERCASE AND all lowercase' = 'All Uppercase And All Lowercase'\n */\nexport function titleCase(input: string) {\n const str = input.toString();\n const splitStr = str.toLowerCase().split(' ');\n for (let i = 0; i < splitStr.length; i += 1) {\n splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].slice(1);\n }\n return splitStr.join(' ');\n}\n\nexport function getRealmString({ state }: { state: State }) {\n const realm = state.getRealm();\n return realm\n .split('/')\n .reduce((result, item) => `${result}${titleCase(item)}`, '');\n}\n\nexport function convertBase64TextToArray(b64text: string) {\n let arrayOut = [];\n let plainText = decode(b64text);\n plainText = plainText.replace(/\\t/g, ' ');\n arrayOut = plainText.split('\\n');\n return arrayOut;\n}\n\nexport function convertBase64UrlTextToArray(b64UTF8Text: string) {\n let arrayOut = [];\n let plainText = decodeBase64Url(b64UTF8Text);\n plainText = plainText.replace(/\\t/g, ' ');\n arrayOut = plainText.split('\\n');\n return arrayOut;\n}\n\nexport function convertTextArrayToBase64(textArray: string[]) {\n const joinedText = textArray.join('\\n');\n const b64encodedScript = encode(joinedText);\n return b64encodedScript;\n}\n\nexport function convertTextArrayToBase64Url(textArray: string[]) {\n const joinedText = textArray.join('\\n');\n const b64encodedScript = encodeBase64Url(joinedText);\n return b64encodedScript;\n}\n\n// eslint-disable-next-line no-unused-vars\nexport function validateImport(metadata): boolean {\n return metadata || true;\n}\n\nexport function getTypedFilename(name: string, type: string, suffix = 'json') {\n const slug = slugify(name.replace(/^http(s?):\\/\\//, ''));\n return `${slug}.${type}.${suffix}`;\n}\n\nexport function getWorkingDirectory({ state }: { state: State }) {\n let wd = '.';\n if (state.getDirectory()) {\n wd = state.getDirectory().replace(/\\/$/, '');\n // create directory if it doesn't exist\n if (!fs.existsSync(wd)) {\n debugMessage(\n `ExportImportUtils.getWorkingDirectory: creating directory '${wd}'`\n );\n fs.mkdirSync(wd, { recursive: true });\n }\n }\n return wd;\n}\n\nexport function saveToFile({\n type,\n data,\n identifier,\n filename,\n state,\n}: {\n type: string;\n data: object;\n identifier: string;\n filename: string;\n state: State;\n}) {\n const exportData = {};\n exportData['meta'] = getMetadata({ state });\n exportData[type] = {};\n\n if (Array.isArray(data)) {\n data.forEach((element) => {\n exportData[type][element[identifier]] = element;\n });\n } else {\n exportData[type][data[identifier]] = data;\n }\n fs.writeFile(filename, JSON.stringify(exportData, null, 2), (err) => {\n if (err) {\n return printMessage(`ERROR - can't save ${type} to file`, 'error');\n }\n return '';\n });\n}\n\n/**\n * Save JSON object to file\n * @param {Object} data data object\n * @param {String} filename file name\n * @return {boolean} true if successful, false otherwise\n */\nexport function saveJsonToFile({\n data,\n filename,\n includeMeta = true,\n state,\n}: {\n data: object;\n filename: string;\n includeMeta?: boolean;\n state: State;\n}): boolean {\n const exportData = data;\n if (includeMeta) exportData['meta'] = getMetadata({ state });\n try {\n fs.writeFileSync(filename, JSON.stringify(exportData, null, 2));\n return true;\n } catch (err) {\n printMessage(`ERROR - can't save ${filename}`, 'error');\n return false;\n }\n}\n\n/**\n * Append text data to file\n * @param {String} data text data\n * @param {String} filename file name\n */\nexport function appendTextToFile(data: string, filename: string) {\n try {\n fs.appendFileSync(filename, data);\n } catch (error) {\n printMessage(`${error.message}`, 'error');\n }\n}\n\n/**\n * Find files by name\n * @param {string} fileName file name to search for\n * @param {boolean} fast return first result and stop search\n * @param {string} path path to directory where to start the search\n * @returns {string[]} array of found file paths relative to starting directory\n */\nexport function findFilesByName(\n fileName: string,\n fast = true,\n path = './'\n): string[] {\n const entries = fs.readdirSync(path, {\n encoding: 'utf8',\n withFileTypes: true,\n });\n\n // Get files within the current directory and add a path key to the file objects\n const files: string[] = entries\n .filter((entry) => !entry.isDirectory())\n .filter((file) => file.name === fileName)\n // .map((file) => ({ ...file, path: path + file.name }));\n .map((file) => path + file.name);\n\n if (fast && files.length > 0) return files;\n\n // search sub-folders\n const folders = entries.filter((entry) => entry.isDirectory());\n for (const folder of folders)\n files.push(...findFilesByName(fileName, fast, `${path}${folder.name}/`));\n\n return files;\n}\n\n/**\n * find all (nested) files in a directory\n *\n * @param directory directory to search\n * @returns list of files\n */\nexport async function readFilesRecursive(directory: string): Promise<string[]> {\n const items = await readdir(directory);\n\n const filePathsNested = await Promise.all(\n items.map(async (entity) => {\n const path = join(directory, entity);\n const isDirectory = (await lstat(path)).isDirectory();\n\n if (isDirectory) {\n return readFilesRecursive(path);\n }\n return path;\n })\n );\n\n return filePathsNested.flat();\n}\n"]}
1
+ {"version":3,"sources":["../src/ops/utils/ExportImportUtils.ts"],"names":[],"mappings":"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","file":"ExportImportUtils.d.ts","sourcesContent":["import fs from 'fs';\nimport { lstat, readdir } from 'fs/promises';\nimport { join } from 'path';\nimport slugify from 'slugify';\nimport {\n decode,\n decodeBase64Url,\n encode,\n encodeBase64Url,\n} from '../../api/utils/Base64';\nimport State from '../../shared/State';\nimport { FRODO_METADATA_ID } from '../../storage/StaticStorage';\nimport { ExportMetaData } from '../OpsTypes';\nimport { debugMessage, printMessage } from './Console';\n\nexport default class ExportImportUtils {\n state: State;\n constructor(state: State) {\n this.state = state;\n }\n\n getMetadata(): ExportMetaData {\n return getMetadata({ state: this.state });\n }\n\n /*\n * Output str in title case\n *\n * e.g.: 'ALL UPPERCASE AND all lowercase' = 'All Uppercase And All Lowercase'\n */\n titleCase(input: string) {\n return titleCase(input);\n }\n\n getRealmString() {\n return getRealmString({ state: this.state });\n }\n\n convertBase64TextToArray(b64text: string) {\n return convertBase64TextToArray(b64text);\n }\n\n convertBase64UrlTextToArray(b64UTF8Text: string) {\n return convertBase64UrlTextToArray(b64UTF8Text);\n }\n\n convertTextArrayToBase64(textArray: string[]) {\n return convertTextArrayToBase64(textArray);\n }\n\n convertTextArrayToBase64Url(textArray: string[]) {\n return convertTextArrayToBase64Url(textArray);\n }\n\n validateImport(metadata): boolean {\n return validateImport(metadata);\n }\n\n getTypedFilename(name: string, type: string, suffix = 'json') {\n return getTypedFilename(name, type, suffix);\n }\n\n getWorkingDirectory() {\n return getWorkingDirectory({ state: this.state });\n }\n\n saveToFile(type: string, data: object, identifier: string, filename: string) {\n return saveToFile({ type, data, identifier, filename, state: this.state });\n }\n\n /**\n * Save JSON object to file\n * @param {Object} data data object\n * @param {String} filename file name\n * @return {boolean} true if successful, false otherwise\n */\n saveJsonToFile(data: object, filename: string, includeMeta = true): boolean {\n return saveJsonToFile({ data, filename, includeMeta, state: this.state });\n }\n\n /**\n * Append text data to file\n * @param {String} data text data\n * @param {String} filename file name\n */\n appendTextToFile(data: string, filename: string) {\n return appendTextToFile(data, filename);\n }\n\n /**\n * Find files by name\n * @param {string} fileName file name to search for\n * @param {boolean} fast return first result and stop search\n * @param {string} path path to directory where to start the search\n * @returns {string[]} array of found file paths relative to starting directory\n */\n findFilesByName(fileName: string, fast = true, path = './'): string[] {\n return findFilesByName(fileName, fast, path);\n }\n\n /**\n * find all (nested) files in a directory\n *\n * @param directory directory to search\n * @returns list of files\n */\n async readFilesRecursive(directory: string): Promise<string[]> {\n return readFilesRecursive(directory);\n }\n}\n\nexport function getMetadata({ state }: { state: State }): ExportMetaData {\n const metadata: ExportMetaData = {\n origin: state.getHost(),\n originAmVersion: state.getAmVersion(),\n exportedBy: state.getUsername(),\n exportDate: new Date().toISOString(),\n exportTool: FRODO_METADATA_ID,\n exportToolVersion: state.getFrodoVersion(),\n };\n return metadata;\n}\n\n/*\n * Output str in title case\n *\n * e.g.: 'ALL UPPERCASE AND all lowercase' = 'All Uppercase And All Lowercase'\n */\nexport function titleCase(input: string) {\n const str = input.toString();\n const splitStr = str.toLowerCase().split(' ');\n for (let i = 0; i < splitStr.length; i += 1) {\n splitStr[i] = splitStr[i].charAt(0).toUpperCase() + splitStr[i].slice(1);\n }\n return splitStr.join(' ');\n}\n\nexport function getRealmString({ state }: { state: State }) {\n const realm = state.getRealm();\n return realm\n .split('/')\n .reduce((result, item) => `${result}${titleCase(item)}`, '');\n}\n\nexport function convertBase64TextToArray(b64text: string) {\n let arrayOut = [];\n let plainText = decode(b64text);\n plainText = plainText.replace(/\\t/g, ' ');\n arrayOut = plainText.split('\\n');\n return arrayOut;\n}\n\nexport function convertBase64UrlTextToArray(b64UTF8Text: string) {\n let arrayOut = [];\n let plainText = decodeBase64Url(b64UTF8Text);\n plainText = plainText.replace(/\\t/g, ' ');\n arrayOut = plainText.split('\\n');\n return arrayOut;\n}\n\nexport function convertTextArrayToBase64(textArray: string[]) {\n const joinedText = textArray.join('\\n');\n const b64encodedScript = encode(joinedText);\n return b64encodedScript;\n}\n\nexport function convertTextArrayToBase64Url(textArray: string[]) {\n const joinedText = textArray.join('\\n');\n const b64encodedScript = encodeBase64Url(joinedText);\n return b64encodedScript;\n}\n\n// eslint-disable-next-line no-unused-vars\nexport function validateImport(metadata): boolean {\n return metadata || true;\n}\n\nexport function getTypedFilename(name: string, type: string, suffix = 'json') {\n const slug = slugify(name.replace(/^http(s?):\\/\\//, ''));\n return `${slug}.${type}.${suffix}`;\n}\n\nexport function getWorkingDirectory({ state }: { state: State }) {\n let wd = '.';\n if (state.getDirectory()) {\n wd = state.getDirectory().replace(/\\/$/, '');\n // create directory if it doesn't exist\n if (!fs.existsSync(wd)) {\n debugMessage({\n message: `ExportImportUtils.getWorkingDirectory: creating directory '${wd}'`,\n state,\n });\n fs.mkdirSync(wd, { recursive: true });\n }\n }\n return wd;\n}\n\nexport function saveToFile({\n type,\n data,\n identifier,\n filename,\n state,\n}: {\n type: string;\n data: object;\n identifier: string;\n filename: string;\n state: State;\n}) {\n const exportData = {};\n exportData['meta'] = getMetadata({ state });\n exportData[type] = {};\n\n if (Array.isArray(data)) {\n data.forEach((element) => {\n exportData[type][element[identifier]] = element;\n });\n } else {\n exportData[type][data[identifier]] = data;\n }\n fs.writeFile(filename, JSON.stringify(exportData, null, 2), (err) => {\n if (err) {\n return printMessage({\n message: `ERROR - can't save ${type} to file`,\n state,\n type: 'error',\n });\n }\n return '';\n });\n}\n\n/**\n * Save JSON object to file\n * @param {Object} data data object\n * @param {String} filename file name\n * @return {boolean} true if successful, false otherwise\n */\nexport function saveJsonToFile({\n data,\n filename,\n includeMeta = true,\n state,\n}: {\n data: object;\n filename: string;\n includeMeta?: boolean;\n state: State;\n}): boolean {\n const exportData = data;\n if (includeMeta) exportData['meta'] = getMetadata({ state });\n try {\n fs.writeFileSync(filename, JSON.stringify(exportData, null, 2));\n return true;\n } catch (err) {\n printMessage({\n message: `ERROR - can't save ${filename}`,\n type: 'error',\n state,\n });\n return false;\n }\n}\n\n/**\n * Append text data to file\n * @param {String} data text data\n * @param {String} filename file name\n */\nexport function appendTextToFile(data: string, filename: string) {\n fs.appendFileSync(filename, data);\n}\n\n/**\n * Find files by name\n * @param {string} fileName file name to search for\n * @param {boolean} fast return first result and stop search\n * @param {string} path path to directory where to start the search\n * @returns {string[]} array of found file paths relative to starting directory\n */\nexport function findFilesByName(\n fileName: string,\n fast = true,\n path = './'\n): string[] {\n const entries = fs.readdirSync(path, {\n encoding: 'utf8',\n withFileTypes: true,\n });\n\n // Get files within the current directory and add a path key to the file objects\n const files: string[] = entries\n .filter((entry) => !entry.isDirectory())\n .filter((file) => file.name === fileName)\n // .map((file) => ({ ...file, path: path + file.name }));\n .map((file) => path + file.name);\n\n if (fast && files.length > 0) return files;\n\n // search sub-folders\n const folders = entries.filter((entry) => entry.isDirectory());\n for (const folder of folders)\n files.push(...findFilesByName(fileName, fast, `${path}${folder.name}/`));\n\n return files;\n}\n\n/**\n * find all (nested) files in a directory\n *\n * @param directory directory to search\n * @returns list of files\n */\nexport async function readFilesRecursive(directory: string): Promise<string[]> {\n const items = await readdir(directory);\n\n const filePathsNested = await Promise.all(\n items.map(async (entity) => {\n const path = join(directory, entity);\n const isDirectory = (await lstat(path)).isDirectory();\n\n if (isDirectory) {\n return readFilesRecursive(path);\n }\n return path;\n })\n );\n\n return filePathsNested.flat();\n}\n"]}
@@ -1,5 +1,15 @@
1
1
  import { ScriptSkeleton } from '../../api/ApiTypes';
2
- export declare function validateScriptHooks(jsonData: object): boolean;
3
- export declare function validateScript(script: ScriptSkeleton): boolean;
4
- export declare function validateScriptDecoded(scriptSkeleton: ScriptSkeleton): boolean;
5
- export declare function isValidJs(javascriptSource: string): boolean;
2
+ import State from '../../shared/State';
3
+ export declare function validateScriptHooks({ jsonData, state, }: {
4
+ jsonData: object;
5
+ state: State;
6
+ }): boolean;
7
+ export declare function validateScript(script: ScriptSkeleton, state: State): boolean;
8
+ export declare function validateScriptDecoded({ scriptSkeleton, state, }: {
9
+ scriptSkeleton: ScriptSkeleton;
10
+ state: State;
11
+ }): boolean;
12
+ export declare function isValidJs({ javascriptSource, state, }: {
13
+ javascriptSource: string;
14
+ state: State;
15
+ }): boolean;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/ops/utils/ScriptValidationUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AASpD,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAc7D;AA0BD,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,GAAG,OAAO,CAO9D;AAED,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,cAAc,GAAG,OAAO,CAS7E;AAED,wBAAgB,SAAS,CAAC,gBAAgB,EAAE,MAAM,WASjD","file":"ScriptValidationUtils.d.ts","sourcesContent":["import { parseScript } from 'esprima';\nimport { ScriptSkeleton } from '../../api/ApiTypes';\nimport { decode } from '../../api/utils/Base64';\nimport { printMessage } from './Console';\n\ninterface ScriptHook {\n type: 'text/javascript';\n source?: string;\n}\n\nexport function validateScriptHooks(jsonData: object): boolean {\n const scriptHooks = findAllScriptHooks(jsonData);\n\n for (const scriptHook of scriptHooks) {\n if (!('source' in scriptHook)) {\n continue;\n }\n\n if (!isValidJs(scriptHook.source)) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction findAllScriptHooks(\n jsonData: unknown,\n scriptHooksArray: ScriptHook[] = []\n): ScriptHook[] {\n if (typeof jsonData !== 'object' || jsonData === null) {\n return scriptHooksArray;\n }\n\n for (const key in jsonData) {\n const item = jsonData[key];\n if (typeof item !== 'object' || item === null) {\n continue;\n }\n\n if ('type' in item && item.type === 'text/javascript') {\n scriptHooksArray.push(item);\n } else {\n findAllScriptHooks(item, scriptHooksArray);\n }\n }\n\n return scriptHooksArray;\n}\n\nexport function validateScript(script: ScriptSkeleton): boolean {\n const scriptRaw = decode(script.script);\n\n if (script.language === 'JAVASCRIPT') {\n return isValidJs(scriptRaw);\n }\n return true;\n}\n\nexport function validateScriptDecoded(scriptSkeleton: ScriptSkeleton): boolean {\n if (!Array.isArray(scriptSkeleton.script)) {\n return false;\n }\n if (scriptSkeleton.language === 'JAVASCRIPT') {\n const script = scriptSkeleton.script.join('\\n');\n return isValidJs(script);\n }\n return true;\n}\n\nexport function isValidJs(javascriptSource: string) {\n try {\n parseScript(javascriptSource);\n return true;\n } catch (e) {\n printMessage(`Invalid JavaScript: ${e.message}`, 'error');\n\n return false;\n }\n}\n"]}
1
+ {"version":3,"sources":["../src/ops/utils/ScriptValidationUtils.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGpD,OAAO,KAAK,MAAM,oBAAoB,CAAC;AAOvC,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EACR,KAAK,GACN,EAAE;IACD,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,OAAO,CAcV;AA0BD,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAO5E;AAED,wBAAgB,qBAAqB,CAAC,EACpC,cAAc,EACd,KAAK,GACN,EAAE;IACD,cAAc,EAAE,cAAc,CAAC;IAC/B,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,OAAO,CASV;AAED,wBAAgB,SAAS,CAAC,EACxB,gBAAgB,EAChB,KAAK,GACN,EAAE;IACD,gBAAgB,EAAE,MAAM,CAAC;IACzB,KAAK,EAAE,KAAK,CAAC;CACd,WAaA","file":"ScriptValidationUtils.d.ts","sourcesContent":["import { parseScript } from 'esprima';\nimport { ScriptSkeleton } from '../../api/ApiTypes';\nimport { decode } from '../../api/utils/Base64';\nimport { printMessage } from './Console';\nimport State from '../../shared/State';\n\ninterface ScriptHook {\n type: 'text/javascript';\n source?: string;\n}\n\nexport function validateScriptHooks({\n jsonData,\n state,\n}: {\n jsonData: object;\n state: State;\n}): boolean {\n const scriptHooks = findAllScriptHooks(jsonData);\n\n for (const scriptHook of scriptHooks) {\n if (!('source' in scriptHook)) {\n continue;\n }\n\n if (!isValidJs({ javascriptSource: scriptHook.source, state })) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction findAllScriptHooks(\n jsonData: unknown,\n scriptHooksArray: ScriptHook[] = []\n): ScriptHook[] {\n if (typeof jsonData !== 'object' || jsonData === null) {\n return scriptHooksArray;\n }\n\n for (const key in jsonData) {\n const item = jsonData[key];\n if (typeof item !== 'object' || item === null) {\n continue;\n }\n\n if ('type' in item && item.type === 'text/javascript') {\n scriptHooksArray.push(item);\n } else {\n findAllScriptHooks(item, scriptHooksArray);\n }\n }\n\n return scriptHooksArray;\n}\n\nexport function validateScript(script: ScriptSkeleton, state: State): boolean {\n const scriptRaw = decode(script.script);\n\n if (script.language === 'JAVASCRIPT') {\n return isValidJs({ javascriptSource: scriptRaw, state });\n }\n return true;\n}\n\nexport function validateScriptDecoded({\n scriptSkeleton,\n state,\n}: {\n scriptSkeleton: ScriptSkeleton;\n state: State;\n}): boolean {\n if (!Array.isArray(scriptSkeleton.script)) {\n return false;\n }\n if (scriptSkeleton.language === 'JAVASCRIPT') {\n const script = scriptSkeleton.script.join('\\n');\n return isValidJs({ javascriptSource: script, state });\n }\n return true;\n}\n\nexport function isValidJs({\n javascriptSource,\n state,\n}: {\n javascriptSource: string;\n state: State;\n}) {\n try {\n parseScript(javascriptSource);\n return true;\n } catch (e) {\n printMessage({\n message: `Invalid JavaScript: ${e.message}`,\n type: 'error',\n state,\n });\n\n return false;\n }\n}\n"]}
@@ -1,2 +1,6 @@
1
1
  import { Polly } from '@pollyjs/core';
2
- export declare function setupPollyForFrodoLib(matchRequestsBy?: any): Polly;
2
+ import State from '../shared/State';
3
+ export declare function setupPollyForFrodoLib({ matchRequestsBy, state, }: {
4
+ matchRequestsBy?: any;
5
+ state: State;
6
+ }): Polly;
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/SetupPollyForFrodoLib.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAmItC,wBAAgB,qBAAqB,CACnC,eAAe,MAA2B,GACzC,KAAK,CAsEP","file":"SetupPollyForFrodoLib.d.ts","sourcesContent":["import path from 'path';\nimport { fileURLToPath } from 'url';\nimport { Polly } from '@pollyjs/core';\nimport { MODES } from '@pollyjs/utils';\nimport NodeHttpAdapter from '@pollyjs/adapter-node-http';\nimport FSPersister from '@pollyjs/persister-fs';\nimport { LogLevelDesc } from 'loglevel';\nimport { debugMessage, printMessage } from '../ops/utils/Console';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst FRODO_MOCK_HOSTS = [\n 'https://openam-frodo-dev.forgeblocks.com',\n 'https://openam-service-accounts.forgeblocks.com',\n 'https://openam-volker-dev.forgeblocks.com',\n];\n\nlet recordIfMissing = false;\nlet mode = MODES.REPLAY;\n\n// resolve \"/home/sandeepc/work/ForgeRock/sources/frodo-lib/esm/api\" to\n// \"/home/sandeepc/work/ForgeRock/sources/frodo-lib/src/test/recordings\"\nconst recordingsDir = __dirname.replace(\n /^(.*\\/frodo-\\w{3})(.*)$/gi,\n '$1/mocks'\n);\n\nif (process.env.FRODO_MOCK) {\n Polly.register(NodeHttpAdapter);\n Polly.register(FSPersister);\n if (process.env.FRODO_MOCK === 'record') {\n mode = MODES.RECORD;\n recordIfMissing = true;\n }\n}\n\nfunction defaultMatchRequestsBy() {\n return JSON.parse(\n JSON.stringify({\n method: true,\n headers: false, // do not match headers, because \"Authorization\" header is sent only at recording time\n body: true,\n order: false,\n url: {\n protocol: false,\n username: false,\n password: false,\n hostname: false, // we will record from different envs but run tests always against `frodo-dev`\n port: false,\n pathname: true,\n query: true,\n hash: true,\n },\n })\n );\n}\n\nfunction authenticationMatchRequestsBy() {\n const matchRequestsBy = defaultMatchRequestsBy();\n matchRequestsBy.body = false;\n matchRequestsBy.order = true;\n return matchRequestsBy;\n}\n\n// returns a delayed promise\nasync function delay(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function countdown(ms) {\n await delay(ms);\n return --ttl;\n}\n\nconst timeout = 15;\nlet ttl = timeout;\nasync function scheduleShutdown(polly: Polly) {\n ++ttl;\n while (await countdown(1000)) {\n if (ttl < 4)\n console.log(\n `Polly instance '${getFrodoCommand()}' stopping in ${ttl}s...`\n );\n }\n await polly.stop();\n console.log(`Polly instance '${getFrodoCommand()}' stopped.`);\n}\n\n/*\nargv:\n[\n '/Users/vscheuber/.nvm/versions/node/v18.7.0/bin/node',\n '/usr/local/bin/frodo',\n 'journey',\n 'list',\n '-l',\n 'https://openam-volker-dev.forgeblocks.com/am',\n 'alpha',\n 'volker.scheuber@forgerock.com',\n 'Sup3rS3cr3t!'\n]\nargv:\n[\n '/Users/vscheuber/.nvm/versions/node/v18.7.0/bin/node',\n '/Users/vscheuber/Projects/frodo-cli/esm/cli/journey/journey-list.js',\n '-l',\n 'https://openam-volker-dev.forgeblocks.com/am',\n 'alpha',\n 'volker.scheuber@forgerock.com',\n 'Sup3rS3cr3t!'\n]\n*/\nfunction getFrodoCommand() {\n try {\n if (mode !== MODES.RECORD)\n debugMessage(\n `SetupPollyForFrodoLib.getFrodoCommand: process.argv=${process.argv}`\n );\n if (\n !process.argv[1].endsWith('frodo') &&\n !process.argv[1].endsWith('frodo.exe') &&\n !process.argv[1].endsWith('app.js')\n ) {\n return path.parse(process.argv[1]).name.replace('-', '/');\n }\n return process.argv[2];\n } catch (error) {\n printMessage(`SetupPollyForFrodoLib.getFrodoCommand: ${error}`, 'error');\n printMessage(process.argv, 'error');\n return 'error';\n }\n}\n\nexport function setupPollyForFrodoLib(\n matchRequestsBy = defaultMatchRequestsBy()\n): Polly {\n const polly = new Polly('default');\n\n polly.configure({\n adapters: ['node-http'],\n mode,\n recordIfMissing,\n flushRequestsOnStop: true,\n logLevel: (process.env.FRODO_POLLY_LOG_LEVEL as LogLevelDesc) || 'warn',\n recordFailedRequests: true,\n persister: 'fs',\n persisterOptions: {\n fs: {\n recordingsDir,\n },\n },\n matchRequestsBy,\n });\n\n for (const host of FRODO_MOCK_HOSTS) {\n if (mode === MODES.RECORD) console.log(`***** Host: ${host}`);\n polly.server.host(host, () => {\n polly.server\n .any('/am/oauth2/*')\n .recordingName(`${getFrodoCommand()}/oauth2`)\n .on('request', (req) => {\n req.configure({ matchRequestsBy: authenticationMatchRequestsBy() });\n });\n polly.server.any('/am/json/*').recordingName(`${getFrodoCommand()}/am`);\n polly.server\n .any('/openidm/*')\n .recordingName(`${getFrodoCommand()}/openidm`);\n polly.server\n .any('/environment/*')\n .recordingName(`${getFrodoCommand()}/environment`);\n polly.server\n .any('/monitoring/*')\n .recordingName(`${getFrodoCommand()}/monitoring`);\n polly.server\n .any('/feature')\n .recordingName(`${getFrodoCommand()}/feature`);\n polly.server\n .any('/dashboard/*')\n .recordingName(`${getFrodoCommand()}/dashboard`);\n });\n }\n polly.server.host('https://api.github.com', () => {\n polly.server.any('/*').recordingName(`github`);\n });\n polly.server.host('https://registry.npmjs.org', () => {\n polly.server.any('/*').recordingName(`npmjs`);\n });\n polly.server.any().on('request', () => {\n if (ttl < timeout) {\n // console.log(`Reset polly stop ttl (${ttl}) to ${timeout}`);\n ttl = timeout;\n }\n });\n\n if (mode === MODES.RECORD) {\n scheduleShutdown(polly);\n } else {\n // only output debug messages if not recording as this polly instance is\n // primarily used by frodo-cli e2e tests, which capture stdout in snapshots.\n // debug messages falsify the snapshot recordings.\n debugMessage(`Polly config:`);\n debugMessage(polly.config);\n }\n\n return polly;\n}\n"]}
1
+ {"version":3,"sources":["../src/utils/SetupPollyForFrodoLib.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAMtC,OAAO,KAAK,MAAM,iBAAiB,CAAC;AAyIpC,wBAAgB,qBAAqB,CAAC,EACpC,eAA0C,EAC1C,KAAK,GACN,EAAE;IACD,eAAe,CAAC,EAAE,GAAG,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;CACd,GAAG,KAAK,CAwER","file":"SetupPollyForFrodoLib.d.ts","sourcesContent":["import path from 'path';\nimport { fileURLToPath } from 'url';\nimport { Polly } from '@pollyjs/core';\nimport { MODES } from '@pollyjs/utils';\nimport NodeHttpAdapter from '@pollyjs/adapter-node-http';\nimport FSPersister from '@pollyjs/persister-fs';\nimport { LogLevelDesc } from 'loglevel';\nimport { debugMessage, printMessage } from '../ops/utils/Console';\nimport State from '../shared/State';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst FRODO_MOCK_HOSTS = [\n 'https://openam-frodo-dev.forgeblocks.com',\n 'https://openam-service-accounts.forgeblocks.com',\n 'https://openam-volker-dev.forgeblocks.com',\n];\n\nlet recordIfMissing = false;\nlet mode = MODES.REPLAY;\n\n// resolve \"/home/sandeepc/work/ForgeRock/sources/frodo-lib/esm/api\" to\n// \"/home/sandeepc/work/ForgeRock/sources/frodo-lib/src/test/recordings\"\nconst recordingsDir = __dirname.replace(\n /^(.*\\/frodo-\\w{3})(.*)$/gi,\n '$1/mocks'\n);\n\nif (process.env.FRODO_MOCK) {\n Polly.register(NodeHttpAdapter);\n Polly.register(FSPersister);\n if (process.env.FRODO_MOCK === 'record') {\n mode = MODES.RECORD;\n recordIfMissing = true;\n }\n}\n\nfunction defaultMatchRequestsBy() {\n return JSON.parse(\n JSON.stringify({\n method: true,\n headers: false, // do not match headers, because \"Authorization\" header is sent only at recording time\n body: true,\n order: false,\n url: {\n protocol: false,\n username: false,\n password: false,\n hostname: false, // we will record from different envs but run tests always against `frodo-dev`\n port: false,\n pathname: true,\n query: true,\n hash: true,\n },\n })\n );\n}\n\nfunction authenticationMatchRequestsBy() {\n const matchRequestsBy = defaultMatchRequestsBy();\n matchRequestsBy.body = false;\n matchRequestsBy.order = true;\n return matchRequestsBy;\n}\n\n// returns a delayed promise\nasync function delay(ms) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nasync function countdown(ms) {\n await delay(ms);\n return --ttl;\n}\n\nconst timeout = 15;\nlet ttl = timeout;\nasync function scheduleShutdown({\n polly,\n state,\n}: {\n polly: Polly;\n state: State;\n}) {\n ++ttl;\n while (await countdown(1000)) {\n if (ttl < 4)\n console.log(\n `Polly instance '${getFrodoCommand({ state })}' stopping in ${ttl}s...`\n );\n }\n await polly.stop();\n console.log(`Polly instance '${getFrodoCommand({ state })}' stopped.`);\n}\n\n/*\nargv:\n[\n '/Users/vscheuber/.nvm/versions/node/v18.7.0/bin/node',\n '/usr/local/bin/frodo',\n 'journey',\n 'list',\n '-l',\n 'https://openam-volker-dev.forgeblocks.com/am',\n 'alpha',\n 'volker.scheuber@forgerock.com',\n 'Sup3rS3cr3t!'\n]\nargv:\n[\n '/Users/vscheuber/.nvm/versions/node/v18.7.0/bin/node',\n '/Users/vscheuber/Projects/frodo-cli/esm/cli/journey/journey-list.js',\n '-l',\n 'https://openam-volker-dev.forgeblocks.com/am',\n 'alpha',\n 'volker.scheuber@forgerock.com',\n 'Sup3rS3cr3t!'\n]\n*/\nfunction getFrodoCommand({ state }: { state: State }) {\n try {\n if (mode !== MODES.RECORD)\n debugMessage({\n message: `SetupPollyForFrodoLib.getFrodoCommand: process.argv=${process.argv}`,\n state,\n });\n if (\n !process.argv[1].endsWith('frodo') &&\n !process.argv[1].endsWith('frodo.exe') &&\n !process.argv[1].endsWith('app.js')\n ) {\n return path.parse(process.argv[1]).name.replace('-', '/');\n }\n return process.argv[2];\n } catch (error) {\n printMessage({\n message: `SetupPollyForFrodoLib.getFrodoCommand: ${error}`,\n type: 'error',\n state,\n });\n printMessage({ message: process.argv, type: 'error', state });\n return 'error';\n }\n}\n\nexport function setupPollyForFrodoLib({\n matchRequestsBy = defaultMatchRequestsBy(),\n state,\n}: {\n matchRequestsBy?: any;\n state: State;\n}): Polly {\n const polly = new Polly('default');\n\n polly.configure({\n adapters: ['node-http'],\n mode,\n recordIfMissing,\n flushRequestsOnStop: true,\n logLevel: (process.env.FRODO_POLLY_LOG_LEVEL as LogLevelDesc) || 'warn',\n recordFailedRequests: true,\n persister: 'fs',\n persisterOptions: {\n fs: {\n recordingsDir,\n },\n },\n matchRequestsBy,\n });\n\n for (const host of FRODO_MOCK_HOSTS) {\n if (mode === MODES.RECORD) console.log(`***** Host: ${host}`);\n polly.server.host(host, () => {\n polly.server\n .any('/am/oauth2/*')\n .recordingName(`${getFrodoCommand({ state })}/oauth2`)\n .on('request', (req) => {\n req.configure({ matchRequestsBy: authenticationMatchRequestsBy() });\n });\n polly.server\n .any('/am/json/*')\n .recordingName(`${getFrodoCommand({ state })}/am`);\n polly.server\n .any('/openidm/*')\n .recordingName(`${getFrodoCommand({ state })}/openidm`);\n polly.server\n .any('/environment/*')\n .recordingName(`${getFrodoCommand({ state })}/environment`);\n polly.server\n .any('/monitoring/*')\n .recordingName(`${getFrodoCommand({ state })}/monitoring`);\n polly.server\n .any('/feature')\n .recordingName(`${getFrodoCommand({ state })}/feature`);\n polly.server\n .any('/dashboard/*')\n .recordingName(`${getFrodoCommand({ state })}/dashboard`);\n });\n }\n polly.server.host('https://api.github.com', () => {\n polly.server.any('/*').recordingName(`github`);\n });\n polly.server.host('https://registry.npmjs.org', () => {\n polly.server.any('/*').recordingName(`npmjs`);\n });\n polly.server.any().on('request', () => {\n if (ttl < timeout) {\n // console.log(`Reset polly stop ttl (${ttl}) to ${timeout}`);\n ttl = timeout;\n }\n });\n\n if (mode === MODES.RECORD) {\n scheduleShutdown({ polly, state });\n } else {\n // only output debug messages if not recording as this polly instance is\n // primarily used by frodo-cli e2e tests, which capture stdout in snapshots.\n // debug messages falsify the snapshot recordings.\n debugMessage({ message: `Polly config:`, state });\n debugMessage({ message: polly.config, state });\n }\n\n return polly;\n}\n"]}