appmap 0.62.0 → 0.62.1
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +4 -0
- data/lib/appmap/version.rb +1 -1
- data/node_modules/@appland/cli/CHANGELOG.md +96 -0
- data/node_modules/@appland/cli/package.json +49 -0
- data/node_modules/@appland/cli/src/appMapCatalog.js +39 -0
- data/node_modules/@appland/cli/src/appland/getAppMap.js +55 -0
- data/node_modules/@appland/cli/src/appland/listAppMaps.js +58 -0
- data/node_modules/@appland/cli/src/appland/settings.js +62 -0
- data/node_modules/@appland/cli/src/appland/types.d.ts +16 -0
- data/node_modules/@appland/cli/src/cli.js +576 -0
- data/node_modules/@appland/cli/src/database.js +197 -0
- data/node_modules/@appland/cli/src/depends.js +157 -0
- data/node_modules/@appland/cli/src/fingerprint/algorithms.js +71 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize.js +70 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/base.js +58 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/classDependencies.js +36 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/classes.js +14 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/eventTree.js +19 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/httpClientRequests.js +18 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/httpServerRequests.js +18 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/info.js +55 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/labels.js +10 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/packageDependencies.js +36 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/packages.js +14 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/sqlNormalized.js +19 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/sqlTables.js +24 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/trace.js +57 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/unique.js +8 -0
- data/node_modules/@appland/cli/src/fingerprint/canonicalize/update.js +85 -0
- data/node_modules/@appland/cli/src/fingerprint/fingerprintDirectoryCommand.js +30 -0
- data/node_modules/@appland/cli/src/fingerprint/fingerprintQueue.js +30 -0
- data/node_modules/@appland/cli/src/fingerprint/fingerprintWatchCommand.js +64 -0
- data/node_modules/@appland/cli/src/fingerprint/fingerprinter.js +186 -0
- data/node_modules/@appland/cli/src/fingerprint/index.js +24 -0
- data/node_modules/@appland/cli/src/functionStats.js +168 -0
- data/node_modules/@appland/cli/src/inspect.js +7 -0
- data/node_modules/@appland/cli/src/inspect/fields.js +66 -0
- data/node_modules/@appland/cli/src/inspect/filter.js +105 -0
- data/node_modules/@appland/cli/src/inspect/home.js +64 -0
- data/node_modules/@appland/cli/src/inspect/print.js +231 -0
- data/node_modules/@appland/cli/src/inspect/reset.js +10 -0
- data/node_modules/@appland/cli/src/inspect/types.d.ts +11 -0
- data/node_modules/@appland/cli/src/inspect/undoFilter.js +10 -0
- data/node_modules/@appland/cli/src/inventoryCommand.js +59 -0
- data/node_modules/@appland/cli/src/search/codeObjectMatcher.js +75 -0
- data/node_modules/@appland/cli/src/search/constants.js +5 -0
- data/node_modules/@appland/cli/src/search/findCodeObjects.js +293 -0
- data/node_modules/@appland/cli/src/search/findEvents.js +184 -0
- data/node_modules/@appland/cli/src/search/matchFilter.js +65 -0
- data/node_modules/@appland/cli/src/search/matchSpec.js +198 -0
- data/node_modules/@appland/cli/src/search/trigram.js +107 -0
- data/node_modules/@appland/cli/src/search/types.d.ts +107 -0
- data/node_modules/@appland/cli/src/search/utils.js +4 -0
- data/node_modules/@appland/cli/src/swagger/README.md +75 -0
- data/node_modules/@appland/cli/src/swagger/command.js +42 -0
- data/node_modules/@appland/cli/src/swagger/method.js +173 -0
- data/node_modules/@appland/cli/src/swagger/model.js +54 -0
- data/node_modules/@appland/cli/src/swagger/path.js +38 -0
- data/node_modules/@appland/cli/src/swagger/response.js +34 -0
- data/node_modules/@appland/cli/src/swagger/schema.js +38 -0
- data/node_modules/@appland/cli/src/swagger/securitySchemes.js +60 -0
- data/node_modules/@appland/cli/src/swagger/settings.js +9 -0
- data/node_modules/@appland/cli/src/swagger/util.js +79 -0
- data/node_modules/@appland/cli/src/utils.js +164 -0
- data/node_modules/@appland/cli/tests/unit/depends.spec.js +55 -0
- data/node_modules/@appland/cli/tests/unit/fingerprint/canonicalize.spec.js +42 -0
- data/node_modules/@appland/cli/tests/unit/fingerprint/sql.spec.js +40 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/app/controllers/organizations_controller.rb +1 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/app/models/configuration.rb +1 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/app/models/show.rb +1 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/app/models/user.rb +1 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/canonicalize/revoke_api_key.info.json +246 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/canonicalize/revoke_api_key.trace.json +289 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/canonicalize/revoke_api_key.update.json +78 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/revoke_api_key.appmap.json +899 -0
- data/node_modules/@appland/cli/tests/unit/fixtures/user_page_scenario.appmap.json +1774 -0
- data/node_modules/@appland/cli/tests/unit/inspect.spec.js +94 -0
- data/node_modules/@appland/models/CHANGELOG.md +83 -0
- data/node_modules/@appland/models/README.md +8 -0
- data/node_modules/@appland/models/dist/index.cjs +4250 -0
- data/node_modules/@appland/models/dist/index.js +4193 -0
- data/node_modules/@appland/models/package.json +50 -0
- data/node_modules/@rollup/plugin-alias/CHANGELOG.md +92 -0
- data/node_modules/@rollup/plugin-alias/LICENSE +21 -0
- data/node_modules/@rollup/plugin-alias/README.md +174 -0
- data/node_modules/@rollup/plugin-alias/dist/index.es.js +95 -0
- data/node_modules/@rollup/plugin-alias/dist/index.js +101 -0
- data/node_modules/@rollup/plugin-alias/package.json +78 -0
- data/node_modules/@rollup/plugin-alias/types/index.d.ts +36 -0
- data/node_modules/ansi-regex/index.d.ts +37 -0
- data/node_modules/ansi-regex/index.js +10 -0
- data/node_modules/ansi-regex/license +9 -0
- data/node_modules/ansi-regex/package.json +55 -0
- data/node_modules/ansi-regex/readme.md +78 -0
- data/node_modules/ansi-styles/index.d.ts +345 -0
- data/node_modules/ansi-styles/index.js +163 -0
- data/node_modules/ansi-styles/license +9 -0
- data/node_modules/ansi-styles/package.json +56 -0
- data/node_modules/ansi-styles/readme.md +152 -0
- data/node_modules/anymatch/LICENSE +15 -0
- data/node_modules/anymatch/README.md +87 -0
- data/node_modules/anymatch/index.d.ts +19 -0
- data/node_modules/anymatch/index.js +104 -0
- data/node_modules/anymatch/package.json +48 -0
- data/node_modules/argparse/CHANGELOG.md +185 -0
- data/node_modules/argparse/LICENSE +21 -0
- data/node_modules/argparse/README.md +257 -0
- data/node_modules/argparse/index.js +3 -0
- data/node_modules/argparse/lib/action.js +146 -0
- data/node_modules/argparse/lib/action/append.js +53 -0
- data/node_modules/argparse/lib/action/append/constant.js +47 -0
- data/node_modules/argparse/lib/action/count.js +40 -0
- data/node_modules/argparse/lib/action/help.js +47 -0
- data/node_modules/argparse/lib/action/store.js +50 -0
- data/node_modules/argparse/lib/action/store/constant.js +43 -0
- data/node_modules/argparse/lib/action/store/false.js +27 -0
- data/node_modules/argparse/lib/action/store/true.js +26 -0
- data/node_modules/argparse/lib/action/subparsers.js +149 -0
- data/node_modules/argparse/lib/action/version.js +47 -0
- data/node_modules/argparse/lib/action_container.js +482 -0
- data/node_modules/argparse/lib/argparse.js +14 -0
- data/node_modules/argparse/lib/argument/error.js +50 -0
- data/node_modules/argparse/lib/argument/exclusive.js +54 -0
- data/node_modules/argparse/lib/argument/group.js +75 -0
- data/node_modules/argparse/lib/argument_parser.js +1161 -0
- data/node_modules/argparse/lib/const.js +21 -0
- data/node_modules/argparse/lib/help/added_formatters.js +87 -0
- data/node_modules/argparse/lib/help/formatter.js +795 -0
- data/node_modules/argparse/lib/namespace.js +76 -0
- data/node_modules/argparse/lib/utils.js +57 -0
- data/node_modules/argparse/package.json +34 -0
- data/node_modules/async/CHANGELOG.md +331 -0
- data/node_modules/async/LICENSE +19 -0
- data/node_modules/async/README.md +60 -0
- data/node_modules/async/all.js +54 -0
- data/node_modules/async/allLimit.js +46 -0
- data/node_modules/async/allSeries.js +45 -0
- data/node_modules/async/any.js +56 -0
- data/node_modules/async/anyLimit.js +47 -0
- data/node_modules/async/anySeries.js +46 -0
- data/node_modules/async/apply.js +55 -0
- data/node_modules/async/applyEach.js +57 -0
- data/node_modules/async/applyEachSeries.js +37 -0
- data/node_modules/async/asyncify.js +118 -0
- data/node_modules/async/auto.js +267 -0
- data/node_modules/async/autoInject.js +156 -0
- data/node_modules/async/bower.json +17 -0
- data/node_modules/async/cargo.js +63 -0
- data/node_modules/async/cargoQueue.js +71 -0
- data/node_modules/async/compose.js +55 -0
- data/node_modules/async/concat.js +47 -0
- data/node_modules/async/concatLimit.js +60 -0
- data/node_modules/async/concatSeries.js +41 -0
- data/node_modules/async/constant.js +55 -0
- data/node_modules/async/detect.js +61 -0
- data/node_modules/async/detectLimit.js +48 -0
- data/node_modules/async/detectSeries.js +47 -0
- data/node_modules/async/dir.js +43 -0
- data/node_modules/async/dist/async.js +4846 -0
- data/node_modules/async/dist/async.min.js +1 -0
- data/node_modules/async/dist/async.mjs +4734 -0
- data/node_modules/async/doDuring.js +68 -0
- data/node_modules/async/doUntil.js +46 -0
- data/node_modules/async/doWhilst.js +68 -0
- data/node_modules/async/during.js +78 -0
- data/node_modules/async/each.js +88 -0
- data/node_modules/async/eachLimit.js +50 -0
- data/node_modules/async/eachOf.js +116 -0
- data/node_modules/async/eachOfLimit.js +47 -0
- data/node_modules/async/eachOfSeries.js +39 -0
- data/node_modules/async/eachSeries.js +44 -0
- data/node_modules/async/ensureAsync.js +67 -0
- data/node_modules/async/every.js +54 -0
- data/node_modules/async/everyLimit.js +46 -0
- data/node_modules/async/everySeries.js +45 -0
- data/node_modules/async/filter.js +53 -0
- data/node_modules/async/filterLimit.js +45 -0
- data/node_modules/async/filterSeries.js +43 -0
- data/node_modules/async/find.js +61 -0
- data/node_modules/async/findLimit.js +48 -0
- data/node_modules/async/findSeries.js +47 -0
- data/node_modules/async/flatMap.js +47 -0
- data/node_modules/async/flatMapLimit.js +60 -0
- data/node_modules/async/flatMapSeries.js +41 -0
- data/node_modules/async/foldl.js +77 -0
- data/node_modules/async/foldr.js +41 -0
- data/node_modules/async/forEach.js +88 -0
- data/node_modules/async/forEachLimit.js +50 -0
- data/node_modules/async/forEachOf.js +116 -0
- data/node_modules/async/forEachOfLimit.js +47 -0
- data/node_modules/async/forEachOfSeries.js +39 -0
- data/node_modules/async/forEachSeries.js +44 -0
- data/node_modules/async/forever.js +68 -0
- data/node_modules/async/groupBy.js +54 -0
- data/node_modules/async/groupByLimit.js +71 -0
- data/node_modules/async/groupBySeries.js +36 -0
- data/node_modules/async/index.js +588 -0
- data/node_modules/async/inject.js +77 -0
- data/node_modules/async/internal/DoublyLinkedList.js +92 -0
- data/node_modules/async/internal/Heap.js +120 -0
- data/node_modules/async/internal/applyEach.js +29 -0
- data/node_modules/async/internal/asyncEachOfLimit.js +75 -0
- data/node_modules/async/internal/awaitify.js +27 -0
- data/node_modules/async/internal/breakLoop.js +10 -0
- data/node_modules/async/internal/consoleFunc.js +27 -0
- data/node_modules/async/internal/createTester.js +40 -0
- data/node_modules/async/internal/eachOfLimit.js +90 -0
- data/node_modules/async/internal/filter.js +55 -0
- data/node_modules/async/internal/getIterator.js +11 -0
- data/node_modules/async/internal/initialParams.js +14 -0
- data/node_modules/async/internal/isArrayLike.js +10 -0
- data/node_modules/async/internal/iterator.js +54 -0
- data/node_modules/async/internal/map.js +30 -0
- data/node_modules/async/internal/once.js +17 -0
- data/node_modules/async/internal/onlyOnce.js +15 -0
- data/node_modules/async/internal/parallel.js +34 -0
- data/node_modules/async/internal/promiseCallback.js +23 -0
- data/node_modules/async/internal/queue.js +291 -0
- data/node_modules/async/internal/range.js +14 -0
- data/node_modules/async/internal/reject.js +26 -0
- data/node_modules/async/internal/setImmediate.js +30 -0
- data/node_modules/async/internal/withoutIndex.js +10 -0
- data/node_modules/async/internal/wrapAsync.js +34 -0
- data/node_modules/async/log.js +41 -0
- data/node_modules/async/map.js +62 -0
- data/node_modules/async/mapLimit.js +45 -0
- data/node_modules/async/mapSeries.js +44 -0
- data/node_modules/async/mapValues.js +62 -0
- data/node_modules/async/mapValuesLimit.js +61 -0
- data/node_modules/async/mapValuesSeries.js +37 -0
- data/node_modules/async/memoize.js +91 -0
- data/node_modules/async/nextTick.js +52 -0
- data/node_modules/async/package.json +82 -0
- data/node_modules/async/parallel.js +91 -0
- data/node_modules/async/parallelLimit.js +41 -0
- data/node_modules/async/priorityQueue.js +84 -0
- data/node_modules/async/queue.js +167 -0
- data/node_modules/async/race.js +67 -0
- data/node_modules/async/reduce.js +77 -0
- data/node_modules/async/reduceRight.js +41 -0
- data/node_modules/async/reflect.js +78 -0
- data/node_modules/async/reflectAll.js +93 -0
- data/node_modules/async/reject.js +53 -0
- data/node_modules/async/rejectLimit.js +45 -0
- data/node_modules/async/rejectSeries.js +43 -0
- data/node_modules/async/retry.js +159 -0
- data/node_modules/async/retryable.js +77 -0
- data/node_modules/async/select.js +53 -0
- data/node_modules/async/selectLimit.js +45 -0
- data/node_modules/async/selectSeries.js +43 -0
- data/node_modules/async/seq.js +79 -0
- data/node_modules/async/series.js +86 -0
- data/node_modules/async/setImmediate.js +45 -0
- data/node_modules/async/some.js +56 -0
- data/node_modules/async/someLimit.js +47 -0
- data/node_modules/async/someSeries.js +46 -0
- data/node_modules/async/sortBy.js +88 -0
- data/node_modules/async/timeout.js +89 -0
- data/node_modules/async/times.js +50 -0
- data/node_modules/async/timesLimit.js +43 -0
- data/node_modules/async/timesSeries.js +32 -0
- data/node_modules/async/transform.js +81 -0
- data/node_modules/async/tryEach.js +78 -0
- data/node_modules/async/unmemoize.js +25 -0
- data/node_modules/async/until.js +61 -0
- data/node_modules/async/waterfall.js +105 -0
- data/node_modules/async/whilst.js +78 -0
- data/node_modules/async/wrapSync.js +118 -0
- data/node_modules/at-least-node/LICENSE +6 -0
- data/node_modules/at-least-node/README.md +25 -0
- data/node_modules/at-least-node/index.js +5 -0
- data/node_modules/at-least-node/package.json +32 -0
- data/node_modules/balanced-match/LICENSE.md +21 -0
- data/node_modules/balanced-match/README.md +97 -0
- data/node_modules/balanced-match/index.js +62 -0
- data/node_modules/balanced-match/package.json +48 -0
- data/node_modules/binary-extensions/binary-extensions.json +260 -0
- data/node_modules/binary-extensions/binary-extensions.json.d.ts +3 -0
- data/node_modules/binary-extensions/index.d.ts +14 -0
- data/node_modules/binary-extensions/index.js +1 -0
- data/node_modules/binary-extensions/license +9 -0
- data/node_modules/binary-extensions/package.json +38 -0
- data/node_modules/binary-extensions/readme.md +41 -0
- data/node_modules/brace-expansion/LICENSE +21 -0
- data/node_modules/brace-expansion/README.md +129 -0
- data/node_modules/brace-expansion/index.js +201 -0
- data/node_modules/brace-expansion/package.json +47 -0
- data/node_modules/braces/CHANGELOG.md +184 -0
- data/node_modules/braces/LICENSE +21 -0
- data/node_modules/braces/README.md +593 -0
- data/node_modules/braces/index.js +170 -0
- data/node_modules/braces/lib/compile.js +57 -0
- data/node_modules/braces/lib/constants.js +57 -0
- data/node_modules/braces/lib/expand.js +113 -0
- data/node_modules/braces/lib/parse.js +333 -0
- data/node_modules/braces/lib/stringify.js +32 -0
- data/node_modules/braces/lib/utils.js +112 -0
- data/node_modules/braces/package.json +77 -0
- data/node_modules/chokidar/LICENSE +21 -0
- data/node_modules/chokidar/README.md +308 -0
- data/node_modules/chokidar/index.js +973 -0
- data/node_modules/chokidar/lib/constants.js +65 -0
- data/node_modules/chokidar/lib/fsevents-handler.js +524 -0
- data/node_modules/chokidar/lib/nodefs-handler.js +646 -0
- data/node_modules/chokidar/package.json +78 -0
- data/node_modules/chokidar/types/index.d.ts +187 -0
- data/node_modules/cli-progress/CHANGES.md +169 -0
- data/node_modules/cli-progress/LICENSE.md +24 -0
- data/node_modules/cli-progress/README.md +446 -0
- data/node_modules/cli-progress/cli-progress.js +21 -0
- data/node_modules/cli-progress/lib/eta.js +73 -0
- data/node_modules/cli-progress/lib/format-bar.js +11 -0
- data/node_modules/cli-progress/lib/format-time.js +34 -0
- data/node_modules/cli-progress/lib/format-value.js +22 -0
- data/node_modules/cli-progress/lib/formatter.js +80 -0
- data/node_modules/cli-progress/lib/generic-bar.js +212 -0
- data/node_modules/cli-progress/lib/multi-bar.js +201 -0
- data/node_modules/cli-progress/lib/options.js +95 -0
- data/node_modules/cli-progress/lib/single-bar.js +124 -0
- data/node_modules/cli-progress/lib/terminal.js +159 -0
- data/node_modules/cli-progress/package.json +46 -0
- data/node_modules/cli-progress/presets/index.js +11 -0
- data/node_modules/cli-progress/presets/legacy.js +6 -0
- data/node_modules/cli-progress/presets/rect.js +5 -0
- data/node_modules/cli-progress/presets/shades-classic.js +6 -0
- data/node_modules/cli-progress/presets/shades-grey.js +8 -0
- data/node_modules/cliui/CHANGELOG.md +121 -0
- data/node_modules/cliui/LICENSE.txt +14 -0
- data/node_modules/cliui/README.md +141 -0
- data/node_modules/cliui/build/index.cjs +302 -0
- data/node_modules/cliui/build/lib/index.js +287 -0
- data/node_modules/cliui/build/lib/string-utils.js +27 -0
- data/node_modules/cliui/index.mjs +13 -0
- data/node_modules/cliui/package.json +83 -0
- data/node_modules/color-convert/CHANGELOG.md +54 -0
- data/node_modules/color-convert/LICENSE +21 -0
- data/node_modules/color-convert/README.md +68 -0
- data/node_modules/color-convert/conversions.js +839 -0
- data/node_modules/color-convert/index.js +81 -0
- data/node_modules/color-convert/package.json +48 -0
- data/node_modules/color-convert/route.js +97 -0
- data/node_modules/color-name/LICENSE +8 -0
- data/node_modules/color-name/README.md +11 -0
- data/node_modules/color-name/index.js +152 -0
- data/node_modules/color-name/package.json +28 -0
- data/node_modules/colors/LICENSE +25 -0
- data/node_modules/colors/README.md +221 -0
- data/node_modules/colors/examples/normal-usage.js +82 -0
- data/node_modules/colors/examples/safe-string.js +79 -0
- data/node_modules/colors/index.d.ts +136 -0
- data/node_modules/colors/lib/colors.js +211 -0
- data/node_modules/colors/lib/custom/trap.js +46 -0
- data/node_modules/colors/lib/custom/zalgo.js +110 -0
- data/node_modules/colors/lib/extendStringPrototype.js +110 -0
- data/node_modules/colors/lib/index.js +13 -0
- data/node_modules/colors/lib/maps/america.js +10 -0
- data/node_modules/colors/lib/maps/rainbow.js +12 -0
- data/node_modules/colors/lib/maps/random.js +11 -0
- data/node_modules/colors/lib/maps/zebra.js +5 -0
- data/node_modules/colors/lib/styles.js +95 -0
- data/node_modules/colors/lib/system/has-flag.js +35 -0
- data/node_modules/colors/lib/system/supports-colors.js +151 -0
- data/node_modules/colors/package.json +45 -0
- data/node_modules/colors/safe.d.ts +48 -0
- data/node_modules/colors/safe.js +10 -0
- data/node_modules/colors/themes/generic-logging.js +12 -0
- data/node_modules/concat-map/LICENSE +18 -0
- data/node_modules/concat-map/README.markdown +62 -0
- data/node_modules/concat-map/example/map.js +6 -0
- data/node_modules/concat-map/index.js +13 -0
- data/node_modules/concat-map/package.json +43 -0
- data/node_modules/concat-map/test/map.js +39 -0
- data/node_modules/console-table-printer/CHANGELOG.md +96 -0
- data/node_modules/console-table-printer/LICENSE +21 -0
- data/node_modules/console-table-printer/README.md +180 -0
- data/node_modules/console-table-printer/dist/index.d.ts +4 -0
- data/node_modules/console-table-printer/dist/index.js +10 -0
- data/node_modules/console-table-printer/dist/src/console-table-printer.d.ts +14 -0
- data/node_modules/console-table-printer/dist/src/console-table-printer.js +32 -0
- data/node_modules/console-table-printer/dist/src/internalTable/input-converter.d.ts +6 -0
- data/node_modules/console-table-printer/dist/src/internalTable/input-converter.js +15 -0
- data/node_modules/console-table-printer/dist/src/internalTable/internal-table-printer.d.ts +4 -0
- data/node_modules/console-table-printer/dist/src/internalTable/internal-table-printer.js +115 -0
- data/node_modules/console-table-printer/dist/src/internalTable/internal-table.d.ts +25 -0
- data/node_modules/console-table-printer/dist/src/internalTable/internal-table.js +80 -0
- data/node_modules/console-table-printer/dist/src/internalTable/table-pre-processors.d.ts +3 -0
- data/node_modules/console-table-printer/dist/src/internalTable/table-pre-processors.js +43 -0
- data/node_modules/console-table-printer/dist/src/models/common.d.ts +10 -0
- data/node_modules/console-table-printer/dist/src/models/common.js +2 -0
- data/node_modules/console-table-printer/dist/src/models/external-table.d.ts +26 -0
- data/node_modules/console-table-printer/dist/src/models/external-table.js +2 -0
- data/node_modules/console-table-printer/dist/src/models/internal-table.d.ts +21 -0
- data/node_modules/console-table-printer/dist/src/models/internal-table.js +2 -0
- data/node_modules/console-table-printer/dist/src/utils/colored-console-line.d.ts +8 -0
- data/node_modules/console-table-printer/dist/src/utils/colored-console-line.js +29 -0
- data/node_modules/console-table-printer/dist/src/utils/console-utils.d.ts +2 -0
- data/node_modules/console-table-printer/dist/src/utils/console-utils.js +8 -0
- data/node_modules/console-table-printer/dist/src/utils/string-utils.d.ts +4 -0
- data/node_modules/console-table-printer/dist/src/utils/string-utils.js +54 -0
- data/node_modules/console-table-printer/dist/src/utils/table-constants.d.ts +10 -0
- data/node_modules/console-table-printer/dist/src/utils/table-constants.js +49 -0
- data/node_modules/console-table-printer/dist/src/utils/table-helpers.d.ts +26 -0
- data/node_modules/console-table-printer/dist/src/utils/table-helpers.js +91 -0
- data/node_modules/console-table-printer/package.json +51 -0
- data/node_modules/cross-env/CHANGELOG.md +5 -0
- data/node_modules/cross-env/LICENSE +20 -0
- data/node_modules/cross-env/README.md +291 -0
- data/node_modules/cross-env/package.json +54 -0
- data/node_modules/cross-env/src/bin/cross-env-shell.js +5 -0
- data/node_modules/cross-env/src/bin/cross-env.js +5 -0
- data/node_modules/cross-env/src/command.js +32 -0
- data/node_modules/cross-env/src/index.js +95 -0
- data/node_modules/cross-env/src/is-windows.js +2 -0
- data/node_modules/cross-env/src/variable.js +69 -0
- data/node_modules/cross-spawn/CHANGELOG.md +130 -0
- data/node_modules/cross-spawn/LICENSE +21 -0
- data/node_modules/cross-spawn/README.md +96 -0
- data/node_modules/cross-spawn/index.js +39 -0
- data/node_modules/cross-spawn/lib/enoent.js +59 -0
- data/node_modules/cross-spawn/lib/parse.js +91 -0
- data/node_modules/cross-spawn/lib/util/escape.js +45 -0
- data/node_modules/cross-spawn/lib/util/readShebang.js +23 -0
- data/node_modules/cross-spawn/lib/util/resolveCommand.js +52 -0
- data/node_modules/cross-spawn/package.json +73 -0
- data/node_modules/crypto-js/CONTRIBUTING.md +28 -0
- data/node_modules/crypto-js/LICENSE +24 -0
- data/node_modules/crypto-js/README.md +249 -0
- data/node_modules/crypto-js/aes.js +234 -0
- data/node_modules/crypto-js/bower.json +35 -0
- data/node_modules/crypto-js/cipher-core.js +890 -0
- data/node_modules/crypto-js/core.js +797 -0
- data/node_modules/crypto-js/crypto-js.js +6059 -0
- data/node_modules/crypto-js/docs/QuickStartGuide.wiki +470 -0
- data/node_modules/crypto-js/enc-base64.js +136 -0
- data/node_modules/crypto-js/enc-hex.js +18 -0
- data/node_modules/crypto-js/enc-latin1.js +18 -0
- data/node_modules/crypto-js/enc-utf16.js +149 -0
- data/node_modules/crypto-js/enc-utf8.js +18 -0
- data/node_modules/crypto-js/evpkdf.js +134 -0
- data/node_modules/crypto-js/format-hex.js +66 -0
- data/node_modules/crypto-js/format-openssl.js +18 -0
- data/node_modules/crypto-js/hmac-md5.js +18 -0
- data/node_modules/crypto-js/hmac-ripemd160.js +18 -0
- data/node_modules/crypto-js/hmac-sha1.js +18 -0
- data/node_modules/crypto-js/hmac-sha224.js +18 -0
- data/node_modules/crypto-js/hmac-sha256.js +18 -0
- data/node_modules/crypto-js/hmac-sha3.js +18 -0
- data/node_modules/crypto-js/hmac-sha384.js +18 -0
- data/node_modules/crypto-js/hmac-sha512.js +18 -0
- data/node_modules/crypto-js/hmac.js +143 -0
- data/node_modules/crypto-js/index.js +18 -0
- data/node_modules/crypto-js/lib-typedarrays.js +76 -0
- data/node_modules/crypto-js/md5.js +268 -0
- data/node_modules/crypto-js/mode-cfb.js +80 -0
- data/node_modules/crypto-js/mode-ctr-gladman.js +116 -0
- data/node_modules/crypto-js/mode-ctr.js +58 -0
- data/node_modules/crypto-js/mode-ecb.js +40 -0
- data/node_modules/crypto-js/mode-ofb.js +54 -0
- data/node_modules/crypto-js/package.json +38 -0
- data/node_modules/crypto-js/pad-ansix923.js +49 -0
- data/node_modules/crypto-js/pad-iso10126.js +44 -0
- data/node_modules/crypto-js/pad-iso97971.js +40 -0
- data/node_modules/crypto-js/pad-nopadding.js +30 -0
- data/node_modules/crypto-js/pad-pkcs7.js +18 -0
- data/node_modules/crypto-js/pad-zeropadding.js +47 -0
- data/node_modules/crypto-js/pbkdf2.js +145 -0
- data/node_modules/crypto-js/rabbit-legacy.js +190 -0
- data/node_modules/crypto-js/rabbit.js +192 -0
- data/node_modules/crypto-js/rc4.js +139 -0
- data/node_modules/crypto-js/ripemd160.js +267 -0
- data/node_modules/crypto-js/sha1.js +150 -0
- data/node_modules/crypto-js/sha224.js +80 -0
- data/node_modules/crypto-js/sha256.js +199 -0
- data/node_modules/crypto-js/sha3.js +326 -0
- data/node_modules/crypto-js/sha384.js +83 -0
- data/node_modules/crypto-js/sha512.js +326 -0
- data/node_modules/crypto-js/tripledes.js +779 -0
- data/node_modules/crypto-js/x64-core.js +304 -0
- data/node_modules/diff/CONTRIBUTING.md +39 -0
- data/node_modules/diff/LICENSE +31 -0
- data/node_modules/diff/README.md +208 -0
- data/node_modules/diff/dist/diff.js +1582 -0
- data/node_modules/diff/lib/convert/dmp.js +32 -0
- data/node_modules/diff/lib/convert/xml.js +42 -0
- data/node_modules/diff/lib/diff/array.js +45 -0
- data/node_modules/diff/lib/diff/base.js +304 -0
- data/node_modules/diff/lib/diff/character.js +37 -0
- data/node_modules/diff/lib/diff/css.js +41 -0
- data/node_modules/diff/lib/diff/json.js +163 -0
- data/node_modules/diff/lib/diff/line.js +89 -0
- data/node_modules/diff/lib/diff/sentence.js +41 -0
- data/node_modules/diff/lib/diff/word.js +108 -0
- data/node_modules/diff/lib/index.es6.js +1553 -0
- data/node_modules/diff/lib/index.js +216 -0
- data/node_modules/diff/lib/index.mjs +1553 -0
- data/node_modules/diff/lib/patch/apply.js +238 -0
- data/node_modules/diff/lib/patch/create.js +267 -0
- data/node_modules/diff/lib/patch/merge.js +613 -0
- data/node_modules/diff/lib/patch/parse.js +167 -0
- data/node_modules/diff/lib/util/array.js +32 -0
- data/node_modules/diff/lib/util/distance-iterator.js +57 -0
- data/node_modules/diff/lib/util/params.js +24 -0
- data/node_modules/diff/package.json +87 -0
- data/node_modules/diff/release-notes.md +303 -0
- data/node_modules/diff/runtime.js +3 -0
- data/node_modules/emoji-regex/LICENSE-MIT.txt +20 -0
- data/node_modules/emoji-regex/README.md +73 -0
- data/node_modules/emoji-regex/es2015/index.js +6 -0
- data/node_modules/emoji-regex/es2015/text.js +6 -0
- data/node_modules/emoji-regex/index.d.ts +23 -0
- data/node_modules/emoji-regex/index.js +6 -0
- data/node_modules/emoji-regex/package.json +50 -0
- data/node_modules/emoji-regex/text.js +6 -0
- data/node_modules/escalade/dist/index.js +22 -0
- data/node_modules/escalade/dist/index.mjs +22 -0
- data/node_modules/escalade/index.d.ts +3 -0
- data/node_modules/escalade/license +9 -0
- data/node_modules/escalade/package.json +61 -0
- data/node_modules/escalade/readme.md +211 -0
- data/node_modules/escalade/sync/index.d.ts +2 -0
- data/node_modules/escalade/sync/index.js +18 -0
- data/node_modules/escalade/sync/index.mjs +18 -0
- data/node_modules/esprima/ChangeLog +235 -0
- data/node_modules/esprima/LICENSE.BSD +21 -0
- data/node_modules/esprima/README.md +46 -0
- data/node_modules/esprima/bin/esparse.js +139 -0
- data/node_modules/esprima/bin/esvalidate.js +236 -0
- data/node_modules/esprima/dist/esprima.js +6709 -0
- data/node_modules/esprima/package.json +112 -0
- data/node_modules/fill-range/LICENSE +21 -0
- data/node_modules/fill-range/README.md +237 -0
- data/node_modules/fill-range/index.js +249 -0
- data/node_modules/fill-range/package.json +69 -0
- data/node_modules/fs-extra/CHANGELOG.md +902 -0
- data/node_modules/fs-extra/LICENSE +15 -0
- data/node_modules/fs-extra/README.md +264 -0
- data/node_modules/fs-extra/lib/copy-sync/copy-sync.js +166 -0
- data/node_modules/fs-extra/lib/copy-sync/index.js +5 -0
- data/node_modules/fs-extra/lib/copy/copy.js +232 -0
- data/node_modules/fs-extra/lib/copy/index.js +6 -0
- data/node_modules/fs-extra/lib/empty/index.js +48 -0
- data/node_modules/fs-extra/lib/ensure/file.js +69 -0
- data/node_modules/fs-extra/lib/ensure/index.js +23 -0
- data/node_modules/fs-extra/lib/ensure/link.js +61 -0
- data/node_modules/fs-extra/lib/ensure/symlink-paths.js +99 -0
- data/node_modules/fs-extra/lib/ensure/symlink-type.js +31 -0
- data/node_modules/fs-extra/lib/ensure/symlink.js +63 -0
- data/node_modules/fs-extra/lib/fs/index.js +130 -0
- data/node_modules/fs-extra/lib/index.js +27 -0
- data/node_modules/fs-extra/lib/json/index.js +16 -0
- data/node_modules/fs-extra/lib/json/jsonfile.js +11 -0
- data/node_modules/fs-extra/lib/json/output-json-sync.js +12 -0
- data/node_modules/fs-extra/lib/json/output-json.js +12 -0
- data/node_modules/fs-extra/lib/mkdirs/index.js +14 -0
- data/node_modules/fs-extra/lib/mkdirs/make-dir.js +141 -0
- data/node_modules/fs-extra/lib/move-sync/index.js +5 -0
- data/node_modules/fs-extra/lib/move-sync/move-sync.js +47 -0
- data/node_modules/fs-extra/lib/move/index.js +6 -0
- data/node_modules/fs-extra/lib/move/move.js +65 -0
- data/node_modules/fs-extra/lib/output/index.js +40 -0
- data/node_modules/fs-extra/lib/path-exists/index.js +12 -0
- data/node_modules/fs-extra/lib/remove/index.js +9 -0
- data/node_modules/fs-extra/lib/remove/rimraf.js +302 -0
- data/node_modules/fs-extra/lib/util/stat.js +139 -0
- data/node_modules/fs-extra/lib/util/utimes.js +26 -0
- data/node_modules/fs-extra/package.json +70 -0
- data/node_modules/fs.realpath/LICENSE +43 -0
- data/node_modules/fs.realpath/README.md +33 -0
- data/node_modules/fs.realpath/index.js +66 -0
- data/node_modules/fs.realpath/old.js +303 -0
- data/node_modules/fs.realpath/package.json +26 -0
- data/node_modules/fsevents/LICENSE +22 -0
- data/node_modules/fsevents/README.md +83 -0
- data/node_modules/fsevents/fsevents.d.ts +46 -0
- data/node_modules/fsevents/fsevents.js +82 -0
- data/node_modules/fsevents/fsevents.node +0 -0
- data/node_modules/fsevents/package.json +62 -0
- data/node_modules/get-caller-file/LICENSE.md +6 -0
- data/node_modules/get-caller-file/README.md +41 -0
- data/node_modules/get-caller-file/index.d.ts +2 -0
- data/node_modules/get-caller-file/index.js +22 -0
- data/node_modules/get-caller-file/index.js.map +1 -0
- data/node_modules/get-caller-file/package.json +42 -0
- data/node_modules/glob-parent/CHANGELOG.md +110 -0
- data/node_modules/glob-parent/LICENSE +15 -0
- data/node_modules/glob-parent/README.md +137 -0
- data/node_modules/glob-parent/index.js +42 -0
- data/node_modules/glob-parent/package.json +48 -0
- data/node_modules/glob/LICENSE +21 -0
- data/node_modules/glob/README.md +375 -0
- data/node_modules/glob/changelog.md +67 -0
- data/node_modules/glob/common.js +234 -0
- data/node_modules/glob/glob.js +788 -0
- data/node_modules/glob/package.json +51 -0
- data/node_modules/glob/sync.js +484 -0
- data/node_modules/graceful-fs/LICENSE +15 -0
- data/node_modules/graceful-fs/README.md +133 -0
- data/node_modules/graceful-fs/clone.js +23 -0
- data/node_modules/graceful-fs/graceful-fs.js +373 -0
- data/node_modules/graceful-fs/legacy-streams.js +118 -0
- data/node_modules/graceful-fs/package.json +50 -0
- data/node_modules/graceful-fs/polyfills.js +346 -0
- data/node_modules/inflight/LICENSE +15 -0
- data/node_modules/inflight/README.md +37 -0
- data/node_modules/inflight/inflight.js +54 -0
- data/node_modules/inflight/package.json +29 -0
- data/node_modules/inherits/LICENSE +16 -0
- data/node_modules/inherits/README.md +42 -0
- data/node_modules/inherits/inherits.js +9 -0
- data/node_modules/inherits/inherits_browser.js +27 -0
- data/node_modules/inherits/package.json +29 -0
- data/node_modules/is-binary-path/index.d.ts +17 -0
- data/node_modules/is-binary-path/index.js +7 -0
- data/node_modules/is-binary-path/license +9 -0
- data/node_modules/is-binary-path/package.json +40 -0
- data/node_modules/is-binary-path/readme.md +34 -0
- data/node_modules/is-extglob/LICENSE +21 -0
- data/node_modules/is-extglob/README.md +107 -0
- data/node_modules/is-extglob/index.js +20 -0
- data/node_modules/is-extglob/package.json +69 -0
- data/node_modules/is-fullwidth-code-point/index.d.ts +17 -0
- data/node_modules/is-fullwidth-code-point/index.js +50 -0
- data/node_modules/is-fullwidth-code-point/license +9 -0
- data/node_modules/is-fullwidth-code-point/package.json +42 -0
- data/node_modules/is-fullwidth-code-point/readme.md +39 -0
- data/node_modules/is-glob/LICENSE +21 -0
- data/node_modules/is-glob/README.md +206 -0
- data/node_modules/is-glob/index.js +48 -0
- data/node_modules/is-glob/package.json +81 -0
- data/node_modules/is-number/LICENSE +21 -0
- data/node_modules/is-number/README.md +187 -0
- data/node_modules/is-number/index.js +18 -0
- data/node_modules/is-number/package.json +82 -0
- data/node_modules/isexe/LICENSE +15 -0
- data/node_modules/isexe/README.md +51 -0
- data/node_modules/isexe/index.js +57 -0
- data/node_modules/isexe/mode.js +41 -0
- data/node_modules/isexe/package.json +31 -0
- data/node_modules/isexe/test/basic.js +221 -0
- data/node_modules/isexe/windows.js +42 -0
- data/node_modules/js-yaml/CHANGELOG.md +557 -0
- data/node_modules/js-yaml/LICENSE +21 -0
- data/node_modules/js-yaml/README.md +299 -0
- data/node_modules/js-yaml/bin/js-yaml.js +132 -0
- data/node_modules/js-yaml/dist/js-yaml.js +3989 -0
- data/node_modules/js-yaml/dist/js-yaml.min.js +1 -0
- data/node_modules/js-yaml/index.js +7 -0
- data/node_modules/js-yaml/lib/js-yaml.js +39 -0
- data/node_modules/js-yaml/lib/js-yaml/common.js +59 -0
- data/node_modules/js-yaml/lib/js-yaml/dumper.js +850 -0
- data/node_modules/js-yaml/lib/js-yaml/exception.js +43 -0
- data/node_modules/js-yaml/lib/js-yaml/loader.js +1644 -0
- data/node_modules/js-yaml/lib/js-yaml/mark.js +76 -0
- data/node_modules/js-yaml/lib/js-yaml/schema.js +108 -0
- data/node_modules/js-yaml/lib/js-yaml/schema/core.js +18 -0
- data/node_modules/js-yaml/lib/js-yaml/schema/default_full.js +25 -0
- data/node_modules/js-yaml/lib/js-yaml/schema/default_safe.js +28 -0
- data/node_modules/js-yaml/lib/js-yaml/schema/failsafe.js +17 -0
- data/node_modules/js-yaml/lib/js-yaml/schema/json.js +25 -0
- data/node_modules/js-yaml/lib/js-yaml/type.js +61 -0
- data/node_modules/js-yaml/lib/js-yaml/type/binary.js +138 -0
- data/node_modules/js-yaml/lib/js-yaml/type/bool.js +35 -0
- data/node_modules/js-yaml/lib/js-yaml/type/float.js +116 -0
- data/node_modules/js-yaml/lib/js-yaml/type/int.js +173 -0
- data/node_modules/js-yaml/lib/js-yaml/type/js/function.js +93 -0
- data/node_modules/js-yaml/lib/js-yaml/type/js/regexp.js +60 -0
- data/node_modules/js-yaml/lib/js-yaml/type/js/undefined.js +28 -0
- data/node_modules/js-yaml/lib/js-yaml/type/map.js +8 -0
- data/node_modules/js-yaml/lib/js-yaml/type/merge.js +12 -0
- data/node_modules/js-yaml/lib/js-yaml/type/null.js +34 -0
- data/node_modules/js-yaml/lib/js-yaml/type/omap.js +44 -0
- data/node_modules/js-yaml/lib/js-yaml/type/pairs.js +53 -0
- data/node_modules/js-yaml/lib/js-yaml/type/seq.js +8 -0
- data/node_modules/js-yaml/lib/js-yaml/type/set.js +29 -0
- data/node_modules/js-yaml/lib/js-yaml/type/str.js +8 -0
- data/node_modules/js-yaml/lib/js-yaml/type/timestamp.js +88 -0
- data/node_modules/js-yaml/package.json +49 -0
- data/node_modules/jsonfile/CHANGELOG.md +171 -0
- data/node_modules/jsonfile/LICENSE +15 -0
- data/node_modules/jsonfile/README.md +230 -0
- data/node_modules/jsonfile/index.js +88 -0
- data/node_modules/jsonfile/package.json +40 -0
- data/node_modules/jsonfile/utils.js +14 -0
- data/node_modules/lru-cache/LICENSE +15 -0
- data/node_modules/lru-cache/README.md +166 -0
- data/node_modules/lru-cache/index.js +334 -0
- data/node_modules/lru-cache/package.json +34 -0
- data/node_modules/minimatch/LICENSE +15 -0
- data/node_modules/minimatch/README.md +209 -0
- data/node_modules/minimatch/minimatch.js +923 -0
- data/node_modules/minimatch/package.json +30 -0
- data/node_modules/normalize-path/LICENSE +21 -0
- data/node_modules/normalize-path/README.md +127 -0
- data/node_modules/normalize-path/index.js +35 -0
- data/node_modules/normalize-path/package.json +77 -0
- data/node_modules/once/LICENSE +15 -0
- data/node_modules/once/README.md +79 -0
- data/node_modules/once/once.js +42 -0
- data/node_modules/once/package.json +33 -0
- data/node_modules/path-is-absolute/index.js +20 -0
- data/node_modules/path-is-absolute/license +21 -0
- data/node_modules/path-is-absolute/package.json +43 -0
- data/node_modules/path-is-absolute/readme.md +59 -0
- data/node_modules/path-key/index.d.ts +40 -0
- data/node_modules/path-key/index.js +16 -0
- data/node_modules/path-key/license +9 -0
- data/node_modules/path-key/package.json +39 -0
- data/node_modules/path-key/readme.md +61 -0
- data/node_modules/picomatch/CHANGELOG.md +126 -0
- data/node_modules/picomatch/LICENSE +21 -0
- data/node_modules/picomatch/README.md +707 -0
- data/node_modules/picomatch/index.js +3 -0
- data/node_modules/picomatch/lib/constants.js +179 -0
- data/node_modules/picomatch/lib/parse.js +1084 -0
- data/node_modules/picomatch/lib/picomatch.js +342 -0
- data/node_modules/picomatch/lib/scan.js +391 -0
- data/node_modules/picomatch/lib/utils.js +64 -0
- data/node_modules/picomatch/package.json +81 -0
- data/node_modules/readdirp/LICENSE +21 -0
- data/node_modules/readdirp/README.md +122 -0
- data/node_modules/readdirp/index.d.ts +43 -0
- data/node_modules/readdirp/index.js +287 -0
- data/node_modules/readdirp/package.json +122 -0
- data/node_modules/require-directory/LICENSE +22 -0
- data/node_modules/require-directory/README.markdown +184 -0
- data/node_modules/require-directory/index.js +86 -0
- data/node_modules/require-directory/package.json +40 -0
- data/node_modules/semver/CHANGELOG.md +111 -0
- data/node_modules/semver/LICENSE +15 -0
- data/node_modules/semver/README.md +566 -0
- data/node_modules/semver/bin/semver.js +173 -0
- data/node_modules/semver/classes/comparator.js +135 -0
- data/node_modules/semver/classes/index.js +5 -0
- data/node_modules/semver/classes/range.js +510 -0
- data/node_modules/semver/classes/semver.js +287 -0
- data/node_modules/semver/functions/clean.js +6 -0
- data/node_modules/semver/functions/cmp.js +48 -0
- data/node_modules/semver/functions/coerce.js +51 -0
- data/node_modules/semver/functions/compare-build.js +7 -0
- data/node_modules/semver/functions/compare-loose.js +3 -0
- data/node_modules/semver/functions/compare.js +5 -0
- data/node_modules/semver/functions/diff.js +23 -0
- data/node_modules/semver/functions/eq.js +3 -0
- data/node_modules/semver/functions/gt.js +3 -0
- data/node_modules/semver/functions/gte.js +3 -0
- data/node_modules/semver/functions/inc.js +15 -0
- data/node_modules/semver/functions/lt.js +3 -0
- data/node_modules/semver/functions/lte.js +3 -0
- data/node_modules/semver/functions/major.js +3 -0
- data/node_modules/semver/functions/minor.js +3 -0
- data/node_modules/semver/functions/neq.js +3 -0
- data/node_modules/semver/functions/parse.js +33 -0
- data/node_modules/semver/functions/patch.js +3 -0
- data/node_modules/semver/functions/prerelease.js +6 -0
- data/node_modules/semver/functions/rcompare.js +3 -0
- data/node_modules/semver/functions/rsort.js +3 -0
- data/node_modules/semver/functions/satisfies.js +10 -0
- data/node_modules/semver/functions/sort.js +3 -0
- data/node_modules/semver/functions/valid.js +6 -0
- data/node_modules/semver/index.js +48 -0
- data/node_modules/semver/internal/constants.js +17 -0
- data/node_modules/semver/internal/debug.js +9 -0
- data/node_modules/semver/internal/identifiers.js +23 -0
- data/node_modules/semver/internal/parse-options.js +11 -0
- data/node_modules/semver/internal/re.js +182 -0
- data/node_modules/semver/package.json +41 -0
- data/node_modules/semver/preload.js +2 -0
- data/node_modules/semver/range.bnf +16 -0
- data/node_modules/semver/ranges/gtr.js +4 -0
- data/node_modules/semver/ranges/intersects.js +7 -0
- data/node_modules/semver/ranges/ltr.js +4 -0
- data/node_modules/semver/ranges/max-satisfying.js +25 -0
- data/node_modules/semver/ranges/min-satisfying.js +24 -0
- data/node_modules/semver/ranges/min-version.js +60 -0
- data/node_modules/semver/ranges/outside.js +80 -0
- data/node_modules/semver/ranges/simplify.js +44 -0
- data/node_modules/semver/ranges/subset.js +222 -0
- data/node_modules/semver/ranges/to-comparators.js +8 -0
- data/node_modules/semver/ranges/valid.js +11 -0
- data/node_modules/shebang-command/index.js +19 -0
- data/node_modules/shebang-command/license +9 -0
- data/node_modules/shebang-command/package.json +34 -0
- data/node_modules/shebang-command/readme.md +34 -0
- data/node_modules/shebang-regex/index.d.ts +22 -0
- data/node_modules/shebang-regex/index.js +2 -0
- data/node_modules/shebang-regex/license +9 -0
- data/node_modules/shebang-regex/package.json +35 -0
- data/node_modules/shebang-regex/readme.md +33 -0
- data/node_modules/simple-wcswidth/CHANGELOG.md +13 -0
- data/node_modules/simple-wcswidth/LICENSE +21 -0
- data/node_modules/simple-wcswidth/README.md +100 -0
- data/node_modules/simple-wcswidth/dist/index.d.ts +3 -0
- data/node_modules/simple-wcswidth/dist/index.js +10 -0
- data/node_modules/simple-wcswidth/dist/src/binary-search.d.ts +3 -0
- data/node_modules/simple-wcswidth/dist/src/binary-search.js +24 -0
- data/node_modules/simple-wcswidth/dist/src/models.d.ts +4 -0
- data/node_modules/simple-wcswidth/dist/src/models.js +2 -0
- data/node_modules/simple-wcswidth/dist/src/non-spacing-chars.d.ts +3 -0
- data/node_modules/simple-wcswidth/dist/src/non-spacing-chars.js +149 -0
- data/node_modules/simple-wcswidth/dist/src/wcswidth.d.ts +2 -0
- data/node_modules/simple-wcswidth/dist/src/wcswidth.js +20 -0
- data/node_modules/simple-wcswidth/dist/src/wcwidth.d.ts +2 -0
- data/node_modules/simple-wcswidth/dist/src/wcwidth.js +67 -0
- data/node_modules/simple-wcswidth/package.json +44 -0
- data/node_modules/slash/index.d.ts +25 -0
- data/node_modules/slash/index.js +11 -0
- data/node_modules/slash/license +9 -0
- data/node_modules/slash/package.json +35 -0
- data/node_modules/slash/readme.md +44 -0
- data/node_modules/sprintf-js/LICENSE +24 -0
- data/node_modules/sprintf-js/README.md +88 -0
- data/node_modules/sprintf-js/bower.json +14 -0
- data/node_modules/sprintf-js/demo/angular.html +20 -0
- data/node_modules/sprintf-js/dist/angular-sprintf.min.js +4 -0
- data/node_modules/sprintf-js/dist/angular-sprintf.min.js.map +1 -0
- data/node_modules/sprintf-js/dist/angular-sprintf.min.map +1 -0
- data/node_modules/sprintf-js/dist/sprintf.min.js +4 -0
- data/node_modules/sprintf-js/dist/sprintf.min.js.map +1 -0
- data/node_modules/sprintf-js/dist/sprintf.min.map +1 -0
- data/node_modules/sprintf-js/gruntfile.js +36 -0
- data/node_modules/sprintf-js/package.json +22 -0
- data/node_modules/sprintf-js/src/angular-sprintf.js +18 -0
- data/node_modules/sprintf-js/src/sprintf.js +208 -0
- data/node_modules/sprintf-js/test/test.js +82 -0
- data/node_modules/sqlite-parser/CHANGELOG.md +1263 -0
- data/node_modules/sqlite-parser/LICENSE +22 -0
- data/node_modules/sqlite-parser/README.md +187 -0
- data/node_modules/sqlite-parser/bin/sqlite-parser +7 -0
- data/node_modules/sqlite-parser/dist/sqlite-parser.js +19 -0
- data/node_modules/sqlite-parser/lib/index.js +6 -0
- data/node_modules/sqlite-parser/lib/parser.js +6 -0
- data/node_modules/sqlite-parser/lib/streaming-shim.js +6 -0
- data/node_modules/sqlite-parser/lib/streaming.js +6 -0
- data/node_modules/sqlite-parser/lib/tracer.js +6 -0
- data/node_modules/sqlite-parser/package.json +75 -0
- data/node_modules/string-width/index.d.ts +29 -0
- data/node_modules/string-width/index.js +47 -0
- data/node_modules/string-width/license +9 -0
- data/node_modules/string-width/package.json +56 -0
- data/node_modules/string-width/readme.md +50 -0
- data/node_modules/strip-ansi/index.d.ts +17 -0
- data/node_modules/strip-ansi/index.js +4 -0
- data/node_modules/strip-ansi/license +9 -0
- data/node_modules/strip-ansi/package.json +54 -0
- data/node_modules/strip-ansi/readme.md +46 -0
- data/node_modules/to-regex-range/LICENSE +21 -0
- data/node_modules/to-regex-range/README.md +305 -0
- data/node_modules/to-regex-range/index.js +288 -0
- data/node_modules/to-regex-range/package.json +88 -0
- data/node_modules/universalify/LICENSE +20 -0
- data/node_modules/universalify/README.md +76 -0
- data/node_modules/universalify/index.js +24 -0
- data/node_modules/universalify/package.json +34 -0
- data/node_modules/which/CHANGELOG.md +166 -0
- data/node_modules/which/LICENSE +15 -0
- data/node_modules/which/README.md +54 -0
- data/node_modules/which/bin/node-which +52 -0
- data/node_modules/which/package.json +43 -0
- data/node_modules/which/which.js +125 -0
- data/node_modules/wrap-ansi/index.js +216 -0
- data/node_modules/wrap-ansi/license +9 -0
- data/node_modules/wrap-ansi/package.json +62 -0
- data/node_modules/wrap-ansi/readme.md +91 -0
- data/node_modules/wrappy/LICENSE +15 -0
- data/node_modules/wrappy/README.md +36 -0
- data/node_modules/wrappy/package.json +29 -0
- data/node_modules/wrappy/wrappy.js +33 -0
- data/node_modules/y18n/CHANGELOG.md +100 -0
- data/node_modules/y18n/LICENSE +13 -0
- data/node_modules/y18n/README.md +127 -0
- data/node_modules/y18n/build/index.cjs +203 -0
- data/node_modules/y18n/build/lib/cjs.js +6 -0
- data/node_modules/y18n/build/lib/index.js +174 -0
- data/node_modules/y18n/build/lib/platform-shims/node.js +19 -0
- data/node_modules/y18n/index.mjs +8 -0
- data/node_modules/y18n/package.json +70 -0
- data/node_modules/yallist/LICENSE +15 -0
- data/node_modules/yallist/README.md +204 -0
- data/node_modules/yallist/iterator.js +8 -0
- data/node_modules/yallist/package.json +29 -0
- data/node_modules/yallist/yallist.js +426 -0
- data/node_modules/yargs-parser/CHANGELOG.md +263 -0
- data/node_modules/yargs-parser/LICENSE.txt +14 -0
- data/node_modules/yargs-parser/README.md +518 -0
- data/node_modules/yargs-parser/browser.js +29 -0
- data/node_modules/yargs-parser/build/index.cjs +1042 -0
- data/node_modules/yargs-parser/build/lib/index.js +59 -0
- data/node_modules/yargs-parser/build/lib/string-utils.js +65 -0
- data/node_modules/yargs-parser/build/lib/tokenize-arg-string.js +40 -0
- data/node_modules/yargs-parser/build/lib/yargs-parser-types.js +12 -0
- data/node_modules/yargs-parser/build/lib/yargs-parser.js +1037 -0
- data/node_modules/yargs-parser/package.json +87 -0
- data/node_modules/yargs/CHANGELOG.md +151 -0
- data/node_modules/yargs/LICENSE +21 -0
- data/node_modules/yargs/README.md +204 -0
- data/node_modules/yargs/browser.mjs +7 -0
- data/node_modules/yargs/build/index.cjs +1 -0
- data/node_modules/yargs/build/lib/argsert.js +62 -0
- data/node_modules/yargs/build/lib/command.js +436 -0
- data/node_modules/yargs/build/lib/completion-templates.js +48 -0
- data/node_modules/yargs/build/lib/completion.js +166 -0
- data/node_modules/yargs/build/lib/middleware.js +85 -0
- data/node_modules/yargs/build/lib/parse-command.js +32 -0
- data/node_modules/yargs/build/lib/typings/common-types.js +9 -0
- data/node_modules/yargs/build/lib/typings/yargs-parser-types.js +1 -0
- data/node_modules/yargs/build/lib/usage.js +567 -0
- data/node_modules/yargs/build/lib/utils/apply-extends.js +59 -0
- data/node_modules/yargs/build/lib/utils/is-promise.js +5 -0
- data/node_modules/yargs/build/lib/utils/levenshtein.js +26 -0
- data/node_modules/yargs/build/lib/utils/maybe-async-result.js +17 -0
- data/node_modules/yargs/build/lib/utils/obj-filter.js +10 -0
- data/node_modules/yargs/build/lib/utils/process-argv.js +17 -0
- data/node_modules/yargs/build/lib/utils/set-blocking.js +12 -0
- data/node_modules/yargs/build/lib/utils/which-module.js +10 -0
- data/node_modules/yargs/build/lib/validation.js +279 -0
- data/node_modules/yargs/build/lib/yargs-factory.js +1452 -0
- data/node_modules/yargs/build/lib/yerror.js +7 -0
- data/node_modules/yargs/helpers/helpers.mjs +10 -0
- data/node_modules/yargs/helpers/index.js +14 -0
- data/node_modules/yargs/helpers/package.json +3 -0
- data/node_modules/yargs/index.cjs +43 -0
- data/node_modules/yargs/index.mjs +8 -0
- data/node_modules/yargs/lib/platform-shims/browser.mjs +94 -0
- data/node_modules/yargs/lib/platform-shims/esm.mjs +67 -0
- data/node_modules/yargs/locales/be.json +46 -0
- data/node_modules/yargs/locales/de.json +46 -0
- data/node_modules/yargs/locales/en.json +51 -0
- data/node_modules/yargs/locales/es.json +46 -0
- data/node_modules/yargs/locales/fi.json +49 -0
- data/node_modules/yargs/locales/fr.json +53 -0
- data/node_modules/yargs/locales/hi.json +49 -0
- data/node_modules/yargs/locales/hu.json +46 -0
- data/node_modules/yargs/locales/id.json +50 -0
- data/node_modules/yargs/locales/it.json +46 -0
- data/node_modules/yargs/locales/ja.json +51 -0
- data/node_modules/yargs/locales/ko.json +49 -0
- data/node_modules/yargs/locales/nb.json +44 -0
- data/node_modules/yargs/locales/nl.json +49 -0
- data/node_modules/yargs/locales/nn.json +44 -0
- data/node_modules/yargs/locales/pirate.json +13 -0
- data/node_modules/yargs/locales/pl.json +49 -0
- data/node_modules/yargs/locales/pt.json +45 -0
- data/node_modules/yargs/locales/pt_BR.json +48 -0
- data/node_modules/yargs/locales/ru.json +46 -0
- data/node_modules/yargs/locales/th.json +46 -0
- data/node_modules/yargs/locales/tr.json +48 -0
- data/node_modules/yargs/locales/uk_UA.json +51 -0
- data/node_modules/yargs/locales/zh_CN.json +48 -0
- data/node_modules/yargs/locales/zh_TW.json +47 -0
- data/node_modules/yargs/package.json +116 -0
- data/node_modules/yargs/yargs +9 -0
- data/spec/fixtures/depends/revoke_api_key.appmap.json +3 -3
- data/spec/fixtures/depends/user_page_scenario.appmap.json +3 -3
- metadata +956 -7
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
const { utimesSync } = require('fs');
|
|
2
|
+
const { join } = require('path');
|
|
3
|
+
const Fingerprinter = require('../../src/fingerprint/fingerprinter');
|
|
4
|
+
const FindCodeObjects = require('../../src/search/findCodeObjects');
|
|
5
|
+
const { listAppMapFiles, verbose } = require('../../src/utils');
|
|
6
|
+
|
|
7
|
+
const appMapDir = join(__dirname, 'fixtures');
|
|
8
|
+
const now = Date.now();
|
|
9
|
+
|
|
10
|
+
describe('Inspect', () => {
|
|
11
|
+
beforeAll(async () => {
|
|
12
|
+
if (process.env.DEBUG) {
|
|
13
|
+
verbose(true);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const fingerprinter = new Fingerprinter(true);
|
|
17
|
+
await listAppMapFiles(appMapDir, async (fileName) => {
|
|
18
|
+
utimesSync(fileName, now, now);
|
|
19
|
+
await fingerprinter.fingerprint(fileName);
|
|
20
|
+
});
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
test('finds a named function', async () => {
|
|
24
|
+
const fn = new FindCodeObjects(
|
|
25
|
+
appMapDir,
|
|
26
|
+
'function:app/models/ApiKey.issue'
|
|
27
|
+
);
|
|
28
|
+
const result = await fn.find();
|
|
29
|
+
expect(JSON.stringify(result, null, 2)).toEqual(
|
|
30
|
+
JSON.stringify(
|
|
31
|
+
[
|
|
32
|
+
{
|
|
33
|
+
appmap: 'tests/unit/fixtures/revoke_api_key',
|
|
34
|
+
codeObject: {
|
|
35
|
+
name: 'issue',
|
|
36
|
+
type: 'function',
|
|
37
|
+
static: true,
|
|
38
|
+
location: 'app/models/api_key.rb:28',
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
null,
|
|
43
|
+
2
|
|
44
|
+
)
|
|
45
|
+
);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('finds a named class', async () => {
|
|
49
|
+
const fn = new FindCodeObjects(appMapDir, 'class:app/models/ApiKey');
|
|
50
|
+
const result = await fn.find();
|
|
51
|
+
expect(JSON.stringify(result, null, 2)).toEqual(
|
|
52
|
+
JSON.stringify(
|
|
53
|
+
[
|
|
54
|
+
{
|
|
55
|
+
appmap: 'tests/unit/fixtures/revoke_api_key',
|
|
56
|
+
codeObject: {
|
|
57
|
+
name: 'ApiKey',
|
|
58
|
+
type: 'class',
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
null,
|
|
63
|
+
2
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('finds a named package', async () => {
|
|
69
|
+
const fn = new FindCodeObjects(appMapDir, 'package:app/models');
|
|
70
|
+
const result = await fn.find();
|
|
71
|
+
expect(JSON.stringify(result, null, 2)).toEqual(
|
|
72
|
+
JSON.stringify(
|
|
73
|
+
[
|
|
74
|
+
{
|
|
75
|
+
appmap: 'tests/unit/fixtures/revoke_api_key',
|
|
76
|
+
codeObject: {
|
|
77
|
+
name: 'app/models',
|
|
78
|
+
type: 'package',
|
|
79
|
+
},
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
appmap: 'tests/unit/fixtures/user_page_scenario',
|
|
83
|
+
codeObject: {
|
|
84
|
+
name: 'app/models',
|
|
85
|
+
type: 'package',
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
],
|
|
89
|
+
null,
|
|
90
|
+
2
|
|
91
|
+
)
|
|
92
|
+
);
|
|
93
|
+
});
|
|
94
|
+
});
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# [@appland/models-v1.3.0](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.2.0...@appland/models-v1.3.0) (2021-07-02)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Properly normalize 'pragma' query ([1f3b05d](https://github.com/applandinc/appmap-js/commit/1f3b05dbfd871e4446d5d2a8bfcf40474aedbb7f))
|
|
7
|
+
* Separately report query parse and analysis problems ([5121cb9](https://github.com/applandinc/appmap-js/commit/5121cb99809cf96b4f908c21419f22d60d01f841))
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* Include event.depth property ([f1f8ee8](https://github.com/applandinc/appmap-js/commit/f1f8ee81ebea8b9e3b8783a22bc999219b1b2e50))
|
|
13
|
+
* Store the database_type in query classMap entries ([7a44af6](https://github.com/applandinc/appmap-js/commit/7a44af6504dc78574b3ba9eb5d1edb60d3124a44))
|
|
14
|
+
|
|
15
|
+
# [@appland/models-v1.2.0](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.1.0...@appland/models-v1.2.0) (2021-06-22)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* Event#dataObjects was missing message objects from its return value ([ade2c31](https://github.com/applandinc/appmap-js/commit/ade2c31f316284a7232d914ba4fcec8b2c1ca4c7))
|
|
21
|
+
* Prevent access of non-array event messages ([15a9cc2](https://github.com/applandinc/appmap-js/commit/15a9cc2efce41451b83e2c35285de1644016fe3d))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
### Features
|
|
25
|
+
|
|
26
|
+
* HTTP client requests ([0c0e833](https://github.com/applandinc/appmap-js/commit/0c0e8338d6d25bf11f73a17d035e2b424e670add))
|
|
27
|
+
|
|
28
|
+
# [@appland/models-v1.1.0](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.6...@appland/models-v1.1.0) (2021-06-16)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
|
|
33
|
+
* Find and print info about a named function ([544db5c](https://github.com/applandinc/appmap-js/commit/544db5ca402d9e3399326f28da7d3a43a606f5c4))
|
|
34
|
+
* Test if an event is a regular function ([bb162d6](https://github.com/applandinc/appmap-js/commit/bb162d6b6431a4888872335c6eec5cf975b067bb))
|
|
35
|
+
|
|
36
|
+
# [@appland/models-v1.0.6](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.5...@appland/models-v1.0.6) (2021-06-03)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
### Bug Fixes
|
|
40
|
+
|
|
41
|
+
* Optimize performance and behavior of ClassMap.bindEvents ([5bac5bd](https://github.com/applandinc/appmap-js/commit/5bac5bd90c1cc15ca05ff2d7920e9f17483f9dd4))
|
|
42
|
+
|
|
43
|
+
# [@appland/models-v1.0.5](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.4...@appland/models-v1.0.5) (2021-05-28)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
### Bug Fixes
|
|
47
|
+
|
|
48
|
+
* Resolve an incorrect import of sha256 ([#227](https://github.com/applandinc/appmap-js/issues/227)) ([fc64ff9](https://github.com/applandinc/appmap-js/commit/fc64ff981046b5e1732b088889202f32924c407d))
|
|
49
|
+
|
|
50
|
+
# [@appland/models-v1.0.4](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.3...@appland/models-v1.0.4) (2021-05-18)
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
### Bug Fixes
|
|
54
|
+
|
|
55
|
+
* Update local dependencies ([f0d3281](https://github.com/applandinc/appmap-js/commit/f0d328161499999ee98fbb3aec2d438b3095bd0f))
|
|
56
|
+
|
|
57
|
+
# [@appland/models-v1.0.3](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.2...@appland/models-v1.0.3) (2021-05-18)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
### Bug Fixes
|
|
61
|
+
|
|
62
|
+
* Bundle ESM/CJS without external dependencies ([0a38ac0](https://github.com/applandinc/appmap-js/commit/0a38ac0a57baa30c6b0ff00bb69503e4891f8858))
|
|
63
|
+
|
|
64
|
+
# [@appland/models-v1.0.2](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.1...@appland/models-v1.0.2) (2021-05-11)
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
### Bug Fixes
|
|
68
|
+
|
|
69
|
+
* Add publish config ([118c54f](https://github.com/applandinc/appmap-js/commit/118c54f3db08f19de39bca7d67abd36a0071a20e))
|
|
70
|
+
|
|
71
|
+
# [@appland/models-v1.0.1](https://github.com/applandinc/appmap-js/compare/@appland/models-v1.0.0...@appland/models-v1.0.1) (2021-05-11)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
### Bug Fixes
|
|
75
|
+
|
|
76
|
+
* Flag package as public ([67e179c](https://github.com/applandinc/appmap-js/commit/67e179cd72ba247903764de25d8c86e0dd07bf9b))
|
|
77
|
+
|
|
78
|
+
# @appland/models-v1.0.0 (2021-05-11)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
### Features
|
|
82
|
+
|
|
83
|
+
* Initial release ([#195](https://github.com/applandinc/appmap-js/issues/195)) ([c4776a0](https://github.com/applandinc/appmap-js/commit/c4776a0514c333746846b8ffca88465f8c2739ee))
|
|
@@ -0,0 +1,4250 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var require$$0 = require('crypto');
|
|
6
|
+
var sqliteParser = require('sqlite-parser');
|
|
7
|
+
|
|
8
|
+
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
9
|
+
|
|
10
|
+
var require$$0__default = /*#__PURE__*/_interopDefaultLegacy(require$$0);
|
|
11
|
+
var sqliteParser__default = /*#__PURE__*/_interopDefaultLegacy(sqliteParser);
|
|
12
|
+
|
|
13
|
+
var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
|
|
14
|
+
|
|
15
|
+
function createCommonjsModule(fn) {
|
|
16
|
+
var module = { exports: {} };
|
|
17
|
+
return fn(module, module.exports), module.exports;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function commonjsRequire (path) {
|
|
21
|
+
throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
var core = createCommonjsModule(function (module, exports) {
|
|
25
|
+
(function (root, factory) {
|
|
26
|
+
{
|
|
27
|
+
// CommonJS
|
|
28
|
+
module.exports = factory();
|
|
29
|
+
}
|
|
30
|
+
}(commonjsGlobal, function () {
|
|
31
|
+
|
|
32
|
+
/*globals window, global, require*/
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* CryptoJS core components.
|
|
36
|
+
*/
|
|
37
|
+
var CryptoJS = CryptoJS || (function (Math, undefined$1) {
|
|
38
|
+
|
|
39
|
+
var crypto;
|
|
40
|
+
|
|
41
|
+
// Native crypto from window (Browser)
|
|
42
|
+
if (typeof window !== 'undefined' && window.crypto) {
|
|
43
|
+
crypto = window.crypto;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Native (experimental IE 11) crypto from window (Browser)
|
|
47
|
+
if (!crypto && typeof window !== 'undefined' && window.msCrypto) {
|
|
48
|
+
crypto = window.msCrypto;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Native crypto from global (NodeJS)
|
|
52
|
+
if (!crypto && typeof commonjsGlobal !== 'undefined' && commonjsGlobal.crypto) {
|
|
53
|
+
crypto = commonjsGlobal.crypto;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// Native crypto import via require (NodeJS)
|
|
57
|
+
if (!crypto && typeof commonjsRequire === 'function') {
|
|
58
|
+
try {
|
|
59
|
+
crypto = require$$0__default['default'];
|
|
60
|
+
} catch (err) {}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/*
|
|
64
|
+
* Cryptographically secure pseudorandom number generator
|
|
65
|
+
*
|
|
66
|
+
* As Math.random() is cryptographically not safe to use
|
|
67
|
+
*/
|
|
68
|
+
var cryptoSecureRandomInt = function () {
|
|
69
|
+
if (crypto) {
|
|
70
|
+
// Use getRandomValues method (Browser)
|
|
71
|
+
if (typeof crypto.getRandomValues === 'function') {
|
|
72
|
+
try {
|
|
73
|
+
return crypto.getRandomValues(new Uint32Array(1))[0];
|
|
74
|
+
} catch (err) {}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Use randomBytes method (NodeJS)
|
|
78
|
+
if (typeof crypto.randomBytes === 'function') {
|
|
79
|
+
try {
|
|
80
|
+
return crypto.randomBytes(4).readInt32LE();
|
|
81
|
+
} catch (err) {}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
throw new Error('Native crypto module could not be used to get secure random number.');
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
/*
|
|
89
|
+
* Local polyfill of Object.create
|
|
90
|
+
|
|
91
|
+
*/
|
|
92
|
+
var create = Object.create || (function () {
|
|
93
|
+
function F() {}
|
|
94
|
+
|
|
95
|
+
return function (obj) {
|
|
96
|
+
var subtype;
|
|
97
|
+
|
|
98
|
+
F.prototype = obj;
|
|
99
|
+
|
|
100
|
+
subtype = new F();
|
|
101
|
+
|
|
102
|
+
F.prototype = null;
|
|
103
|
+
|
|
104
|
+
return subtype;
|
|
105
|
+
};
|
|
106
|
+
}());
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* CryptoJS namespace.
|
|
110
|
+
*/
|
|
111
|
+
var C = {};
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Library namespace.
|
|
115
|
+
*/
|
|
116
|
+
var C_lib = C.lib = {};
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Base object for prototypal inheritance.
|
|
120
|
+
*/
|
|
121
|
+
var Base = C_lib.Base = (function () {
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
return {
|
|
125
|
+
/**
|
|
126
|
+
* Creates a new object that inherits from this object.
|
|
127
|
+
*
|
|
128
|
+
* @param {Object} overrides Properties to copy into the new object.
|
|
129
|
+
*
|
|
130
|
+
* @return {Object} The new object.
|
|
131
|
+
*
|
|
132
|
+
* @static
|
|
133
|
+
*
|
|
134
|
+
* @example
|
|
135
|
+
*
|
|
136
|
+
* var MyType = CryptoJS.lib.Base.extend({
|
|
137
|
+
* field: 'value',
|
|
138
|
+
*
|
|
139
|
+
* method: function () {
|
|
140
|
+
* }
|
|
141
|
+
* });
|
|
142
|
+
*/
|
|
143
|
+
extend: function (overrides) {
|
|
144
|
+
// Spawn
|
|
145
|
+
var subtype = create(this);
|
|
146
|
+
|
|
147
|
+
// Augment
|
|
148
|
+
if (overrides) {
|
|
149
|
+
subtype.mixIn(overrides);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Create default initializer
|
|
153
|
+
if (!subtype.hasOwnProperty('init') || this.init === subtype.init) {
|
|
154
|
+
subtype.init = function () {
|
|
155
|
+
subtype.$super.init.apply(this, arguments);
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Initializer's prototype is the subtype object
|
|
160
|
+
subtype.init.prototype = subtype;
|
|
161
|
+
|
|
162
|
+
// Reference supertype
|
|
163
|
+
subtype.$super = this;
|
|
164
|
+
|
|
165
|
+
return subtype;
|
|
166
|
+
},
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Extends this object and runs the init method.
|
|
170
|
+
* Arguments to create() will be passed to init().
|
|
171
|
+
*
|
|
172
|
+
* @return {Object} The new object.
|
|
173
|
+
*
|
|
174
|
+
* @static
|
|
175
|
+
*
|
|
176
|
+
* @example
|
|
177
|
+
*
|
|
178
|
+
* var instance = MyType.create();
|
|
179
|
+
*/
|
|
180
|
+
create: function () {
|
|
181
|
+
var instance = this.extend();
|
|
182
|
+
instance.init.apply(instance, arguments);
|
|
183
|
+
|
|
184
|
+
return instance;
|
|
185
|
+
},
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Initializes a newly created object.
|
|
189
|
+
* Override this method to add some logic when your objects are created.
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
*
|
|
193
|
+
* var MyType = CryptoJS.lib.Base.extend({
|
|
194
|
+
* init: function () {
|
|
195
|
+
* // ...
|
|
196
|
+
* }
|
|
197
|
+
* });
|
|
198
|
+
*/
|
|
199
|
+
init: function () {
|
|
200
|
+
},
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Copies properties into this object.
|
|
204
|
+
*
|
|
205
|
+
* @param {Object} properties The properties to mix in.
|
|
206
|
+
*
|
|
207
|
+
* @example
|
|
208
|
+
*
|
|
209
|
+
* MyType.mixIn({
|
|
210
|
+
* field: 'value'
|
|
211
|
+
* });
|
|
212
|
+
*/
|
|
213
|
+
mixIn: function (properties) {
|
|
214
|
+
for (var propertyName in properties) {
|
|
215
|
+
if (properties.hasOwnProperty(propertyName)) {
|
|
216
|
+
this[propertyName] = properties[propertyName];
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// IE won't copy toString using the loop above
|
|
221
|
+
if (properties.hasOwnProperty('toString')) {
|
|
222
|
+
this.toString = properties.toString;
|
|
223
|
+
}
|
|
224
|
+
},
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Creates a copy of this object.
|
|
228
|
+
*
|
|
229
|
+
* @return {Object} The clone.
|
|
230
|
+
*
|
|
231
|
+
* @example
|
|
232
|
+
*
|
|
233
|
+
* var clone = instance.clone();
|
|
234
|
+
*/
|
|
235
|
+
clone: function () {
|
|
236
|
+
return this.init.prototype.extend(this);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}());
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* An array of 32-bit words.
|
|
243
|
+
*
|
|
244
|
+
* @property {Array} words The array of 32-bit words.
|
|
245
|
+
* @property {number} sigBytes The number of significant bytes in this word array.
|
|
246
|
+
*/
|
|
247
|
+
var WordArray = C_lib.WordArray = Base.extend({
|
|
248
|
+
/**
|
|
249
|
+
* Initializes a newly created word array.
|
|
250
|
+
*
|
|
251
|
+
* @param {Array} words (Optional) An array of 32-bit words.
|
|
252
|
+
* @param {number} sigBytes (Optional) The number of significant bytes in the words.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
*
|
|
256
|
+
* var wordArray = CryptoJS.lib.WordArray.create();
|
|
257
|
+
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607]);
|
|
258
|
+
* var wordArray = CryptoJS.lib.WordArray.create([0x00010203, 0x04050607], 6);
|
|
259
|
+
*/
|
|
260
|
+
init: function (words, sigBytes) {
|
|
261
|
+
words = this.words = words || [];
|
|
262
|
+
|
|
263
|
+
if (sigBytes != undefined$1) {
|
|
264
|
+
this.sigBytes = sigBytes;
|
|
265
|
+
} else {
|
|
266
|
+
this.sigBytes = words.length * 4;
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Converts this word array to a string.
|
|
272
|
+
*
|
|
273
|
+
* @param {Encoder} encoder (Optional) The encoding strategy to use. Default: CryptoJS.enc.Hex
|
|
274
|
+
*
|
|
275
|
+
* @return {string} The stringified word array.
|
|
276
|
+
*
|
|
277
|
+
* @example
|
|
278
|
+
*
|
|
279
|
+
* var string = wordArray + '';
|
|
280
|
+
* var string = wordArray.toString();
|
|
281
|
+
* var string = wordArray.toString(CryptoJS.enc.Utf8);
|
|
282
|
+
*/
|
|
283
|
+
toString: function (encoder) {
|
|
284
|
+
return (encoder || Hex).stringify(this);
|
|
285
|
+
},
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Concatenates a word array to this word array.
|
|
289
|
+
*
|
|
290
|
+
* @param {WordArray} wordArray The word array to append.
|
|
291
|
+
*
|
|
292
|
+
* @return {WordArray} This word array.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
*
|
|
296
|
+
* wordArray1.concat(wordArray2);
|
|
297
|
+
*/
|
|
298
|
+
concat: function (wordArray) {
|
|
299
|
+
// Shortcuts
|
|
300
|
+
var thisWords = this.words;
|
|
301
|
+
var thatWords = wordArray.words;
|
|
302
|
+
var thisSigBytes = this.sigBytes;
|
|
303
|
+
var thatSigBytes = wordArray.sigBytes;
|
|
304
|
+
|
|
305
|
+
// Clamp excess bits
|
|
306
|
+
this.clamp();
|
|
307
|
+
|
|
308
|
+
// Concat
|
|
309
|
+
if (thisSigBytes % 4) {
|
|
310
|
+
// Copy one byte at a time
|
|
311
|
+
for (var i = 0; i < thatSigBytes; i++) {
|
|
312
|
+
var thatByte = (thatWords[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
|
313
|
+
thisWords[(thisSigBytes + i) >>> 2] |= thatByte << (24 - ((thisSigBytes + i) % 4) * 8);
|
|
314
|
+
}
|
|
315
|
+
} else {
|
|
316
|
+
// Copy one word at a time
|
|
317
|
+
for (var i = 0; i < thatSigBytes; i += 4) {
|
|
318
|
+
thisWords[(thisSigBytes + i) >>> 2] = thatWords[i >>> 2];
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
this.sigBytes += thatSigBytes;
|
|
322
|
+
|
|
323
|
+
// Chainable
|
|
324
|
+
return this;
|
|
325
|
+
},
|
|
326
|
+
|
|
327
|
+
/**
|
|
328
|
+
* Removes insignificant bits.
|
|
329
|
+
*
|
|
330
|
+
* @example
|
|
331
|
+
*
|
|
332
|
+
* wordArray.clamp();
|
|
333
|
+
*/
|
|
334
|
+
clamp: function () {
|
|
335
|
+
// Shortcuts
|
|
336
|
+
var words = this.words;
|
|
337
|
+
var sigBytes = this.sigBytes;
|
|
338
|
+
|
|
339
|
+
// Clamp
|
|
340
|
+
words[sigBytes >>> 2] &= 0xffffffff << (32 - (sigBytes % 4) * 8);
|
|
341
|
+
words.length = Math.ceil(sigBytes / 4);
|
|
342
|
+
},
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* Creates a copy of this word array.
|
|
346
|
+
*
|
|
347
|
+
* @return {WordArray} The clone.
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
*
|
|
351
|
+
* var clone = wordArray.clone();
|
|
352
|
+
*/
|
|
353
|
+
clone: function () {
|
|
354
|
+
var clone = Base.clone.call(this);
|
|
355
|
+
clone.words = this.words.slice(0);
|
|
356
|
+
|
|
357
|
+
return clone;
|
|
358
|
+
},
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Creates a word array filled with random bytes.
|
|
362
|
+
*
|
|
363
|
+
* @param {number} nBytes The number of random bytes to generate.
|
|
364
|
+
*
|
|
365
|
+
* @return {WordArray} The random word array.
|
|
366
|
+
*
|
|
367
|
+
* @static
|
|
368
|
+
*
|
|
369
|
+
* @example
|
|
370
|
+
*
|
|
371
|
+
* var wordArray = CryptoJS.lib.WordArray.random(16);
|
|
372
|
+
*/
|
|
373
|
+
random: function (nBytes) {
|
|
374
|
+
var words = [];
|
|
375
|
+
|
|
376
|
+
for (var i = 0; i < nBytes; i += 4) {
|
|
377
|
+
words.push(cryptoSecureRandomInt());
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
return new WordArray.init(words, nBytes);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
|
|
384
|
+
/**
|
|
385
|
+
* Encoder namespace.
|
|
386
|
+
*/
|
|
387
|
+
var C_enc = C.enc = {};
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Hex encoding strategy.
|
|
391
|
+
*/
|
|
392
|
+
var Hex = C_enc.Hex = {
|
|
393
|
+
/**
|
|
394
|
+
* Converts a word array to a hex string.
|
|
395
|
+
*
|
|
396
|
+
* @param {WordArray} wordArray The word array.
|
|
397
|
+
*
|
|
398
|
+
* @return {string} The hex string.
|
|
399
|
+
*
|
|
400
|
+
* @static
|
|
401
|
+
*
|
|
402
|
+
* @example
|
|
403
|
+
*
|
|
404
|
+
* var hexString = CryptoJS.enc.Hex.stringify(wordArray);
|
|
405
|
+
*/
|
|
406
|
+
stringify: function (wordArray) {
|
|
407
|
+
// Shortcuts
|
|
408
|
+
var words = wordArray.words;
|
|
409
|
+
var sigBytes = wordArray.sigBytes;
|
|
410
|
+
|
|
411
|
+
// Convert
|
|
412
|
+
var hexChars = [];
|
|
413
|
+
for (var i = 0; i < sigBytes; i++) {
|
|
414
|
+
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
|
415
|
+
hexChars.push((bite >>> 4).toString(16));
|
|
416
|
+
hexChars.push((bite & 0x0f).toString(16));
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
return hexChars.join('');
|
|
420
|
+
},
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Converts a hex string to a word array.
|
|
424
|
+
*
|
|
425
|
+
* @param {string} hexStr The hex string.
|
|
426
|
+
*
|
|
427
|
+
* @return {WordArray} The word array.
|
|
428
|
+
*
|
|
429
|
+
* @static
|
|
430
|
+
*
|
|
431
|
+
* @example
|
|
432
|
+
*
|
|
433
|
+
* var wordArray = CryptoJS.enc.Hex.parse(hexString);
|
|
434
|
+
*/
|
|
435
|
+
parse: function (hexStr) {
|
|
436
|
+
// Shortcut
|
|
437
|
+
var hexStrLength = hexStr.length;
|
|
438
|
+
|
|
439
|
+
// Convert
|
|
440
|
+
var words = [];
|
|
441
|
+
for (var i = 0; i < hexStrLength; i += 2) {
|
|
442
|
+
words[i >>> 3] |= parseInt(hexStr.substr(i, 2), 16) << (24 - (i % 8) * 4);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
return new WordArray.init(words, hexStrLength / 2);
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Latin1 encoding strategy.
|
|
451
|
+
*/
|
|
452
|
+
var Latin1 = C_enc.Latin1 = {
|
|
453
|
+
/**
|
|
454
|
+
* Converts a word array to a Latin1 string.
|
|
455
|
+
*
|
|
456
|
+
* @param {WordArray} wordArray The word array.
|
|
457
|
+
*
|
|
458
|
+
* @return {string} The Latin1 string.
|
|
459
|
+
*
|
|
460
|
+
* @static
|
|
461
|
+
*
|
|
462
|
+
* @example
|
|
463
|
+
*
|
|
464
|
+
* var latin1String = CryptoJS.enc.Latin1.stringify(wordArray);
|
|
465
|
+
*/
|
|
466
|
+
stringify: function (wordArray) {
|
|
467
|
+
// Shortcuts
|
|
468
|
+
var words = wordArray.words;
|
|
469
|
+
var sigBytes = wordArray.sigBytes;
|
|
470
|
+
|
|
471
|
+
// Convert
|
|
472
|
+
var latin1Chars = [];
|
|
473
|
+
for (var i = 0; i < sigBytes; i++) {
|
|
474
|
+
var bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff;
|
|
475
|
+
latin1Chars.push(String.fromCharCode(bite));
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
return latin1Chars.join('');
|
|
479
|
+
},
|
|
480
|
+
|
|
481
|
+
/**
|
|
482
|
+
* Converts a Latin1 string to a word array.
|
|
483
|
+
*
|
|
484
|
+
* @param {string} latin1Str The Latin1 string.
|
|
485
|
+
*
|
|
486
|
+
* @return {WordArray} The word array.
|
|
487
|
+
*
|
|
488
|
+
* @static
|
|
489
|
+
*
|
|
490
|
+
* @example
|
|
491
|
+
*
|
|
492
|
+
* var wordArray = CryptoJS.enc.Latin1.parse(latin1String);
|
|
493
|
+
*/
|
|
494
|
+
parse: function (latin1Str) {
|
|
495
|
+
// Shortcut
|
|
496
|
+
var latin1StrLength = latin1Str.length;
|
|
497
|
+
|
|
498
|
+
// Convert
|
|
499
|
+
var words = [];
|
|
500
|
+
for (var i = 0; i < latin1StrLength; i++) {
|
|
501
|
+
words[i >>> 2] |= (latin1Str.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
return new WordArray.init(words, latin1StrLength);
|
|
505
|
+
}
|
|
506
|
+
};
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* UTF-8 encoding strategy.
|
|
510
|
+
*/
|
|
511
|
+
var Utf8 = C_enc.Utf8 = {
|
|
512
|
+
/**
|
|
513
|
+
* Converts a word array to a UTF-8 string.
|
|
514
|
+
*
|
|
515
|
+
* @param {WordArray} wordArray The word array.
|
|
516
|
+
*
|
|
517
|
+
* @return {string} The UTF-8 string.
|
|
518
|
+
*
|
|
519
|
+
* @static
|
|
520
|
+
*
|
|
521
|
+
* @example
|
|
522
|
+
*
|
|
523
|
+
* var utf8String = CryptoJS.enc.Utf8.stringify(wordArray);
|
|
524
|
+
*/
|
|
525
|
+
stringify: function (wordArray) {
|
|
526
|
+
try {
|
|
527
|
+
return decodeURIComponent(escape(Latin1.stringify(wordArray)));
|
|
528
|
+
} catch (e) {
|
|
529
|
+
throw new Error('Malformed UTF-8 data');
|
|
530
|
+
}
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
/**
|
|
534
|
+
* Converts a UTF-8 string to a word array.
|
|
535
|
+
*
|
|
536
|
+
* @param {string} utf8Str The UTF-8 string.
|
|
537
|
+
*
|
|
538
|
+
* @return {WordArray} The word array.
|
|
539
|
+
*
|
|
540
|
+
* @static
|
|
541
|
+
*
|
|
542
|
+
* @example
|
|
543
|
+
*
|
|
544
|
+
* var wordArray = CryptoJS.enc.Utf8.parse(utf8String);
|
|
545
|
+
*/
|
|
546
|
+
parse: function (utf8Str) {
|
|
547
|
+
return Latin1.parse(unescape(encodeURIComponent(utf8Str)));
|
|
548
|
+
}
|
|
549
|
+
};
|
|
550
|
+
|
|
551
|
+
/**
|
|
552
|
+
* Abstract buffered block algorithm template.
|
|
553
|
+
*
|
|
554
|
+
* The property blockSize must be implemented in a concrete subtype.
|
|
555
|
+
*
|
|
556
|
+
* @property {number} _minBufferSize The number of blocks that should be kept unprocessed in the buffer. Default: 0
|
|
557
|
+
*/
|
|
558
|
+
var BufferedBlockAlgorithm = C_lib.BufferedBlockAlgorithm = Base.extend({
|
|
559
|
+
/**
|
|
560
|
+
* Resets this block algorithm's data buffer to its initial state.
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
*
|
|
564
|
+
* bufferedBlockAlgorithm.reset();
|
|
565
|
+
*/
|
|
566
|
+
reset: function () {
|
|
567
|
+
// Initial values
|
|
568
|
+
this._data = new WordArray.init();
|
|
569
|
+
this._nDataBytes = 0;
|
|
570
|
+
},
|
|
571
|
+
|
|
572
|
+
/**
|
|
573
|
+
* Adds new data to this block algorithm's buffer.
|
|
574
|
+
*
|
|
575
|
+
* @param {WordArray|string} data The data to append. Strings are converted to a WordArray using UTF-8.
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
*
|
|
579
|
+
* bufferedBlockAlgorithm._append('data');
|
|
580
|
+
* bufferedBlockAlgorithm._append(wordArray);
|
|
581
|
+
*/
|
|
582
|
+
_append: function (data) {
|
|
583
|
+
// Convert string to WordArray, else assume WordArray already
|
|
584
|
+
if (typeof data == 'string') {
|
|
585
|
+
data = Utf8.parse(data);
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
// Append
|
|
589
|
+
this._data.concat(data);
|
|
590
|
+
this._nDataBytes += data.sigBytes;
|
|
591
|
+
},
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Processes available data blocks.
|
|
595
|
+
*
|
|
596
|
+
* This method invokes _doProcessBlock(offset), which must be implemented by a concrete subtype.
|
|
597
|
+
*
|
|
598
|
+
* @param {boolean} doFlush Whether all blocks and partial blocks should be processed.
|
|
599
|
+
*
|
|
600
|
+
* @return {WordArray} The processed data.
|
|
601
|
+
*
|
|
602
|
+
* @example
|
|
603
|
+
*
|
|
604
|
+
* var processedData = bufferedBlockAlgorithm._process();
|
|
605
|
+
* var processedData = bufferedBlockAlgorithm._process(!!'flush');
|
|
606
|
+
*/
|
|
607
|
+
_process: function (doFlush) {
|
|
608
|
+
var processedWords;
|
|
609
|
+
|
|
610
|
+
// Shortcuts
|
|
611
|
+
var data = this._data;
|
|
612
|
+
var dataWords = data.words;
|
|
613
|
+
var dataSigBytes = data.sigBytes;
|
|
614
|
+
var blockSize = this.blockSize;
|
|
615
|
+
var blockSizeBytes = blockSize * 4;
|
|
616
|
+
|
|
617
|
+
// Count blocks ready
|
|
618
|
+
var nBlocksReady = dataSigBytes / blockSizeBytes;
|
|
619
|
+
if (doFlush) {
|
|
620
|
+
// Round up to include partial blocks
|
|
621
|
+
nBlocksReady = Math.ceil(nBlocksReady);
|
|
622
|
+
} else {
|
|
623
|
+
// Round down to include only full blocks,
|
|
624
|
+
// less the number of blocks that must remain in the buffer
|
|
625
|
+
nBlocksReady = Math.max((nBlocksReady | 0) - this._minBufferSize, 0);
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
// Count words ready
|
|
629
|
+
var nWordsReady = nBlocksReady * blockSize;
|
|
630
|
+
|
|
631
|
+
// Count bytes ready
|
|
632
|
+
var nBytesReady = Math.min(nWordsReady * 4, dataSigBytes);
|
|
633
|
+
|
|
634
|
+
// Process blocks
|
|
635
|
+
if (nWordsReady) {
|
|
636
|
+
for (var offset = 0; offset < nWordsReady; offset += blockSize) {
|
|
637
|
+
// Perform concrete-algorithm logic
|
|
638
|
+
this._doProcessBlock(dataWords, offset);
|
|
639
|
+
}
|
|
640
|
+
|
|
641
|
+
// Remove processed words
|
|
642
|
+
processedWords = dataWords.splice(0, nWordsReady);
|
|
643
|
+
data.sigBytes -= nBytesReady;
|
|
644
|
+
}
|
|
645
|
+
|
|
646
|
+
// Return processed words
|
|
647
|
+
return new WordArray.init(processedWords, nBytesReady);
|
|
648
|
+
},
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Creates a copy of this object.
|
|
652
|
+
*
|
|
653
|
+
* @return {Object} The clone.
|
|
654
|
+
*
|
|
655
|
+
* @example
|
|
656
|
+
*
|
|
657
|
+
* var clone = bufferedBlockAlgorithm.clone();
|
|
658
|
+
*/
|
|
659
|
+
clone: function () {
|
|
660
|
+
var clone = Base.clone.call(this);
|
|
661
|
+
clone._data = this._data.clone();
|
|
662
|
+
|
|
663
|
+
return clone;
|
|
664
|
+
},
|
|
665
|
+
|
|
666
|
+
_minBufferSize: 0
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Abstract hasher template.
|
|
671
|
+
*
|
|
672
|
+
* @property {number} blockSize The number of 32-bit words this hasher operates on. Default: 16 (512 bits)
|
|
673
|
+
*/
|
|
674
|
+
C_lib.Hasher = BufferedBlockAlgorithm.extend({
|
|
675
|
+
/**
|
|
676
|
+
* Configuration options.
|
|
677
|
+
*/
|
|
678
|
+
cfg: Base.extend(),
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Initializes a newly created hasher.
|
|
682
|
+
*
|
|
683
|
+
* @param {Object} cfg (Optional) The configuration options to use for this hash computation.
|
|
684
|
+
*
|
|
685
|
+
* @example
|
|
686
|
+
*
|
|
687
|
+
* var hasher = CryptoJS.algo.SHA256.create();
|
|
688
|
+
*/
|
|
689
|
+
init: function (cfg) {
|
|
690
|
+
// Apply config defaults
|
|
691
|
+
this.cfg = this.cfg.extend(cfg);
|
|
692
|
+
|
|
693
|
+
// Set initial values
|
|
694
|
+
this.reset();
|
|
695
|
+
},
|
|
696
|
+
|
|
697
|
+
/**
|
|
698
|
+
* Resets this hasher to its initial state.
|
|
699
|
+
*
|
|
700
|
+
* @example
|
|
701
|
+
*
|
|
702
|
+
* hasher.reset();
|
|
703
|
+
*/
|
|
704
|
+
reset: function () {
|
|
705
|
+
// Reset data buffer
|
|
706
|
+
BufferedBlockAlgorithm.reset.call(this);
|
|
707
|
+
|
|
708
|
+
// Perform concrete-hasher logic
|
|
709
|
+
this._doReset();
|
|
710
|
+
},
|
|
711
|
+
|
|
712
|
+
/**
|
|
713
|
+
* Updates this hasher with a message.
|
|
714
|
+
*
|
|
715
|
+
* @param {WordArray|string} messageUpdate The message to append.
|
|
716
|
+
*
|
|
717
|
+
* @return {Hasher} This hasher.
|
|
718
|
+
*
|
|
719
|
+
* @example
|
|
720
|
+
*
|
|
721
|
+
* hasher.update('message');
|
|
722
|
+
* hasher.update(wordArray);
|
|
723
|
+
*/
|
|
724
|
+
update: function (messageUpdate) {
|
|
725
|
+
// Append
|
|
726
|
+
this._append(messageUpdate);
|
|
727
|
+
|
|
728
|
+
// Update the hash
|
|
729
|
+
this._process();
|
|
730
|
+
|
|
731
|
+
// Chainable
|
|
732
|
+
return this;
|
|
733
|
+
},
|
|
734
|
+
|
|
735
|
+
/**
|
|
736
|
+
* Finalizes the hash computation.
|
|
737
|
+
* Note that the finalize operation is effectively a destructive, read-once operation.
|
|
738
|
+
*
|
|
739
|
+
* @param {WordArray|string} messageUpdate (Optional) A final message update.
|
|
740
|
+
*
|
|
741
|
+
* @return {WordArray} The hash.
|
|
742
|
+
*
|
|
743
|
+
* @example
|
|
744
|
+
*
|
|
745
|
+
* var hash = hasher.finalize();
|
|
746
|
+
* var hash = hasher.finalize('message');
|
|
747
|
+
* var hash = hasher.finalize(wordArray);
|
|
748
|
+
*/
|
|
749
|
+
finalize: function (messageUpdate) {
|
|
750
|
+
// Final message update
|
|
751
|
+
if (messageUpdate) {
|
|
752
|
+
this._append(messageUpdate);
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
// Perform concrete-hasher logic
|
|
756
|
+
var hash = this._doFinalize();
|
|
757
|
+
|
|
758
|
+
return hash;
|
|
759
|
+
},
|
|
760
|
+
|
|
761
|
+
blockSize: 512/32,
|
|
762
|
+
|
|
763
|
+
/**
|
|
764
|
+
* Creates a shortcut function to a hasher's object interface.
|
|
765
|
+
*
|
|
766
|
+
* @param {Hasher} hasher The hasher to create a helper for.
|
|
767
|
+
*
|
|
768
|
+
* @return {Function} The shortcut function.
|
|
769
|
+
*
|
|
770
|
+
* @static
|
|
771
|
+
*
|
|
772
|
+
* @example
|
|
773
|
+
*
|
|
774
|
+
* var SHA256 = CryptoJS.lib.Hasher._createHelper(CryptoJS.algo.SHA256);
|
|
775
|
+
*/
|
|
776
|
+
_createHelper: function (hasher) {
|
|
777
|
+
return function (message, cfg) {
|
|
778
|
+
return new hasher.init(cfg).finalize(message);
|
|
779
|
+
};
|
|
780
|
+
},
|
|
781
|
+
|
|
782
|
+
/**
|
|
783
|
+
* Creates a shortcut function to the HMAC's object interface.
|
|
784
|
+
*
|
|
785
|
+
* @param {Hasher} hasher The hasher to use in this HMAC helper.
|
|
786
|
+
*
|
|
787
|
+
* @return {Function} The shortcut function.
|
|
788
|
+
*
|
|
789
|
+
* @static
|
|
790
|
+
*
|
|
791
|
+
* @example
|
|
792
|
+
*
|
|
793
|
+
* var HmacSHA256 = CryptoJS.lib.Hasher._createHmacHelper(CryptoJS.algo.SHA256);
|
|
794
|
+
*/
|
|
795
|
+
_createHmacHelper: function (hasher) {
|
|
796
|
+
return function (message, key) {
|
|
797
|
+
return new C_algo.HMAC.init(hasher, key).finalize(message);
|
|
798
|
+
};
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Algorithm namespace.
|
|
804
|
+
*/
|
|
805
|
+
var C_algo = C.algo = {};
|
|
806
|
+
|
|
807
|
+
return C;
|
|
808
|
+
}(Math));
|
|
809
|
+
|
|
810
|
+
|
|
811
|
+
return CryptoJS;
|
|
812
|
+
|
|
813
|
+
}));
|
|
814
|
+
});
|
|
815
|
+
|
|
816
|
+
var sha256 = createCommonjsModule(function (module, exports) {
|
|
817
|
+
(function (root, factory) {
|
|
818
|
+
{
|
|
819
|
+
// CommonJS
|
|
820
|
+
module.exports = factory(core);
|
|
821
|
+
}
|
|
822
|
+
}(commonjsGlobal, function (CryptoJS) {
|
|
823
|
+
|
|
824
|
+
(function (Math) {
|
|
825
|
+
// Shortcuts
|
|
826
|
+
var C = CryptoJS;
|
|
827
|
+
var C_lib = C.lib;
|
|
828
|
+
var WordArray = C_lib.WordArray;
|
|
829
|
+
var Hasher = C_lib.Hasher;
|
|
830
|
+
var C_algo = C.algo;
|
|
831
|
+
|
|
832
|
+
// Initialization and round constants tables
|
|
833
|
+
var H = [];
|
|
834
|
+
var K = [];
|
|
835
|
+
|
|
836
|
+
// Compute constants
|
|
837
|
+
(function () {
|
|
838
|
+
function isPrime(n) {
|
|
839
|
+
var sqrtN = Math.sqrt(n);
|
|
840
|
+
for (var factor = 2; factor <= sqrtN; factor++) {
|
|
841
|
+
if (!(n % factor)) {
|
|
842
|
+
return false;
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
|
|
846
|
+
return true;
|
|
847
|
+
}
|
|
848
|
+
|
|
849
|
+
function getFractionalBits(n) {
|
|
850
|
+
return ((n - (n | 0)) * 0x100000000) | 0;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
var n = 2;
|
|
854
|
+
var nPrime = 0;
|
|
855
|
+
while (nPrime < 64) {
|
|
856
|
+
if (isPrime(n)) {
|
|
857
|
+
if (nPrime < 8) {
|
|
858
|
+
H[nPrime] = getFractionalBits(Math.pow(n, 1 / 2));
|
|
859
|
+
}
|
|
860
|
+
K[nPrime] = getFractionalBits(Math.pow(n, 1 / 3));
|
|
861
|
+
|
|
862
|
+
nPrime++;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
n++;
|
|
866
|
+
}
|
|
867
|
+
}());
|
|
868
|
+
|
|
869
|
+
// Reusable object
|
|
870
|
+
var W = [];
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* SHA-256 hash algorithm.
|
|
874
|
+
*/
|
|
875
|
+
var SHA256 = C_algo.SHA256 = Hasher.extend({
|
|
876
|
+
_doReset: function () {
|
|
877
|
+
this._hash = new WordArray.init(H.slice(0));
|
|
878
|
+
},
|
|
879
|
+
|
|
880
|
+
_doProcessBlock: function (M, offset) {
|
|
881
|
+
// Shortcut
|
|
882
|
+
var H = this._hash.words;
|
|
883
|
+
|
|
884
|
+
// Working variables
|
|
885
|
+
var a = H[0];
|
|
886
|
+
var b = H[1];
|
|
887
|
+
var c = H[2];
|
|
888
|
+
var d = H[3];
|
|
889
|
+
var e = H[4];
|
|
890
|
+
var f = H[5];
|
|
891
|
+
var g = H[6];
|
|
892
|
+
var h = H[7];
|
|
893
|
+
|
|
894
|
+
// Computation
|
|
895
|
+
for (var i = 0; i < 64; i++) {
|
|
896
|
+
if (i < 16) {
|
|
897
|
+
W[i] = M[offset + i] | 0;
|
|
898
|
+
} else {
|
|
899
|
+
var gamma0x = W[i - 15];
|
|
900
|
+
var gamma0 = ((gamma0x << 25) | (gamma0x >>> 7)) ^
|
|
901
|
+
((gamma0x << 14) | (gamma0x >>> 18)) ^
|
|
902
|
+
(gamma0x >>> 3);
|
|
903
|
+
|
|
904
|
+
var gamma1x = W[i - 2];
|
|
905
|
+
var gamma1 = ((gamma1x << 15) | (gamma1x >>> 17)) ^
|
|
906
|
+
((gamma1x << 13) | (gamma1x >>> 19)) ^
|
|
907
|
+
(gamma1x >>> 10);
|
|
908
|
+
|
|
909
|
+
W[i] = gamma0 + W[i - 7] + gamma1 + W[i - 16];
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
var ch = (e & f) ^ (~e & g);
|
|
913
|
+
var maj = (a & b) ^ (a & c) ^ (b & c);
|
|
914
|
+
|
|
915
|
+
var sigma0 = ((a << 30) | (a >>> 2)) ^ ((a << 19) | (a >>> 13)) ^ ((a << 10) | (a >>> 22));
|
|
916
|
+
var sigma1 = ((e << 26) | (e >>> 6)) ^ ((e << 21) | (e >>> 11)) ^ ((e << 7) | (e >>> 25));
|
|
917
|
+
|
|
918
|
+
var t1 = h + sigma1 + ch + K[i] + W[i];
|
|
919
|
+
var t2 = sigma0 + maj;
|
|
920
|
+
|
|
921
|
+
h = g;
|
|
922
|
+
g = f;
|
|
923
|
+
f = e;
|
|
924
|
+
e = (d + t1) | 0;
|
|
925
|
+
d = c;
|
|
926
|
+
c = b;
|
|
927
|
+
b = a;
|
|
928
|
+
a = (t1 + t2) | 0;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
// Intermediate hash value
|
|
932
|
+
H[0] = (H[0] + a) | 0;
|
|
933
|
+
H[1] = (H[1] + b) | 0;
|
|
934
|
+
H[2] = (H[2] + c) | 0;
|
|
935
|
+
H[3] = (H[3] + d) | 0;
|
|
936
|
+
H[4] = (H[4] + e) | 0;
|
|
937
|
+
H[5] = (H[5] + f) | 0;
|
|
938
|
+
H[6] = (H[6] + g) | 0;
|
|
939
|
+
H[7] = (H[7] + h) | 0;
|
|
940
|
+
},
|
|
941
|
+
|
|
942
|
+
_doFinalize: function () {
|
|
943
|
+
// Shortcuts
|
|
944
|
+
var data = this._data;
|
|
945
|
+
var dataWords = data.words;
|
|
946
|
+
|
|
947
|
+
var nBitsTotal = this._nDataBytes * 8;
|
|
948
|
+
var nBitsLeft = data.sigBytes * 8;
|
|
949
|
+
|
|
950
|
+
// Add padding
|
|
951
|
+
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
|
|
952
|
+
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = Math.floor(nBitsTotal / 0x100000000);
|
|
953
|
+
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = nBitsTotal;
|
|
954
|
+
data.sigBytes = dataWords.length * 4;
|
|
955
|
+
|
|
956
|
+
// Hash final blocks
|
|
957
|
+
this._process();
|
|
958
|
+
|
|
959
|
+
// Return final computed hash
|
|
960
|
+
return this._hash;
|
|
961
|
+
},
|
|
962
|
+
|
|
963
|
+
clone: function () {
|
|
964
|
+
var clone = Hasher.clone.call(this);
|
|
965
|
+
clone._hash = this._hash.clone();
|
|
966
|
+
|
|
967
|
+
return clone;
|
|
968
|
+
}
|
|
969
|
+
});
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* Shortcut function to the hasher's object interface.
|
|
973
|
+
*
|
|
974
|
+
* @param {WordArray|string} message The message to hash.
|
|
975
|
+
*
|
|
976
|
+
* @return {WordArray} The hash.
|
|
977
|
+
*
|
|
978
|
+
* @static
|
|
979
|
+
*
|
|
980
|
+
* @example
|
|
981
|
+
*
|
|
982
|
+
* var hash = CryptoJS.SHA256('message');
|
|
983
|
+
* var hash = CryptoJS.SHA256(wordArray);
|
|
984
|
+
*/
|
|
985
|
+
C.SHA256 = Hasher._createHelper(SHA256);
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* Shortcut function to the HMAC's object interface.
|
|
989
|
+
*
|
|
990
|
+
* @param {WordArray|string} message The message to hash.
|
|
991
|
+
* @param {WordArray|string} key The secret key.
|
|
992
|
+
*
|
|
993
|
+
* @return {WordArray} The HMAC.
|
|
994
|
+
*
|
|
995
|
+
* @static
|
|
996
|
+
*
|
|
997
|
+
* @example
|
|
998
|
+
*
|
|
999
|
+
* var hmac = CryptoJS.HmacSHA256(message, key);
|
|
1000
|
+
*/
|
|
1001
|
+
C.HmacSHA256 = Hasher._createHmacHelper(SHA256);
|
|
1002
|
+
}(Math));
|
|
1003
|
+
|
|
1004
|
+
|
|
1005
|
+
return CryptoJS.SHA256;
|
|
1006
|
+
|
|
1007
|
+
}));
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
const hasProp = (obj, prop) =>
|
|
1011
|
+
Object.prototype.hasOwnProperty.call(obj, prop);
|
|
1012
|
+
|
|
1013
|
+
function isFalsey(valueObj) {
|
|
1014
|
+
if (!valueObj) {
|
|
1015
|
+
return true;
|
|
1016
|
+
}
|
|
1017
|
+
if (valueObj.class === 'FalseClass') {
|
|
1018
|
+
return true;
|
|
1019
|
+
}
|
|
1020
|
+
if (valueObj.class === 'Array' && valueObj.value === '[]') {
|
|
1021
|
+
return true;
|
|
1022
|
+
}
|
|
1023
|
+
if (valueObj.value === '') {
|
|
1024
|
+
return true;
|
|
1025
|
+
}
|
|
1026
|
+
|
|
1027
|
+
return false;
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
function isCommand(event) {
|
|
1031
|
+
if (event.http_server_request) {
|
|
1032
|
+
return true;
|
|
1033
|
+
}
|
|
1034
|
+
if (event.codeObject.labels.has('command')) {
|
|
1035
|
+
return true;
|
|
1036
|
+
}
|
|
1037
|
+
return false;
|
|
1038
|
+
}
|
|
1039
|
+
|
|
1040
|
+
function capitalizeString(str) {
|
|
1041
|
+
if (typeof str !== 'string') {
|
|
1042
|
+
return '';
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
return str.slice(0, 1).toUpperCase() + str.slice(1).toLowerCase();
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
function getHttpLabel(event) {
|
|
1049
|
+
if (hasProp(event, 'http_server_request') === false) {
|
|
1050
|
+
return null;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
const requestMethod = event.http_server_request.request_method;
|
|
1054
|
+
const pathInfo = event.http_server_request.path_info;
|
|
1055
|
+
let label;
|
|
1056
|
+
|
|
1057
|
+
try {
|
|
1058
|
+
// the url is fake, we only care about the path info anyway
|
|
1059
|
+
const url = new URL(pathInfo, 'http://hostname');
|
|
1060
|
+
label = `${requestMethod} ${url.pathname}`;
|
|
1061
|
+
} catch (ex) {
|
|
1062
|
+
label = 'HTTP Request';
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
return label;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
const sqlLabels = new Set([
|
|
1069
|
+
'insert',
|
|
1070
|
+
'update',
|
|
1071
|
+
'select',
|
|
1072
|
+
'delete',
|
|
1073
|
+
'alter',
|
|
1074
|
+
'create',
|
|
1075
|
+
'drop',
|
|
1076
|
+
'rename',
|
|
1077
|
+
'truncate',
|
|
1078
|
+
'replace',
|
|
1079
|
+
'savepoint',
|
|
1080
|
+
'release',
|
|
1081
|
+
'rollback',
|
|
1082
|
+
'lock',
|
|
1083
|
+
'unlock',
|
|
1084
|
+
'set',
|
|
1085
|
+
'start',
|
|
1086
|
+
'call',
|
|
1087
|
+
'delete',
|
|
1088
|
+
'do',
|
|
1089
|
+
'perform',
|
|
1090
|
+
'handler',
|
|
1091
|
+
'load',
|
|
1092
|
+
'purge',
|
|
1093
|
+
'reset',
|
|
1094
|
+
'prepare',
|
|
1095
|
+
'execute',
|
|
1096
|
+
'deallocate',
|
|
1097
|
+
'xa',
|
|
1098
|
+
]);
|
|
1099
|
+
|
|
1100
|
+
function getSqlLabelFromString(sqlString) {
|
|
1101
|
+
const sqlChars = [...sqlString.trimLeft()];
|
|
1102
|
+
if (sqlChars.length > 0 && sqlChars[0] === '(') {
|
|
1103
|
+
// if the query is wrapped in parenthesis, drop the opening parenthesis
|
|
1104
|
+
// it doesn't matter if we leave a hanging closing parenthesis.
|
|
1105
|
+
// e.g. (SELECT 1);
|
|
1106
|
+
|
|
1107
|
+
sqlChars.shift();
|
|
1108
|
+
}
|
|
1109
|
+
|
|
1110
|
+
// drop sub-queries and parenthesized expressions
|
|
1111
|
+
let depth = 0;
|
|
1112
|
+
const topLevelSql = sqlChars
|
|
1113
|
+
.reduce((arr, c) => {
|
|
1114
|
+
if (c === '(') {
|
|
1115
|
+
depth += 1;
|
|
1116
|
+
}
|
|
1117
|
+
|
|
1118
|
+
if (depth === 0) {
|
|
1119
|
+
arr.push(c);
|
|
1120
|
+
}
|
|
1121
|
+
|
|
1122
|
+
if (c === ')') {
|
|
1123
|
+
depth -= 1;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
return arr;
|
|
1127
|
+
}, [])
|
|
1128
|
+
.join('');
|
|
1129
|
+
|
|
1130
|
+
let queryType = null;
|
|
1131
|
+
if (topLevelSql.search(/\s/) === -1) {
|
|
1132
|
+
// There's only a single token
|
|
1133
|
+
// e.g. BEGIN, COMMIT, CHECKPOINT
|
|
1134
|
+
queryType = topLevelSql;
|
|
1135
|
+
} else {
|
|
1136
|
+
// convert non-word sequences to spaces and split by space
|
|
1137
|
+
// find the first known token
|
|
1138
|
+
queryType = topLevelSql
|
|
1139
|
+
.replace(/[^\w]+/g, ' ')
|
|
1140
|
+
.toLowerCase()
|
|
1141
|
+
.split(' ')
|
|
1142
|
+
.find((t) => sqlLabels.has(t));
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1145
|
+
return ['SQL', capitalizeString(queryType) || null].join(' ');
|
|
1146
|
+
}
|
|
1147
|
+
function getSqlLabel(event) {
|
|
1148
|
+
if (hasProp(event, 'sql_query') === false) {
|
|
1149
|
+
return null;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
return getSqlLabelFromString(
|
|
1153
|
+
event.sql_query.normalized_sql || event.sql_query.sql || ''
|
|
1154
|
+
);
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1157
|
+
function getLabel(event) {
|
|
1158
|
+
let label = getHttpLabel(event);
|
|
1159
|
+
if (!label) {
|
|
1160
|
+
label = getSqlLabel(event);
|
|
1161
|
+
}
|
|
1162
|
+
return label;
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
function hashify(obj) {
|
|
1166
|
+
const clone = { ...obj };
|
|
1167
|
+
Object.keys(obj).forEach((key) => {
|
|
1168
|
+
const val = obj[key];
|
|
1169
|
+
if (Array.isArray(val)) {
|
|
1170
|
+
clone[key] = new Set(val);
|
|
1171
|
+
} else if (val instanceof Set) {
|
|
1172
|
+
clone[key] = val;
|
|
1173
|
+
} else if (val && typeof val === 'object') {
|
|
1174
|
+
clone[key] = hashify(val);
|
|
1175
|
+
} else {
|
|
1176
|
+
clone[key] = val;
|
|
1177
|
+
}
|
|
1178
|
+
});
|
|
1179
|
+
return clone;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
const REPOSITORY_RESOLVERS = {
|
|
1183
|
+
github: (d) => {
|
|
1184
|
+
const match = d.url.match(/github.com[:|/]?(.*).git/);
|
|
1185
|
+
if (!match || match.length <= 1) {
|
|
1186
|
+
return null;
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
const hash = typeof d.lineNumber === 'number' ? `#L${d.lineNumber}` : '';
|
|
1190
|
+
return `https://github.com/${match[1]}/blob/${d.commit}/${d.path}${hash}`;
|
|
1191
|
+
},
|
|
1192
|
+
};
|
|
1193
|
+
|
|
1194
|
+
function getRepositoryUrl(
|
|
1195
|
+
url,
|
|
1196
|
+
path,
|
|
1197
|
+
commit = 'master',
|
|
1198
|
+
lineNumber = null
|
|
1199
|
+
) {
|
|
1200
|
+
if (url && path) {
|
|
1201
|
+
const d = { url, path, lineNumber, commit };
|
|
1202
|
+
const resolvers = Object.values(REPOSITORY_RESOLVERS);
|
|
1203
|
+
for (let i = 0; i < resolvers.length; i += 1) {
|
|
1204
|
+
const repositoryUrl = resolvers[i](d);
|
|
1205
|
+
if (repositoryUrl) {
|
|
1206
|
+
return repositoryUrl;
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
|
|
1211
|
+
return null;
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
const UPPER = 0x1;
|
|
1215
|
+
const LOWER = 0x10;
|
|
1216
|
+
const getCase = (char) => (/[A-Z]/.exec(char) === null ? LOWER : UPPER);
|
|
1217
|
+
const getCasePattern = (str) => {
|
|
1218
|
+
if (str.length <= 2) {
|
|
1219
|
+
return null;
|
|
1220
|
+
}
|
|
1221
|
+
|
|
1222
|
+
return {
|
|
1223
|
+
firstCase: getCase(str[0]),
|
|
1224
|
+
secondCase: getCase(str[1]),
|
|
1225
|
+
};
|
|
1226
|
+
};
|
|
1227
|
+
|
|
1228
|
+
const splitCamelCase = (str) => {
|
|
1229
|
+
const strLen = str.length;
|
|
1230
|
+
if (strLen < 1) {
|
|
1231
|
+
return [];
|
|
1232
|
+
}
|
|
1233
|
+
|
|
1234
|
+
const casePattern = getCasePattern(str);
|
|
1235
|
+
if (!casePattern) {
|
|
1236
|
+
return [str];
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
const { firstCase, secondCase } = casePattern;
|
|
1240
|
+
const ret = [];
|
|
1241
|
+
let matched = false;
|
|
1242
|
+
for (let i = 2; i < strLen; i += 1) {
|
|
1243
|
+
const charCase = getCase(str[i]);
|
|
1244
|
+
if (charCase === UPPER) {
|
|
1245
|
+
if (firstCase === LOWER || secondCase === LOWER) {
|
|
1246
|
+
const token = str.slice(0, i);
|
|
1247
|
+
ret.push(token);
|
|
1248
|
+
ret.push(...splitCamelCase(str.slice(i)));
|
|
1249
|
+
matched = true;
|
|
1250
|
+
break;
|
|
1251
|
+
}
|
|
1252
|
+
} else if (
|
|
1253
|
+
charCase === LOWER &&
|
|
1254
|
+
firstCase === UPPER &&
|
|
1255
|
+
secondCase === UPPER
|
|
1256
|
+
) {
|
|
1257
|
+
const token = str.slice(0, i - 1);
|
|
1258
|
+
ret.push(token);
|
|
1259
|
+
ret.push(...splitCamelCase(str.slice(i - 1)));
|
|
1260
|
+
matched = true;
|
|
1261
|
+
break;
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
|
|
1265
|
+
if (!matched) {
|
|
1266
|
+
ret.push(str);
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
return ret;
|
|
1270
|
+
};
|
|
1271
|
+
|
|
1272
|
+
// Builds the fully qualified function name of a function (static or instance) within a
|
|
1273
|
+
// fully qualified class name.
|
|
1274
|
+
function fullyQualifiedFunctionName(event) {
|
|
1275
|
+
const label = getLabel(event);
|
|
1276
|
+
if (label) {
|
|
1277
|
+
return label;
|
|
1278
|
+
}
|
|
1279
|
+
|
|
1280
|
+
return event.toString();
|
|
1281
|
+
}
|
|
1282
|
+
|
|
1283
|
+
// tokenizeIdentifier returns tokens of an identifier split by non-alphanumeric and camel casing
|
|
1284
|
+
// example:
|
|
1285
|
+
// someMethodName -> [ 'some', 'method', 'name' ]
|
|
1286
|
+
// some_method_name -> [ 'some', 'method', 'name' ]
|
|
1287
|
+
// org.company.MyPackage.MyClass -> [ 'org', 'company', 'My', 'Package', 'My', 'Class']
|
|
1288
|
+
function tokenizeIdentifier(id) {
|
|
1289
|
+
const ret = [];
|
|
1290
|
+
|
|
1291
|
+
// Split first by non-alphanumeric tokens
|
|
1292
|
+
const tokens = (id || '').split(/[$.:#\-_]/);
|
|
1293
|
+
|
|
1294
|
+
// Split remaining tokens by camel case
|
|
1295
|
+
tokens.forEach((token) => {
|
|
1296
|
+
ret.push(...splitCamelCase(token));
|
|
1297
|
+
});
|
|
1298
|
+
|
|
1299
|
+
return ret;
|
|
1300
|
+
}
|
|
1301
|
+
|
|
1302
|
+
function addHiddenProperty(obj, property, opts) {
|
|
1303
|
+
if (!Object.hasOwnProperty.call(obj, '$hidden')) {
|
|
1304
|
+
Object.defineProperty(obj, '$hidden', {
|
|
1305
|
+
enumerable: false,
|
|
1306
|
+
writable: false,
|
|
1307
|
+
value: {},
|
|
1308
|
+
});
|
|
1309
|
+
}
|
|
1310
|
+
|
|
1311
|
+
Object.defineProperty(obj.$hidden, property, {
|
|
1312
|
+
enumerable: false,
|
|
1313
|
+
writable: true,
|
|
1314
|
+
...opts,
|
|
1315
|
+
});
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
function buildLabels(classMap, events) {
|
|
1319
|
+
const result = {};
|
|
1320
|
+
|
|
1321
|
+
function addLabel(label, obj, type, target) {
|
|
1322
|
+
/* eslint-disable no-param-reassign */
|
|
1323
|
+
if (!obj[label]) {
|
|
1324
|
+
obj[label] = {};
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
if (!obj[label][type]) {
|
|
1328
|
+
obj[label][type] = [];
|
|
1329
|
+
}
|
|
1330
|
+
|
|
1331
|
+
obj[label][type].push(target);
|
|
1332
|
+
/* eslint-enable no-param-reassign */
|
|
1333
|
+
}
|
|
1334
|
+
|
|
1335
|
+
classMap.codeObjects
|
|
1336
|
+
.filter((obj) => obj.labels.size)
|
|
1337
|
+
.forEach((codeObject) => {
|
|
1338
|
+
Array.from(codeObject.labels).forEach((label) => {
|
|
1339
|
+
addLabel(label, result, codeObject.type, codeObject);
|
|
1340
|
+
});
|
|
1341
|
+
});
|
|
1342
|
+
|
|
1343
|
+
events
|
|
1344
|
+
.filter((event) => event.isCall() && event.labels.size)
|
|
1345
|
+
.forEach((event) => {
|
|
1346
|
+
Array.from(event.labels).forEach((label) => {
|
|
1347
|
+
addLabel(label, result, 'event', event);
|
|
1348
|
+
});
|
|
1349
|
+
});
|
|
1350
|
+
|
|
1351
|
+
return result;
|
|
1352
|
+
}
|
|
1353
|
+
|
|
1354
|
+
// sizeof returns a naive byte count for an object when serialized.
|
|
1355
|
+
// I was using an external library for this (object-sizeof), but getting results off by a factor of
|
|
1356
|
+
// ~2. This is awfully wasteful, slow and inaccurate but it works for now. -DB
|
|
1357
|
+
const sizeof = (obj) => JSON.stringify(obj).length;
|
|
1358
|
+
|
|
1359
|
+
const DYNAMIC_FIELDS = new Set([
|
|
1360
|
+
'id',
|
|
1361
|
+
'value',
|
|
1362
|
+
'thread_id',
|
|
1363
|
+
'elapsed',
|
|
1364
|
+
'object_id',
|
|
1365
|
+
'lineno',
|
|
1366
|
+
'path',
|
|
1367
|
+
]);
|
|
1368
|
+
|
|
1369
|
+
function getStaticPropValues(obj) {
|
|
1370
|
+
return Object.getOwnPropertyNames(obj)
|
|
1371
|
+
.filter((k) => typeof obj[k] !== 'object' && !DYNAMIC_FIELDS.has(k))
|
|
1372
|
+
.sort()
|
|
1373
|
+
.map((k) => obj[k]);
|
|
1374
|
+
}
|
|
1375
|
+
|
|
1376
|
+
/* eslint-disable no-inner-declarations */
|
|
1377
|
+
function parseNormalizeSQL(sql) {
|
|
1378
|
+
const parseSQL = sql.replace(/\s+returning\s+\*/i, '');
|
|
1379
|
+
let ast;
|
|
1380
|
+
try {
|
|
1381
|
+
ast = sqliteParser__default['default'](parseSQL);
|
|
1382
|
+
} catch (e) {
|
|
1383
|
+
console.warn(`Unable to parse ${parseSQL} : ${e.message}`);
|
|
1384
|
+
return null;
|
|
1385
|
+
}
|
|
1386
|
+
|
|
1387
|
+
try {
|
|
1388
|
+
const actions = [];
|
|
1389
|
+
const columns = [];
|
|
1390
|
+
const tables = [];
|
|
1391
|
+
|
|
1392
|
+
function parse(statement) {
|
|
1393
|
+
const tokens = ['type', 'variant']
|
|
1394
|
+
.map((propertyName) => statement[propertyName])
|
|
1395
|
+
.filter((value) => value);
|
|
1396
|
+
|
|
1397
|
+
const key = tokens.join('.');
|
|
1398
|
+
// eslint-disable-next-line no-use-before-define
|
|
1399
|
+
let parser = parsers[key];
|
|
1400
|
+
if (!parser) {
|
|
1401
|
+
// eslint-disable-next-line no-use-before-define
|
|
1402
|
+
parser = parseStatement;
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
const parserList = Array.isArray(parser) ? parser : [parser];
|
|
1406
|
+
parserList.forEach((prs) => prs(statement));
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
function parseStatement(statement) {
|
|
1410
|
+
const reservedWords = ['type', 'variant', 'name', 'value'];
|
|
1411
|
+
Object.keys(statement)
|
|
1412
|
+
.filter((property) => !reservedWords.includes(property))
|
|
1413
|
+
.map((propertyName) => statement[propertyName])
|
|
1414
|
+
.forEach((property) => {
|
|
1415
|
+
if (Array.isArray(property)) {
|
|
1416
|
+
property.forEach(parse);
|
|
1417
|
+
} else if (typeof property === 'object') {
|
|
1418
|
+
parse(property);
|
|
1419
|
+
} else if (
|
|
1420
|
+
typeof property === 'string' ||
|
|
1421
|
+
typeof property === 'boolean'
|
|
1422
|
+
) {
|
|
1423
|
+
// pass
|
|
1424
|
+
} else {
|
|
1425
|
+
console.warn(
|
|
1426
|
+
`Unrecognized subexpression: ${typeof property} ${property}`
|
|
1427
|
+
);
|
|
1428
|
+
}
|
|
1429
|
+
});
|
|
1430
|
+
}
|
|
1431
|
+
|
|
1432
|
+
function parseList(listElements, statement) {
|
|
1433
|
+
listElements.forEach((listElement) => {
|
|
1434
|
+
const subExpression = statement[listElement];
|
|
1435
|
+
if (Array.isArray(subExpression)) {
|
|
1436
|
+
subExpression.forEach(parse);
|
|
1437
|
+
} else if (typeof subExpression === 'object') {
|
|
1438
|
+
parse(subExpression);
|
|
1439
|
+
} else {
|
|
1440
|
+
console.warn(`Unrecognized subexpression: ${subExpression}`);
|
|
1441
|
+
}
|
|
1442
|
+
});
|
|
1443
|
+
}
|
|
1444
|
+
const nop = () => {};
|
|
1445
|
+
function parseIdentifierExpression(statement) {
|
|
1446
|
+
if (statement.format === 'table') {
|
|
1447
|
+
tables.push(statement.name);
|
|
1448
|
+
}
|
|
1449
|
+
parseList(['columns'], statement);
|
|
1450
|
+
}
|
|
1451
|
+
function recordAction(action) {
|
|
1452
|
+
return () => {
|
|
1453
|
+
actions.push(action);
|
|
1454
|
+
};
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
const parsers = {
|
|
1458
|
+
'literal.text': nop,
|
|
1459
|
+
'literal.decimal': nop,
|
|
1460
|
+
'identifier.star': (statement) => columns.push(statement.name),
|
|
1461
|
+
'identifier.column': (statement) => columns.push(statement.name),
|
|
1462
|
+
'identifier.table': (statement) => tables.push(statement.name),
|
|
1463
|
+
'identifier.expression': parseIdentifierExpression,
|
|
1464
|
+
'statement.select': [recordAction('select'), parseStatement],
|
|
1465
|
+
'statement.insert': [recordAction('insert'), parseStatement],
|
|
1466
|
+
'statement.update': [recordAction('update'), parseStatement],
|
|
1467
|
+
'statement.delete': [recordAction('delete'), parseStatement],
|
|
1468
|
+
'statement.pragma': nop,
|
|
1469
|
+
};
|
|
1470
|
+
|
|
1471
|
+
parse(ast);
|
|
1472
|
+
|
|
1473
|
+
function unique(list) {
|
|
1474
|
+
return [...new Set(list)];
|
|
1475
|
+
}
|
|
1476
|
+
const uniqueActions = unique(actions).sort();
|
|
1477
|
+
|
|
1478
|
+
return {
|
|
1479
|
+
actions: uniqueActions,
|
|
1480
|
+
tables: unique(tables).sort(),
|
|
1481
|
+
columns: unique(columns).sort(),
|
|
1482
|
+
};
|
|
1483
|
+
} catch (e) {
|
|
1484
|
+
console.warn(`Unable to interpret AST tree for ${parseSQL} : ${e.message}`);
|
|
1485
|
+
return null;
|
|
1486
|
+
}
|
|
1487
|
+
}
|
|
1488
|
+
/* eslint-enable no-inner-declarations */
|
|
1489
|
+
|
|
1490
|
+
function dumbNormalizeSQL(sql) {
|
|
1491
|
+
const sqlLower = sql.toLowerCase().trim();
|
|
1492
|
+
if (sqlLower.indexOf('pragma') === 0) {
|
|
1493
|
+
return {
|
|
1494
|
+
tables: [],
|
|
1495
|
+
columns: [],
|
|
1496
|
+
};
|
|
1497
|
+
}
|
|
1498
|
+
|
|
1499
|
+
const stopWords = ['where', 'limit', 'order by', 'group by', 'values', 'set'];
|
|
1500
|
+
const stopWordLocations = stopWords
|
|
1501
|
+
.map((word) => sqlLower.indexOf(` ${word}`))
|
|
1502
|
+
.filter((index) => index !== -1)
|
|
1503
|
+
.sort();
|
|
1504
|
+
if (stopWordLocations.length > 0) {
|
|
1505
|
+
const subSQL = sql.slice(0, stopWordLocations[0] - 1);
|
|
1506
|
+
return subSQL.replace(
|
|
1507
|
+
/\s([\w_]+)\(\s+'?[w\d]+'?\)\s+\)(?:\s|^)/g,
|
|
1508
|
+
'$1(...)'
|
|
1509
|
+
);
|
|
1510
|
+
}
|
|
1511
|
+
|
|
1512
|
+
console.warn(`Unparseable: ${sql}`);
|
|
1513
|
+
return 'Unparseable';
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
/**
|
|
1517
|
+
* It's essential to normalize SQL to remove trivial differences like WHERE clauses on
|
|
1518
|
+
* generated id values, timestamps, etc.
|
|
1519
|
+
*
|
|
1520
|
+
* @param {string} sql
|
|
1521
|
+
*/
|
|
1522
|
+
function normalizeSQL(sql) {
|
|
1523
|
+
return parseNormalizeSQL(sql) || dumbNormalizeSQL(sql);
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
// #region ========= BEGIN UNUSED CODE =========
|
|
1527
|
+
// These are called from Event.compare, but that method may be removed.
|
|
1528
|
+
// Don't merge me!
|
|
1529
|
+
|
|
1530
|
+
function appMapObjectCompare(a, b) {
|
|
1531
|
+
if (a === b) {
|
|
1532
|
+
return true;
|
|
1533
|
+
}
|
|
1534
|
+
|
|
1535
|
+
if (!a || !b) {
|
|
1536
|
+
return false;
|
|
1537
|
+
}
|
|
1538
|
+
|
|
1539
|
+
const props = [
|
|
1540
|
+
...new Set([
|
|
1541
|
+
...Object.getOwnPropertyNames(a),
|
|
1542
|
+
...Object.getOwnPropertyNames(b),
|
|
1543
|
+
]),
|
|
1544
|
+
].filter((k) => !DYNAMIC_FIELDS.has(k));
|
|
1545
|
+
|
|
1546
|
+
// return the props that differ
|
|
1547
|
+
return props.filter((k) => a[k] !== b[k]);
|
|
1548
|
+
}
|
|
1549
|
+
|
|
1550
|
+
function sqlCompare(a, b) {
|
|
1551
|
+
let { sqlQuery: sqlQueryA } = a;
|
|
1552
|
+
let { sqlQuery: sqlQueryB } = b;
|
|
1553
|
+
|
|
1554
|
+
if (sqlQueryA === sqlQueryB) {
|
|
1555
|
+
return true;
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
if (!sqlQueryA || !sqlQueryB) {
|
|
1559
|
+
return false;
|
|
1560
|
+
}
|
|
1561
|
+
|
|
1562
|
+
sqlQueryA = normalizeSQL(sqlQueryA);
|
|
1563
|
+
sqlQueryB = normalizeSQL(sqlQueryB);
|
|
1564
|
+
|
|
1565
|
+
if (sqlQueryA.action !== sqlQueryB.action) {
|
|
1566
|
+
return false;
|
|
1567
|
+
}
|
|
1568
|
+
|
|
1569
|
+
const allColumns = [...sqlQueryA.columns, ...sqlQueryB.columns];
|
|
1570
|
+
const allTables = [...sqlQueryA.tables, ...sqlQueryB.tables];
|
|
1571
|
+
|
|
1572
|
+
return (
|
|
1573
|
+
allColumns.find(
|
|
1574
|
+
(c) => !sqlQueryA.columns.includes(c) || !sqlQueryB.columns.includes(c)
|
|
1575
|
+
) === undefined &&
|
|
1576
|
+
allTables.find(
|
|
1577
|
+
(c) => !sqlQueryA.tables.includes(c) || !sqlQueryB.tables.includes(c)
|
|
1578
|
+
) === undefined
|
|
1579
|
+
);
|
|
1580
|
+
}
|
|
1581
|
+
|
|
1582
|
+
function arrayCompare(a, b) {
|
|
1583
|
+
if (a === b) {
|
|
1584
|
+
return true;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
if (!a || !b) {
|
|
1588
|
+
return false;
|
|
1589
|
+
}
|
|
1590
|
+
|
|
1591
|
+
const lengthA = a ? a.length || 0 : 0;
|
|
1592
|
+
const lengthB = b ? b.length || 0 : 0;
|
|
1593
|
+
|
|
1594
|
+
if (lengthA !== lengthB) {
|
|
1595
|
+
return false;
|
|
1596
|
+
}
|
|
1597
|
+
|
|
1598
|
+
for (let i = 0; i < lengthA; i += 1) {
|
|
1599
|
+
if (!appMapObjectCompare(a[i], b[i])) {
|
|
1600
|
+
return false;
|
|
1601
|
+
}
|
|
1602
|
+
}
|
|
1603
|
+
|
|
1604
|
+
return true;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
function httpCompare(a, b) {
|
|
1608
|
+
const {
|
|
1609
|
+
message: messageA,
|
|
1610
|
+
httpServerRequest: httpServerRequestA,
|
|
1611
|
+
httpServerResponse: httpServerResponseA,
|
|
1612
|
+
} = a;
|
|
1613
|
+
|
|
1614
|
+
const {
|
|
1615
|
+
message: messageB,
|
|
1616
|
+
httpServerRequest: httpServerRequestB,
|
|
1617
|
+
httpServerResponse: httpServerResponseB,
|
|
1618
|
+
} = b;
|
|
1619
|
+
|
|
1620
|
+
return (
|
|
1621
|
+
arrayCompare(messageA, messageB) &&
|
|
1622
|
+
appMapObjectCompare(httpServerRequestA, httpServerRequestB) &&
|
|
1623
|
+
appMapObjectCompare(httpServerResponseA, httpServerResponseB)
|
|
1624
|
+
);
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
function setCompare(a, b) {
|
|
1628
|
+
if (a === b) {
|
|
1629
|
+
return true;
|
|
1630
|
+
}
|
|
1631
|
+
|
|
1632
|
+
if (!a || !b) {
|
|
1633
|
+
return false;
|
|
1634
|
+
}
|
|
1635
|
+
|
|
1636
|
+
const allItems = [...new Set([...a, ...b])];
|
|
1637
|
+
return allItems.find((i) => !a.has(i) || !b.has(i)) === undefined;
|
|
1638
|
+
}
|
|
1639
|
+
// #endregion ========= END UNUSED CODE =========
|
|
1640
|
+
|
|
1641
|
+
function hashHttp(e) {
|
|
1642
|
+
const { httpServerRequest } = e;
|
|
1643
|
+
if (!httpServerRequest) {
|
|
1644
|
+
return null;
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
const { message, httpServerResponse } = e;
|
|
1648
|
+
const content = [];
|
|
1649
|
+
message.forEach((m) =>
|
|
1650
|
+
getStaticPropValues(m).forEach((v) => content.push(v))
|
|
1651
|
+
);
|
|
1652
|
+
getStaticPropValues(httpServerResponse).forEach((v) => content.push(v));
|
|
1653
|
+
getStaticPropValues(httpServerRequest).forEach((v) => content.push(v));
|
|
1654
|
+
|
|
1655
|
+
return sha256(content.join('')).toString();
|
|
1656
|
+
}
|
|
1657
|
+
|
|
1658
|
+
function hashSql(e) {
|
|
1659
|
+
const { sqlQuery } = e;
|
|
1660
|
+
if (!sqlQuery) {
|
|
1661
|
+
return null;
|
|
1662
|
+
}
|
|
1663
|
+
|
|
1664
|
+
const normalizedSql = normalizeSQL(sqlQuery);
|
|
1665
|
+
const content = [normalizedSql.action];
|
|
1666
|
+
|
|
1667
|
+
if (normalizedSql.columns) {
|
|
1668
|
+
normalizedSql.columns.forEach((c) => content.push(c));
|
|
1669
|
+
}
|
|
1670
|
+
|
|
1671
|
+
if (normalizedSql.tables) {
|
|
1672
|
+
normalizedSql.tables.forEach((t) => content.push(t));
|
|
1673
|
+
}
|
|
1674
|
+
|
|
1675
|
+
return sha256(content.join('')).toString();
|
|
1676
|
+
}
|
|
1677
|
+
|
|
1678
|
+
// Returns a unique 'hash' (or really, a key) tied to the event's core identity: SQL, HTTP, or a
|
|
1679
|
+
// specific method on a specific class. This is _really_ naive. The idea is that this better finds
|
|
1680
|
+
// a singular change versus an existing object that has been removed and a new object added in its
|
|
1681
|
+
// place.
|
|
1682
|
+
function identityHashEvent(e) {
|
|
1683
|
+
if (e.httpServerRequest) {
|
|
1684
|
+
return 'http';
|
|
1685
|
+
}
|
|
1686
|
+
|
|
1687
|
+
const { sqlQuery } = e;
|
|
1688
|
+
if (sqlQuery) {
|
|
1689
|
+
const queryOps = normalizeSQL(sqlQuery);
|
|
1690
|
+
const content = ['sql', queryOps.action, ...queryOps.tables]
|
|
1691
|
+
.filter(Boolean)
|
|
1692
|
+
.join('');
|
|
1693
|
+
return sha256(content).toString();
|
|
1694
|
+
}
|
|
1695
|
+
|
|
1696
|
+
return e.toString();
|
|
1697
|
+
}
|
|
1698
|
+
|
|
1699
|
+
function hashEvent(e) {
|
|
1700
|
+
let hash = hashHttp(e);
|
|
1701
|
+
if (hash) {
|
|
1702
|
+
return hash;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
hash = hashSql(e);
|
|
1706
|
+
if (hash) {
|
|
1707
|
+
return hash;
|
|
1708
|
+
}
|
|
1709
|
+
|
|
1710
|
+
const content = [];
|
|
1711
|
+
getStaticPropValues(e).forEach((v) => content.push(v));
|
|
1712
|
+
e.parameters.forEach((p) =>
|
|
1713
|
+
getStaticPropValues(p).forEach((v) => content.push(v))
|
|
1714
|
+
);
|
|
1715
|
+
[...e.labels].forEach((l) => content.push(l));
|
|
1716
|
+
|
|
1717
|
+
return sha256(content.join('')).toString();
|
|
1718
|
+
}
|
|
1719
|
+
|
|
1720
|
+
function resolveDifferences(arr1, arr2) {
|
|
1721
|
+
let arr1Index = 0;
|
|
1722
|
+
let arr2Index = 0;
|
|
1723
|
+
|
|
1724
|
+
for (;;) {
|
|
1725
|
+
const a = arr1[arr1Index];
|
|
1726
|
+
const b = arr2[arr2Index];
|
|
1727
|
+
if (!a && !b) {
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
|
|
1731
|
+
if (typeof a === 'undefined') {
|
|
1732
|
+
arr1.push(null);
|
|
1733
|
+
arr1Index += 1;
|
|
1734
|
+
arr2Index += 1;
|
|
1735
|
+
continue; // eslint-disable-line no-continue
|
|
1736
|
+
}
|
|
1737
|
+
|
|
1738
|
+
if (typeof b === 'undefined') {
|
|
1739
|
+
arr2.push(null);
|
|
1740
|
+
arr1Index += 1;
|
|
1741
|
+
arr2Index += 1;
|
|
1742
|
+
continue; // eslint-disable-line no-continue
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
const hashA = a.identityHash;
|
|
1746
|
+
const hashB = b.identityHash;
|
|
1747
|
+
if (hashA !== hashB) {
|
|
1748
|
+
let instancesA = 0;
|
|
1749
|
+
for (let i = arr1Index + 1; i < arr1.length; i += 1) {
|
|
1750
|
+
instancesA += arr1[i].identityHash === hashA ? 1 : 0;
|
|
1751
|
+
}
|
|
1752
|
+
|
|
1753
|
+
let instancesB = 0;
|
|
1754
|
+
for (let i = arr2Index + 1; i < arr2.length; i += 1) {
|
|
1755
|
+
instancesB += arr2[i].identityHash === hashA ? 1 : 0;
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1758
|
+
if (instancesA >= instancesB) {
|
|
1759
|
+
arr2.splice(arr2Index, 0, null);
|
|
1760
|
+
} else if (instancesA < instancesB) {
|
|
1761
|
+
arr1.splice(arr1Index, 0, null);
|
|
1762
|
+
} // eslint-disable-line no-continue
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
arr1Index += 1;
|
|
1766
|
+
arr2Index += 1;
|
|
1767
|
+
}
|
|
1768
|
+
}
|
|
1769
|
+
|
|
1770
|
+
function getRootEvents(eventArray) {
|
|
1771
|
+
let events = eventArray.filter((e) => e.isCall() && e.httpServerRequest);
|
|
1772
|
+
if (events.length === 0) {
|
|
1773
|
+
events = eventArray.filter((e) => e.isCall() && !e.parent);
|
|
1774
|
+
}
|
|
1775
|
+
return events;
|
|
1776
|
+
}
|
|
1777
|
+
|
|
1778
|
+
const CodeObjectType = {
|
|
1779
|
+
DATABASE: 'database',
|
|
1780
|
+
QUERY: 'query',
|
|
1781
|
+
HTTP: 'http',
|
|
1782
|
+
EXTERNAL_SERVICE: 'external-service',
|
|
1783
|
+
ROUTE: 'route',
|
|
1784
|
+
PACKAGE: 'package',
|
|
1785
|
+
CLASS: 'class',
|
|
1786
|
+
FUNCTION: 'function',
|
|
1787
|
+
};
|
|
1788
|
+
|
|
1789
|
+
class CodeObject {
|
|
1790
|
+
constructor(data, parent) {
|
|
1791
|
+
this.data = { ...data };
|
|
1792
|
+
|
|
1793
|
+
if (!(this.data.labels instanceof Set)) {
|
|
1794
|
+
this.data.labels = new Set(this.data.labels);
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
this.children = [];
|
|
1798
|
+
if (parent) {
|
|
1799
|
+
parent.children.push(this);
|
|
1800
|
+
}
|
|
1801
|
+
|
|
1802
|
+
addHiddenProperty(this, 'parent', { value: parent });
|
|
1803
|
+
addHiddenProperty(this, 'events', { writable: false, value: [] });
|
|
1804
|
+
}
|
|
1805
|
+
|
|
1806
|
+
get id() {
|
|
1807
|
+
const tokens = this.buildId();
|
|
1808
|
+
|
|
1809
|
+
if (this.parent && this.type === CodeObjectType.FUNCTION) {
|
|
1810
|
+
const separator = this.static ? '.' : '#';
|
|
1811
|
+
tokens[tokens.length - 2] = separator;
|
|
1812
|
+
}
|
|
1813
|
+
|
|
1814
|
+
return tokens.join('');
|
|
1815
|
+
}
|
|
1816
|
+
|
|
1817
|
+
get name() {
|
|
1818
|
+
return this.data.name;
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
get type() {
|
|
1822
|
+
return this.data.type;
|
|
1823
|
+
}
|
|
1824
|
+
|
|
1825
|
+
get static() {
|
|
1826
|
+
return this.data.static;
|
|
1827
|
+
}
|
|
1828
|
+
|
|
1829
|
+
get location() {
|
|
1830
|
+
return this.data.location;
|
|
1831
|
+
}
|
|
1832
|
+
|
|
1833
|
+
get labels() {
|
|
1834
|
+
return this.data.labels;
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
get events() {
|
|
1838
|
+
return this.$hidden.events;
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
get parent() {
|
|
1842
|
+
return this.$hidden.parent;
|
|
1843
|
+
}
|
|
1844
|
+
|
|
1845
|
+
set parent(val) {
|
|
1846
|
+
this.$hidden.parent = val;
|
|
1847
|
+
}
|
|
1848
|
+
|
|
1849
|
+
// Gets the source locations for this code object. For a package, no source locations are returned
|
|
1850
|
+
// (there would be too many to be useful). For a class, the paths to all files which add methods to the class are
|
|
1851
|
+
// returned. For a function, the path and line number is returned.
|
|
1852
|
+
get locations() {
|
|
1853
|
+
switch (this.type) {
|
|
1854
|
+
case CodeObjectType.CLASS:
|
|
1855
|
+
return Array.from(this.classLocations()).sort();
|
|
1856
|
+
case CodeObjectType.FUNCTION:
|
|
1857
|
+
return [this.location];
|
|
1858
|
+
default:
|
|
1859
|
+
return [];
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
|
|
1863
|
+
get packageOf() {
|
|
1864
|
+
return [this, ...this.ancestors()]
|
|
1865
|
+
.filter((obj) => obj.type === CodeObjectType.PACKAGE)
|
|
1866
|
+
.map((obj) => obj.name)
|
|
1867
|
+
.reverse()
|
|
1868
|
+
.join('/');
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
get classOf() {
|
|
1872
|
+
return [this, ...this.ancestors()]
|
|
1873
|
+
.filter((obj) => obj.type === CodeObjectType.CLASS)
|
|
1874
|
+
.map((obj) => obj.name)
|
|
1875
|
+
.reverse()
|
|
1876
|
+
.join('::');
|
|
1877
|
+
}
|
|
1878
|
+
|
|
1879
|
+
get classObject() {
|
|
1880
|
+
return [this, ...this.ancestors()].find(
|
|
1881
|
+
(obj) => obj.type === CodeObjectType.CLASS
|
|
1882
|
+
);
|
|
1883
|
+
}
|
|
1884
|
+
|
|
1885
|
+
get packageObject() {
|
|
1886
|
+
return [this, ...this.ancestors()].find(
|
|
1887
|
+
(obj) => obj.type === CodeObjectType.PACKAGE
|
|
1888
|
+
);
|
|
1889
|
+
}
|
|
1890
|
+
|
|
1891
|
+
get functions() {
|
|
1892
|
+
if (this.type === CodeObjectType.CLASS) {
|
|
1893
|
+
// getting the functions of a class should not return functions of nested classes
|
|
1894
|
+
return this.children.filter(
|
|
1895
|
+
(obj) => obj.type === CodeObjectType.FUNCTION
|
|
1896
|
+
);
|
|
1897
|
+
}
|
|
1898
|
+
|
|
1899
|
+
return this.descendants().filter(
|
|
1900
|
+
(obj) => obj.type === CodeObjectType.FUNCTION
|
|
1901
|
+
);
|
|
1902
|
+
}
|
|
1903
|
+
|
|
1904
|
+
get classes() {
|
|
1905
|
+
return [this, ...this.descendants()].filter(
|
|
1906
|
+
(obj) => obj.type === CodeObjectType.CLASS && obj.functions.length
|
|
1907
|
+
);
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
get allEvents() {
|
|
1911
|
+
return [this, ...this.descendants()].map((obj) => obj.events).flat();
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
descendants() {
|
|
1915
|
+
const queue = [...this.children];
|
|
1916
|
+
const children = [];
|
|
1917
|
+
|
|
1918
|
+
while (queue.length) {
|
|
1919
|
+
const child = queue.pop();
|
|
1920
|
+
children.push(child);
|
|
1921
|
+
queue.push(...child.children);
|
|
1922
|
+
}
|
|
1923
|
+
|
|
1924
|
+
return children;
|
|
1925
|
+
}
|
|
1926
|
+
|
|
1927
|
+
ancestors() {
|
|
1928
|
+
let currentObject = this.parent;
|
|
1929
|
+
const parents = [];
|
|
1930
|
+
|
|
1931
|
+
while (currentObject) {
|
|
1932
|
+
parents.push(currentObject);
|
|
1933
|
+
currentObject = currentObject.parent;
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
return parents;
|
|
1937
|
+
}
|
|
1938
|
+
|
|
1939
|
+
// Leafs retrieves the leaf objects for the current type that contain children of another type. It
|
|
1940
|
+
// is useful for retrieving children without worrying about types or deeply nested objects.
|
|
1941
|
+
//
|
|
1942
|
+
// For example, the leafs of the package "com" may be:
|
|
1943
|
+
// - com.myorg.myapp
|
|
1944
|
+
// - com.myorg.myapp.api
|
|
1945
|
+
//
|
|
1946
|
+
// Whereas its children would only contain "myorg", and its descendants would include functions
|
|
1947
|
+
// and classes from any other nested package.
|
|
1948
|
+
leafs() {
|
|
1949
|
+
const { type } = this;
|
|
1950
|
+
const queue = [this];
|
|
1951
|
+
const leafArray = [];
|
|
1952
|
+
|
|
1953
|
+
while (queue.length) {
|
|
1954
|
+
const obj = queue.pop();
|
|
1955
|
+
const childrenOfType = obj.children.filter(
|
|
1956
|
+
(child) => child.type === type
|
|
1957
|
+
);
|
|
1958
|
+
|
|
1959
|
+
// If this object has children of another type, consider it a leaf.
|
|
1960
|
+
// For example, a package containing a class.
|
|
1961
|
+
if (childrenOfType.length) {
|
|
1962
|
+
queue.push(...childrenOfType);
|
|
1963
|
+
}
|
|
1964
|
+
|
|
1965
|
+
// If, however, this object has a variety of child types, it's both a leaf and a parent
|
|
1966
|
+
if (
|
|
1967
|
+
(!obj.children.length && obj.type === type) ||
|
|
1968
|
+
childrenOfType.length !== obj.children.length
|
|
1969
|
+
) {
|
|
1970
|
+
leafArray.push(obj);
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
return leafArray;
|
|
1975
|
+
}
|
|
1976
|
+
|
|
1977
|
+
// Returns leafs of all children. Similar to the `classes` accessor, but returns children of any
|
|
1978
|
+
// type.
|
|
1979
|
+
childLeafs() {
|
|
1980
|
+
return this.children.map((child) => child.leafs()).flat();
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
visit(fn, stack = []) {
|
|
1984
|
+
stack.push(this);
|
|
1985
|
+
fn(this, stack);
|
|
1986
|
+
this.children.forEach((child) => child.visit(fn, stack));
|
|
1987
|
+
stack.pop();
|
|
1988
|
+
}
|
|
1989
|
+
|
|
1990
|
+
buildId(tokens = []) {
|
|
1991
|
+
if (this.parent) {
|
|
1992
|
+
this.parent.buildId(tokens);
|
|
1993
|
+
|
|
1994
|
+
let separator;
|
|
1995
|
+
switch (this.parent.type) {
|
|
1996
|
+
case CodeObjectType.PACKAGE:
|
|
1997
|
+
separator = '/';
|
|
1998
|
+
break;
|
|
1999
|
+
case CodeObjectType.CLASS:
|
|
2000
|
+
separator = '::';
|
|
2001
|
+
break;
|
|
2002
|
+
default:
|
|
2003
|
+
separator = '->';
|
|
2004
|
+
}
|
|
2005
|
+
tokens.push(separator);
|
|
2006
|
+
}
|
|
2007
|
+
tokens.push(this.name);
|
|
2008
|
+
return tokens;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
classLocations(paths = new Set()) {
|
|
2012
|
+
this.children.forEach((child) => child.classLocations(paths));
|
|
2013
|
+
|
|
2014
|
+
if (this.type === CodeObjectType.FUNCTION) {
|
|
2015
|
+
const tokens = this.data.location.split(':', 2);
|
|
2016
|
+
paths.add(tokens[0]);
|
|
2017
|
+
}
|
|
2018
|
+
return paths;
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
toJSON() {
|
|
2022
|
+
const obj = {
|
|
2023
|
+
name: this.data.name,
|
|
2024
|
+
type: this.data.type,
|
|
2025
|
+
};
|
|
2026
|
+
|
|
2027
|
+
if (this.data.type === CodeObjectType.FUNCTION) {
|
|
2028
|
+
obj.static = this.data.static;
|
|
2029
|
+
obj.location = this.data.location;
|
|
2030
|
+
}
|
|
2031
|
+
if (this.data.type === CodeObjectType.QUERY) {
|
|
2032
|
+
obj.database_type = this.data.database_type;
|
|
2033
|
+
}
|
|
2034
|
+
|
|
2035
|
+
if (this.children.length > 0) {
|
|
2036
|
+
obj.children = this.children;
|
|
2037
|
+
}
|
|
2038
|
+
|
|
2039
|
+
return obj;
|
|
2040
|
+
}
|
|
2041
|
+
|
|
2042
|
+
static constructDataChainFromEvent(event) {
|
|
2043
|
+
let elements;
|
|
2044
|
+
if (event.httpServerRequest) {
|
|
2045
|
+
elements = [
|
|
2046
|
+
{
|
|
2047
|
+
type: CodeObjectType.HTTP,
|
|
2048
|
+
name: 'HTTP server requests',
|
|
2049
|
+
},
|
|
2050
|
+
{
|
|
2051
|
+
type: CodeObjectType.ROUTE,
|
|
2052
|
+
name: event.route,
|
|
2053
|
+
},
|
|
2054
|
+
];
|
|
2055
|
+
} else if (event.httpClientRequest) {
|
|
2056
|
+
let serviceName;
|
|
2057
|
+
|
|
2058
|
+
try {
|
|
2059
|
+
const url = new URL(event.httpClientRequest.url);
|
|
2060
|
+
serviceName = url.host;
|
|
2061
|
+
} catch {
|
|
2062
|
+
serviceName = 'External service';
|
|
2063
|
+
}
|
|
2064
|
+
|
|
2065
|
+
elements = [
|
|
2066
|
+
{
|
|
2067
|
+
type: CodeObjectType.EXTERNAL_SERVICE,
|
|
2068
|
+
name: serviceName,
|
|
2069
|
+
},
|
|
2070
|
+
];
|
|
2071
|
+
} else if (event.sqlQuery) {
|
|
2072
|
+
elements = [
|
|
2073
|
+
{
|
|
2074
|
+
type: CodeObjectType.DATABASE,
|
|
2075
|
+
name: 'Database',
|
|
2076
|
+
},
|
|
2077
|
+
{
|
|
2078
|
+
type: CodeObjectType.QUERY,
|
|
2079
|
+
name: event.sqlQuery,
|
|
2080
|
+
database_type: event.sql.database_type,
|
|
2081
|
+
},
|
|
2082
|
+
];
|
|
2083
|
+
} else {
|
|
2084
|
+
elements = [
|
|
2085
|
+
{
|
|
2086
|
+
type: CodeObjectType.CLASS,
|
|
2087
|
+
name: event.definedClass,
|
|
2088
|
+
},
|
|
2089
|
+
{
|
|
2090
|
+
type: CodeObjectType.FUNCTION,
|
|
2091
|
+
name: event.methodId,
|
|
2092
|
+
static: event.isStatic,
|
|
2093
|
+
location: '',
|
|
2094
|
+
},
|
|
2095
|
+
];
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
// Flag this object as having been created dynamically
|
|
2099
|
+
const queue = [...elements];
|
|
2100
|
+
while (queue.length) {
|
|
2101
|
+
const obj = queue.pop();
|
|
2102
|
+
obj.dynamic = true;
|
|
2103
|
+
if (obj.children) {
|
|
2104
|
+
obj.children.forEach((child) => queue.push(child));
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
|
|
2108
|
+
return elements;
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
get inboundConnections() {
|
|
2112
|
+
return this.allEvents
|
|
2113
|
+
.filter((e) => e.parent)
|
|
2114
|
+
.map((e) => e.parent.codeObject);
|
|
2115
|
+
}
|
|
2116
|
+
|
|
2117
|
+
get outboundConnections() {
|
|
2118
|
+
return this.allEvents
|
|
2119
|
+
.map((e) => e.children)
|
|
2120
|
+
.flat()
|
|
2121
|
+
.map((e) => e.codeObject);
|
|
2122
|
+
}
|
|
2123
|
+
|
|
2124
|
+
get sqlQueries() {
|
|
2125
|
+
return this.allEvents
|
|
2126
|
+
.map((e) => e.children)
|
|
2127
|
+
.flat()
|
|
2128
|
+
.filter((e) => e.sql)
|
|
2129
|
+
.map((e) => e.codeObject);
|
|
2130
|
+
}
|
|
2131
|
+
|
|
2132
|
+
get prettyName() {
|
|
2133
|
+
switch (this.type) {
|
|
2134
|
+
case CodeObjectType.FUNCTION:
|
|
2135
|
+
return `${this.classOf}${this.static ? '.' : '#'}${this.name}`;
|
|
2136
|
+
case CodeObjectType.CLASS:
|
|
2137
|
+
return this.classOf;
|
|
2138
|
+
case CodeObjectType.PACKAGE:
|
|
2139
|
+
return this.packageOf;
|
|
2140
|
+
case CodeObjectType.QUERY:
|
|
2141
|
+
return getSqlLabelFromString(this.name);
|
|
2142
|
+
default:
|
|
2143
|
+
return this.name;
|
|
2144
|
+
}
|
|
2145
|
+
}
|
|
2146
|
+
|
|
2147
|
+
get fqid() {
|
|
2148
|
+
return `${this.type}:${this.id}`;
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
function indexCodeObject(co, codeObjects, codeObjectsById) {
|
|
2153
|
+
codeObjects.push(co);
|
|
2154
|
+
codeObjectsById[co.id] = co;
|
|
2155
|
+
}
|
|
2156
|
+
|
|
2157
|
+
class ClassMap {
|
|
2158
|
+
constructor(classMap) {
|
|
2159
|
+
this.codeObjectsByLocation = {};
|
|
2160
|
+
this.codeObjects = [];
|
|
2161
|
+
this.codeObjectsById = {};
|
|
2162
|
+
|
|
2163
|
+
const buildCodeObject = (data, parent = null) => {
|
|
2164
|
+
const co = new CodeObject(data, parent);
|
|
2165
|
+
indexCodeObject(co, this.codeObjects, this.codeObjectsById);
|
|
2166
|
+
|
|
2167
|
+
(data.children || []).forEach((child) => {
|
|
2168
|
+
buildCodeObject(child, co);
|
|
2169
|
+
});
|
|
2170
|
+
|
|
2171
|
+
if (co.type !== 'package') {
|
|
2172
|
+
co.locations.forEach((location) => {
|
|
2173
|
+
let codeObjects = this.codeObjectsByLocation[location];
|
|
2174
|
+
if (!codeObjects) {
|
|
2175
|
+
codeObjects = [];
|
|
2176
|
+
this.codeObjectsByLocation[location] = codeObjects;
|
|
2177
|
+
}
|
|
2178
|
+
codeObjects.push(co);
|
|
2179
|
+
});
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
return co;
|
|
2183
|
+
};
|
|
2184
|
+
|
|
2185
|
+
this.roots = classMap.map((root) => buildCodeObject(root));
|
|
2186
|
+
}
|
|
2187
|
+
|
|
2188
|
+
visit(fn) {
|
|
2189
|
+
this.roots.forEach((co) => co.visit(fn));
|
|
2190
|
+
}
|
|
2191
|
+
|
|
2192
|
+
search(query) {
|
|
2193
|
+
const queryLower = query.toLowerCase();
|
|
2194
|
+
return this.codeObjects.filter(
|
|
2195
|
+
(co) => co.id.toLowerCase().indexOf(queryLower) !== -1
|
|
2196
|
+
);
|
|
2197
|
+
}
|
|
2198
|
+
|
|
2199
|
+
codeObjectFromId(id) {
|
|
2200
|
+
return this.codeObjectsById[id];
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
codeObjectsAtLocation(location) {
|
|
2204
|
+
return this.codeObjectsByLocation[location] || [];
|
|
2205
|
+
}
|
|
2206
|
+
|
|
2207
|
+
codeObjectFromEvent(event) {
|
|
2208
|
+
let codeObject;
|
|
2209
|
+
// These types of events should not be reporting path and lineno, but sometimes
|
|
2210
|
+
// they do.
|
|
2211
|
+
if (!(event.httpServerRequest || event.httpClientRequest || event.sql)) {
|
|
2212
|
+
const { path, lineno } = event;
|
|
2213
|
+
const location = [path, lineno].filter((e) => e).join(':');
|
|
2214
|
+
if (location !== '') {
|
|
2215
|
+
const codeObjects = this.codeObjectsAtLocation(location);
|
|
2216
|
+
codeObject = codeObjects.find((o) => o.name === event.methodId);
|
|
2217
|
+
if (codeObject) {
|
|
2218
|
+
return codeObject;
|
|
2219
|
+
}
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
|
|
2223
|
+
return null;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
// Returns the first root code object of a given type or null if it doesn't exist
|
|
2227
|
+
root(type) {
|
|
2228
|
+
return this.roots.find((obj) => obj.type === type);
|
|
2229
|
+
}
|
|
2230
|
+
|
|
2231
|
+
// Returns the root HTTP code object if it exists
|
|
2232
|
+
get httpObject() {
|
|
2233
|
+
return this.root(CodeObjectType.HTTP);
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
// Returns the root SQL code object if it exists
|
|
2237
|
+
get sqlObject() {
|
|
2238
|
+
return this.root(CodeObjectType.DATABASE);
|
|
2239
|
+
}
|
|
2240
|
+
|
|
2241
|
+
// Binds an event array to code objects and vice versa. This allows use of
|
|
2242
|
+
// direct accessors: `Event.codeObject` and `CodeObject.events`. Additionally,
|
|
2243
|
+
// it guarantees non-null accessors, meaning it will construct a code object
|
|
2244
|
+
// for an event if it previously did not exist.
|
|
2245
|
+
bindEvents(events) {
|
|
2246
|
+
if (!events || !Array.isArray(events) || !events.length) {
|
|
2247
|
+
return;
|
|
2248
|
+
}
|
|
2249
|
+
|
|
2250
|
+
const validCodeObjects = new Set();
|
|
2251
|
+
events
|
|
2252
|
+
.filter((e) => e.isCall())
|
|
2253
|
+
.forEach((e) => {
|
|
2254
|
+
let codeObject = this.codeObjectFromEvent(e);
|
|
2255
|
+
if (!codeObject) {
|
|
2256
|
+
const findOrCreateCodeObject = (data, codeObjectArray, parent) => {
|
|
2257
|
+
// TODO: This ignores static/non-static function collisions and function overloads, though this method
|
|
2258
|
+
// is never currently called in a context where those edge cases exist.
|
|
2259
|
+
let newCodeObject = codeObjectArray.find(
|
|
2260
|
+
(obj) => obj.type === data.type && obj.name === data.name
|
|
2261
|
+
);
|
|
2262
|
+
|
|
2263
|
+
if (!newCodeObject) {
|
|
2264
|
+
newCodeObject = new CodeObject(data, parent);
|
|
2265
|
+
if (!parent) {
|
|
2266
|
+
this.roots.push(newCodeObject);
|
|
2267
|
+
}
|
|
2268
|
+
indexCodeObject(
|
|
2269
|
+
newCodeObject,
|
|
2270
|
+
this.codeObjects,
|
|
2271
|
+
this.codeObjectsById
|
|
2272
|
+
);
|
|
2273
|
+
}
|
|
2274
|
+
|
|
2275
|
+
return newCodeObject;
|
|
2276
|
+
};
|
|
2277
|
+
|
|
2278
|
+
const dataElements = CodeObject.constructDataChainFromEvent(e);
|
|
2279
|
+
let parent = null;
|
|
2280
|
+
dataElements.forEach((dataElement) => {
|
|
2281
|
+
parent = findOrCreateCodeObject(
|
|
2282
|
+
dataElement,
|
|
2283
|
+
parent ? parent.children : this.roots,
|
|
2284
|
+
parent
|
|
2285
|
+
);
|
|
2286
|
+
});
|
|
2287
|
+
codeObject = parent;
|
|
2288
|
+
}
|
|
2289
|
+
|
|
2290
|
+
e.codeObject = codeObject;
|
|
2291
|
+
codeObject.events.push(e);
|
|
2292
|
+
|
|
2293
|
+
const ancestors = codeObject.ancestors();
|
|
2294
|
+
validCodeObjects.add(codeObject);
|
|
2295
|
+
ancestors.forEach((obj) => validCodeObjects.add(obj));
|
|
2296
|
+
});
|
|
2297
|
+
|
|
2298
|
+
this.codeObjects = this.codeObjects.filter((obj) =>
|
|
2299
|
+
validCodeObjects.has(obj)
|
|
2300
|
+
);
|
|
2301
|
+
|
|
2302
|
+
this.roots = this.roots.filter((obj) => validCodeObjects.has(obj));
|
|
2303
|
+
|
|
2304
|
+
Object.keys(this.codeObjectsByLocation).forEach((obj) => {
|
|
2305
|
+
if (!validCodeObjects.has(obj)) {
|
|
2306
|
+
delete this.codeObjectsByLocation[obj];
|
|
2307
|
+
}
|
|
2308
|
+
});
|
|
2309
|
+
|
|
2310
|
+
Object.entries(this.codeObjectsById).forEach(([id, obj]) => {
|
|
2311
|
+
if (!validCodeObjects.has(obj)) {
|
|
2312
|
+
delete this.codeObjectsById[id];
|
|
2313
|
+
}
|
|
2314
|
+
});
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
toJSON() {
|
|
2318
|
+
// Don't write out code objects that were created during runtime
|
|
2319
|
+
return this.roots.filter((obj) => !obj.dynamic);
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2322
|
+
|
|
2323
|
+
// Deprecated. Prefer `Event` instead.
|
|
2324
|
+
class CallNode {
|
|
2325
|
+
constructor(input = {}, output = {}, caller = null, labels = []) {
|
|
2326
|
+
this.input = input;
|
|
2327
|
+
this.output = output;
|
|
2328
|
+
this.children = [];
|
|
2329
|
+
this.labels = labels;
|
|
2330
|
+
|
|
2331
|
+
// Cyclic references shall not be enumerable
|
|
2332
|
+
addHiddenProperty(this, 'caller', { value: caller });
|
|
2333
|
+
}
|
|
2334
|
+
|
|
2335
|
+
get caller() {
|
|
2336
|
+
return this.$hidden.caller;
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
set caller(value) {
|
|
2340
|
+
this.$hidden.$hiddencaller = value;
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
clone() {
|
|
2344
|
+
const input = { ...this.input };
|
|
2345
|
+
const output = { ...this.output };
|
|
2346
|
+
const labels = [...this.labels];
|
|
2347
|
+
const newNode = new CallNode(input, output, null, labels);
|
|
2348
|
+
|
|
2349
|
+
if (this.displayName) {
|
|
2350
|
+
newNode.displayName = this.displayName;
|
|
2351
|
+
}
|
|
2352
|
+
|
|
2353
|
+
this.children.forEach((child) => {
|
|
2354
|
+
const newChild = child.clone();
|
|
2355
|
+
newNode.addChild(newChild);
|
|
2356
|
+
newChild.caller = newNode;
|
|
2357
|
+
});
|
|
2358
|
+
|
|
2359
|
+
return newNode;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
addChild(node) {
|
|
2363
|
+
this.children.push(node);
|
|
2364
|
+
}
|
|
2365
|
+
|
|
2366
|
+
// Replace a given child with a different set of children.
|
|
2367
|
+
replaceChild(child, children) {
|
|
2368
|
+
const idx = this.children.indexOf(child);
|
|
2369
|
+
if (idx === -1) {
|
|
2370
|
+
throw new Error(`${child} not found in call tree`);
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
this.children.splice(idx, 1, ...children);
|
|
2374
|
+
/* eslint-disable no-param-reassign */
|
|
2375
|
+
children.forEach((c) => {
|
|
2376
|
+
c.caller = this;
|
|
2377
|
+
});
|
|
2378
|
+
child.caller = null;
|
|
2379
|
+
/* eslint-enable no-param-reassign */
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
removeChild(child) {
|
|
2383
|
+
const childIndex = this.children.indexOf(child);
|
|
2384
|
+
if (childIndex < 0) {
|
|
2385
|
+
throw new Error(`${child} found orphaned by ${this} !`);
|
|
2386
|
+
}
|
|
2387
|
+
this.children.splice(childIndex, 1);
|
|
2388
|
+
}
|
|
2389
|
+
|
|
2390
|
+
postOrderForEach(fn, stack = []) {
|
|
2391
|
+
stack.push(this);
|
|
2392
|
+
const children = [...this.children];
|
|
2393
|
+
children.forEach((child) => child.postOrderForEach(fn, stack));
|
|
2394
|
+
fn(this, stack);
|
|
2395
|
+
stack.pop(this);
|
|
2396
|
+
}
|
|
2397
|
+
|
|
2398
|
+
preOrderForEach(fn, stack = []) {
|
|
2399
|
+
stack.push(this);
|
|
2400
|
+
fn(this, stack);
|
|
2401
|
+
const children = [...this.children];
|
|
2402
|
+
children.forEach((child) => child.preOrderForEach(fn, stack));
|
|
2403
|
+
stack.pop(this);
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
forEach(fn) {
|
|
2407
|
+
this.postOrderForEach(fn);
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
// filter returns a tree in which all nodes match a condition. If a node fails the
|
|
2411
|
+
// condition, its children are adopted by it's parent.
|
|
2412
|
+
filter(conditionFn) {
|
|
2413
|
+
const root = this.clone();
|
|
2414
|
+
root.forEach((node, stack) => {
|
|
2415
|
+
if (node.isRoot()) {
|
|
2416
|
+
return;
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
if (!conditionFn(node, stack)) {
|
|
2420
|
+
const parent = node.caller;
|
|
2421
|
+
parent.replaceChild(node, node.children);
|
|
2422
|
+
}
|
|
2423
|
+
});
|
|
2424
|
+
|
|
2425
|
+
return root;
|
|
2426
|
+
}
|
|
2427
|
+
|
|
2428
|
+
// include returns a tree in which all leaf nodes match a condition.
|
|
2429
|
+
// If a node passes the condition, the node and all of its parents are retained
|
|
2430
|
+
// in the tree. If it fails, the node and its children are removed from the tree.
|
|
2431
|
+
// Note that if a node passes the condition, the condition will not be evaluated
|
|
2432
|
+
// for that node's parent nodes, since they are already marked as retained.
|
|
2433
|
+
include(conditionFn) {
|
|
2434
|
+
/* eslint-disable no-param-reassign */
|
|
2435
|
+
const root = this.clone();
|
|
2436
|
+
root.postOrderForEach((node, stack) => {
|
|
2437
|
+
if (node.isRoot()) {
|
|
2438
|
+
return;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
if (node.marked_include && node.caller) {
|
|
2442
|
+
node.caller.marked_include = true;
|
|
2443
|
+
return;
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
node.marked_include = conditionFn(node, stack);
|
|
2447
|
+
if (node.marked_include) {
|
|
2448
|
+
if (node.caller) {
|
|
2449
|
+
node.caller.marked_include = true;
|
|
2450
|
+
}
|
|
2451
|
+
return;
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
if (node.caller) {
|
|
2455
|
+
node.caller.removeChild(node);
|
|
2456
|
+
}
|
|
2457
|
+
});
|
|
2458
|
+
|
|
2459
|
+
root.postOrderForEach((node) => {
|
|
2460
|
+
delete node.marked_include;
|
|
2461
|
+
});
|
|
2462
|
+
|
|
2463
|
+
return root;
|
|
2464
|
+
/* eslint-enable no-param-reassign */
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
// exclude returns a tree in which all nodes that match a condition are removed, along
|
|
2468
|
+
// with their child nodes.
|
|
2469
|
+
exclude(conditionFn) {
|
|
2470
|
+
const root = this.clone();
|
|
2471
|
+
root.forEach((node, stack) => {
|
|
2472
|
+
if (node.isRoot()) {
|
|
2473
|
+
return;
|
|
2474
|
+
}
|
|
2475
|
+
|
|
2476
|
+
if (conditionFn(node, stack)) {
|
|
2477
|
+
const parent = node.caller;
|
|
2478
|
+
parent.removeChild(node);
|
|
2479
|
+
}
|
|
2480
|
+
});
|
|
2481
|
+
|
|
2482
|
+
return root;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
// toArray returns this tree as a one dimensional array
|
|
2486
|
+
toArray() {
|
|
2487
|
+
const childEvents = this.children.map((child) => child.toArray()).flat();
|
|
2488
|
+
|
|
2489
|
+
if (this.isRoot()) {
|
|
2490
|
+
return childEvents;
|
|
2491
|
+
}
|
|
2492
|
+
|
|
2493
|
+
return [this, ...childEvents];
|
|
2494
|
+
}
|
|
2495
|
+
|
|
2496
|
+
// find calls find recursively on all children
|
|
2497
|
+
// iterates in pre-order
|
|
2498
|
+
find(fn) {
|
|
2499
|
+
if (fn(this)) {
|
|
2500
|
+
return this;
|
|
2501
|
+
}
|
|
2502
|
+
|
|
2503
|
+
for (let i = 0; i < this.children.length; i += 1) {
|
|
2504
|
+
const match = this.children[i].find(fn);
|
|
2505
|
+
if (match) {
|
|
2506
|
+
return match;
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2509
|
+
|
|
2510
|
+
return null;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
// depth returns the depth of this node
|
|
2514
|
+
depth() {
|
|
2515
|
+
return this.ancestors().length;
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
// ancestors returns an array of this nodes ancestors
|
|
2519
|
+
ancestors() {
|
|
2520
|
+
const nodes = [];
|
|
2521
|
+
|
|
2522
|
+
let parent = this.caller;
|
|
2523
|
+
while (parent) {
|
|
2524
|
+
nodes.push(parent);
|
|
2525
|
+
parent = parent.caller;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
return nodes;
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
// returns whether or not a node has a particular node in its ancestry
|
|
2532
|
+
hasAncestor(ancestor) {
|
|
2533
|
+
let node = this;
|
|
2534
|
+
while (node) {
|
|
2535
|
+
if (node === ancestor) {
|
|
2536
|
+
return true;
|
|
2537
|
+
}
|
|
2538
|
+
node = node.caller;
|
|
2539
|
+
}
|
|
2540
|
+
return false;
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
descendants() {
|
|
2544
|
+
return [this, ...this.children.map((x) => x.descendants()).flat()];
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
next() {
|
|
2548
|
+
if (this.children.length > 0) {
|
|
2549
|
+
return this.children[0];
|
|
2550
|
+
}
|
|
2551
|
+
|
|
2552
|
+
let child = this;
|
|
2553
|
+
let parent = this.caller;
|
|
2554
|
+
const fnChildIndex = (n) => n === child;
|
|
2555
|
+
while (parent) {
|
|
2556
|
+
const myIndex = parent.children.findIndex(fnChildIndex);
|
|
2557
|
+
if (myIndex < 0) {
|
|
2558
|
+
throw new Error(`${this} found orphaned by ${parent}!`);
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
if (myIndex < parent.children.length - 1) {
|
|
2562
|
+
return parent.children[myIndex + 1];
|
|
2563
|
+
}
|
|
2564
|
+
|
|
2565
|
+
child = parent;
|
|
2566
|
+
parent = parent.caller;
|
|
2567
|
+
}
|
|
2568
|
+
|
|
2569
|
+
return null;
|
|
2570
|
+
}
|
|
2571
|
+
|
|
2572
|
+
previous() {
|
|
2573
|
+
const parent = this.caller;
|
|
2574
|
+
if (!parent) {
|
|
2575
|
+
return null;
|
|
2576
|
+
}
|
|
2577
|
+
|
|
2578
|
+
if (parent.children.length === 1) {
|
|
2579
|
+
return parent;
|
|
2580
|
+
}
|
|
2581
|
+
|
|
2582
|
+
const myIndex = parent.children.findIndex((n) => n === this);
|
|
2583
|
+
if (myIndex < 0) {
|
|
2584
|
+
throw new Error(`${this.input.id} found orphaned by ${parent.input.id}!`);
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
if (myIndex > 0) {
|
|
2588
|
+
// this branch will yield our previous node
|
|
2589
|
+
let candidate = parent.children[myIndex - 1];
|
|
2590
|
+
|
|
2591
|
+
// iterate until we find a leaf node
|
|
2592
|
+
while (candidate.children.length > 0) {
|
|
2593
|
+
candidate = candidate.children[candidate.children.length - 1];
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
return candidate;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
return parent;
|
|
2600
|
+
}
|
|
2601
|
+
|
|
2602
|
+
// return the node to the left, at given max depth
|
|
2603
|
+
left(depth) {
|
|
2604
|
+
const target = depth || this.depth();
|
|
2605
|
+
|
|
2606
|
+
// find the target or the nearest descendant
|
|
2607
|
+
let current = this;
|
|
2608
|
+
for (;;) {
|
|
2609
|
+
const parent = current.caller;
|
|
2610
|
+
if (!parent) return this;
|
|
2611
|
+
|
|
2612
|
+
const siblings = parent.children;
|
|
2613
|
+
const i = siblings.indexOf(current);
|
|
2614
|
+
if (i !== 0) {
|
|
2615
|
+
current = parent.children[i - 1];
|
|
2616
|
+
break;
|
|
2617
|
+
} else {
|
|
2618
|
+
current = parent;
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
|
|
2622
|
+
// find rightmost child closest to the right depth
|
|
2623
|
+
while (current.depth() !== target) {
|
|
2624
|
+
const { children } = current;
|
|
2625
|
+
if (children.length === 0) break;
|
|
2626
|
+
current = children[children.length - 1];
|
|
2627
|
+
}
|
|
2628
|
+
|
|
2629
|
+
return current;
|
|
2630
|
+
}
|
|
2631
|
+
|
|
2632
|
+
// return the node to the right, at given max depth
|
|
2633
|
+
right(depth) {
|
|
2634
|
+
const target = depth || this.depth();
|
|
2635
|
+
|
|
2636
|
+
// find the target or the nearest descendant
|
|
2637
|
+
let current = this;
|
|
2638
|
+
for (;;) {
|
|
2639
|
+
const parent = current.caller;
|
|
2640
|
+
if (!parent) return this;
|
|
2641
|
+
|
|
2642
|
+
const siblings = parent.children;
|
|
2643
|
+
const i = siblings.indexOf(current);
|
|
2644
|
+
if (i !== siblings.length - 1) {
|
|
2645
|
+
current = parent.children[i + 1];
|
|
2646
|
+
break;
|
|
2647
|
+
} else {
|
|
2648
|
+
current = parent;
|
|
2649
|
+
}
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
// find leftmost child closest to the right depth
|
|
2653
|
+
while (current.depth() !== target) {
|
|
2654
|
+
const { children } = current;
|
|
2655
|
+
if (children.length === 0) break;
|
|
2656
|
+
[current] = children;
|
|
2657
|
+
}
|
|
2658
|
+
|
|
2659
|
+
return current;
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
isRoot() {
|
|
2663
|
+
return this.caller === null;
|
|
2664
|
+
}
|
|
2665
|
+
|
|
2666
|
+
count() {
|
|
2667
|
+
let numNodes = 0;
|
|
2668
|
+
this.forEach(() => {
|
|
2669
|
+
numNodes += 1;
|
|
2670
|
+
});
|
|
2671
|
+
return numNodes;
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
get id() {
|
|
2675
|
+
if (this.input && this.input.id) {
|
|
2676
|
+
return this.input.id;
|
|
2677
|
+
}
|
|
2678
|
+
return null;
|
|
2679
|
+
}
|
|
2680
|
+
}
|
|
2681
|
+
|
|
2682
|
+
function getListenerArray(eventSource, eventType) {
|
|
2683
|
+
/* eslint-disable no-param-reassign */
|
|
2684
|
+
let listeners = eventSource.listeners[eventType];
|
|
2685
|
+
if (!listeners) {
|
|
2686
|
+
listeners = [];
|
|
2687
|
+
eventSource.listeners[eventType] = listeners;
|
|
2688
|
+
}
|
|
2689
|
+
return listeners;
|
|
2690
|
+
/* eslint-enable no-param-reassign */
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
class EventSource {
|
|
2694
|
+
constructor() {
|
|
2695
|
+
this.listeners = {};
|
|
2696
|
+
this.anyListeners = [];
|
|
2697
|
+
}
|
|
2698
|
+
|
|
2699
|
+
once(eventType, fn) {
|
|
2700
|
+
const handlers = getListenerArray(this, eventType);
|
|
2701
|
+
handlers.push({ fn, once: true });
|
|
2702
|
+
return this;
|
|
2703
|
+
}
|
|
2704
|
+
|
|
2705
|
+
on(eventType, fn) {
|
|
2706
|
+
const handlers = getListenerArray(this, eventType);
|
|
2707
|
+
handlers.push({ fn });
|
|
2708
|
+
return this;
|
|
2709
|
+
}
|
|
2710
|
+
|
|
2711
|
+
off(eventType, fn) {
|
|
2712
|
+
const handlers = this.listeners[eventType];
|
|
2713
|
+
|
|
2714
|
+
if (handlers) {
|
|
2715
|
+
const updatedHandlers = handlers.filter((h) => h.fn && h.fn !== fn);
|
|
2716
|
+
if (updatedHandlers.length === 0) {
|
|
2717
|
+
delete this.listeners[eventType];
|
|
2718
|
+
} else if (updatedHandlers.length !== handlers.length) {
|
|
2719
|
+
this.listeners[eventType] = updatedHandlers;
|
|
2720
|
+
}
|
|
2721
|
+
}
|
|
2722
|
+
|
|
2723
|
+
return this;
|
|
2724
|
+
}
|
|
2725
|
+
|
|
2726
|
+
emit(eventType, data = undefined) {
|
|
2727
|
+
const handlers = this.listeners[eventType];
|
|
2728
|
+
|
|
2729
|
+
if (handlers) {
|
|
2730
|
+
let includesOnce = false;
|
|
2731
|
+
handlers.forEach((handler) => {
|
|
2732
|
+
if (handler.once) {
|
|
2733
|
+
includesOnce = true;
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
try {
|
|
2737
|
+
handler.fn(data);
|
|
2738
|
+
} catch (e) {
|
|
2739
|
+
console.error(`error occurred while executing event ${eventType}`);
|
|
2740
|
+
console.error(e);
|
|
2741
|
+
}
|
|
2742
|
+
});
|
|
2743
|
+
|
|
2744
|
+
if (includesOnce) {
|
|
2745
|
+
// Only reassign this value if we've encountered a handler that's run once
|
|
2746
|
+
this.listeners[eventType] = this.listeners[eventType].filter(
|
|
2747
|
+
(h) => !h.once
|
|
2748
|
+
);
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
|
|
2752
|
+
this.anyListeners.forEach((eventSource) =>
|
|
2753
|
+
eventSource.emit(eventType, data)
|
|
2754
|
+
);
|
|
2755
|
+
|
|
2756
|
+
return this;
|
|
2757
|
+
}
|
|
2758
|
+
|
|
2759
|
+
// Pipe events from EventSource A to EventSource B. If `eventTypes` are
|
|
2760
|
+
// provided, bind only those types. Otherwise, pipe any event.
|
|
2761
|
+
pipe(eventSource, ...eventTypes) {
|
|
2762
|
+
if (eventTypes.length) {
|
|
2763
|
+
eventTypes.forEach((type) =>
|
|
2764
|
+
eventSource.on(type, (data) => this.emit(data))
|
|
2765
|
+
);
|
|
2766
|
+
return this;
|
|
2767
|
+
}
|
|
2768
|
+
|
|
2769
|
+
eventSource.any(this);
|
|
2770
|
+
return this;
|
|
2771
|
+
}
|
|
2772
|
+
|
|
2773
|
+
// Bind `eventSource` to recieve any event sent from `this`.
|
|
2774
|
+
any(eventSource) {
|
|
2775
|
+
this.anyListeners.push(eventSource);
|
|
2776
|
+
return this;
|
|
2777
|
+
}
|
|
2778
|
+
}
|
|
2779
|
+
|
|
2780
|
+
class CallTree extends EventSource {
|
|
2781
|
+
constructor(events, functionLabels = () => []) {
|
|
2782
|
+
super();
|
|
2783
|
+
|
|
2784
|
+
this.dataStore = {
|
|
2785
|
+
rootEvent: this.rootNode,
|
|
2786
|
+
selectedEvent: this.rootNode,
|
|
2787
|
+
};
|
|
2788
|
+
|
|
2789
|
+
this.rootEvent = new CallNode();
|
|
2790
|
+
const stack = [this.rootEvent];
|
|
2791
|
+
events.forEach((e) => {
|
|
2792
|
+
if (e.event !== 'call') {
|
|
2793
|
+
if (stack.length > 1) {
|
|
2794
|
+
stack.pop();
|
|
2795
|
+
}
|
|
2796
|
+
return;
|
|
2797
|
+
}
|
|
2798
|
+
|
|
2799
|
+
const parent = stack[stack.length - 1];
|
|
2800
|
+
const callNode = new CallNode(
|
|
2801
|
+
e,
|
|
2802
|
+
e.returnEvent,
|
|
2803
|
+
parent,
|
|
2804
|
+
functionLabels(e)
|
|
2805
|
+
);
|
|
2806
|
+
parent.addChild(callNode);
|
|
2807
|
+
stack.push(callNode);
|
|
2808
|
+
});
|
|
2809
|
+
|
|
2810
|
+
return this;
|
|
2811
|
+
}
|
|
2812
|
+
|
|
2813
|
+
get rootEvent() {
|
|
2814
|
+
return this.dataStore.rootEvent;
|
|
2815
|
+
}
|
|
2816
|
+
|
|
2817
|
+
set rootEvent(event) {
|
|
2818
|
+
this.dataStore.rootEvent = event;
|
|
2819
|
+
this.emit('rootEvent', event);
|
|
2820
|
+
}
|
|
2821
|
+
|
|
2822
|
+
get selectedEvent() {
|
|
2823
|
+
return this.dataStore.selectedEvent;
|
|
2824
|
+
}
|
|
2825
|
+
|
|
2826
|
+
set selectedEvent(event) {
|
|
2827
|
+
this.dataStore.selectedEvent = event;
|
|
2828
|
+
this.emit('selectedEvent', event);
|
|
2829
|
+
}
|
|
2830
|
+
}
|
|
2831
|
+
|
|
2832
|
+
// merge contiguous changes into a single element (as an array)
|
|
2833
|
+
function groupChanges(eventArray) {
|
|
2834
|
+
const events = new Set(eventArray);
|
|
2835
|
+
const seen = new Set();
|
|
2836
|
+
const result = [];
|
|
2837
|
+
|
|
2838
|
+
eventArray.forEach((e) => {
|
|
2839
|
+
if (seen.has(e)) {
|
|
2840
|
+
return;
|
|
2841
|
+
}
|
|
2842
|
+
|
|
2843
|
+
seen.add(e);
|
|
2844
|
+
|
|
2845
|
+
const group = [e];
|
|
2846
|
+
let currentEvent = e;
|
|
2847
|
+
for (;;) {
|
|
2848
|
+
const { nextSibling } = currentEvent;
|
|
2849
|
+
if (nextSibling && events.has(nextSibling)) {
|
|
2850
|
+
group.push(nextSibling);
|
|
2851
|
+
seen.add(nextSibling);
|
|
2852
|
+
currentEvent = nextSibling;
|
|
2853
|
+
} else {
|
|
2854
|
+
break;
|
|
2855
|
+
}
|
|
2856
|
+
}
|
|
2857
|
+
|
|
2858
|
+
result.push(group);
|
|
2859
|
+
});
|
|
2860
|
+
|
|
2861
|
+
return result;
|
|
2862
|
+
}
|
|
2863
|
+
|
|
2864
|
+
class AppMap {
|
|
2865
|
+
constructor(data) {
|
|
2866
|
+
this.data = {
|
|
2867
|
+
events: [],
|
|
2868
|
+
classMap: [],
|
|
2869
|
+
...data,
|
|
2870
|
+
};
|
|
2871
|
+
|
|
2872
|
+
this.classMap = new ClassMap(this.data.classMap);
|
|
2873
|
+
this.callTree = new CallTree(this.events);
|
|
2874
|
+
this.classMap.bindEvents(this.events);
|
|
2875
|
+
this.labels = buildLabels(this.classMap, this.events);
|
|
2876
|
+
|
|
2877
|
+
// Establish event linked list references
|
|
2878
|
+
let previousEvent;
|
|
2879
|
+
this.events.forEach((e) => {
|
|
2880
|
+
if (previousEvent) {
|
|
2881
|
+
e.previous = previousEvent;
|
|
2882
|
+
previousEvent.next = e;
|
|
2883
|
+
}
|
|
2884
|
+
|
|
2885
|
+
previousEvent = e;
|
|
2886
|
+
});
|
|
2887
|
+
|
|
2888
|
+
// Keep these fields seperate for serialization
|
|
2889
|
+
delete this.data.classMap;
|
|
2890
|
+
}
|
|
2891
|
+
|
|
2892
|
+
get version() {
|
|
2893
|
+
return this.data.version;
|
|
2894
|
+
}
|
|
2895
|
+
|
|
2896
|
+
get metadata() {
|
|
2897
|
+
return this.data.metadata || {};
|
|
2898
|
+
}
|
|
2899
|
+
|
|
2900
|
+
get name() {
|
|
2901
|
+
return this.metadata.name;
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
get rootEvent() {
|
|
2905
|
+
return this.callTree.rootEvent;
|
|
2906
|
+
}
|
|
2907
|
+
|
|
2908
|
+
get events() {
|
|
2909
|
+
return this.data.events;
|
|
2910
|
+
}
|
|
2911
|
+
|
|
2912
|
+
shallowCopy() {
|
|
2913
|
+
const copy = new AppMap({});
|
|
2914
|
+
copy.data.events = this.data.events;
|
|
2915
|
+
copy.data.metadata = this.data.metadata;
|
|
2916
|
+
copy.classMap = this.classMap;
|
|
2917
|
+
copy.callTree = this.callTree;
|
|
2918
|
+
return copy;
|
|
2919
|
+
}
|
|
2920
|
+
|
|
2921
|
+
// Retrieve an array of root entry point events (currently, just HTTP server requests). If none
|
|
2922
|
+
// are found, return all the root nodes which have no caller.
|
|
2923
|
+
rootEvents() {
|
|
2924
|
+
return getRootEvents(this.events);
|
|
2925
|
+
}
|
|
2926
|
+
|
|
2927
|
+
// Iterate many AppMaps at once as an event tree. This method will follow the deepest branch
|
|
2928
|
+
// available, and yield the nodes at that position. Given that the tree structure may differ
|
|
2929
|
+
// across AppMaps, it's possible that some nodes will be null.
|
|
2930
|
+
static *multiTreeIterator(baseAppMap, workingAppMap) {
|
|
2931
|
+
let baseEvent;
|
|
2932
|
+
let workingEvent;
|
|
2933
|
+
const baseQueue = baseAppMap.rootEvents();
|
|
2934
|
+
const workingQueue = workingAppMap.rootEvents();
|
|
2935
|
+
|
|
2936
|
+
resolveDifferences(baseQueue, workingQueue);
|
|
2937
|
+
|
|
2938
|
+
for (;;) {
|
|
2939
|
+
baseEvent = baseQueue.shift();
|
|
2940
|
+
workingEvent = workingQueue.shift();
|
|
2941
|
+
|
|
2942
|
+
// If both are null, every path has been exhausted. We're done.
|
|
2943
|
+
if (!baseEvent && !workingEvent) {
|
|
2944
|
+
return;
|
|
2945
|
+
}
|
|
2946
|
+
|
|
2947
|
+
// Don't bother continuing to iterate through a branch that doesn't exist in the other tree.
|
|
2948
|
+
if (baseEvent && workingEvent) {
|
|
2949
|
+
const baseChildren = baseEvent ? [...baseEvent.children] : [];
|
|
2950
|
+
const workingChildren = workingEvent ? [...workingEvent.children] : [];
|
|
2951
|
+
|
|
2952
|
+
resolveDifferences(baseChildren, workingChildren);
|
|
2953
|
+
baseChildren.forEach((e) => baseQueue.push(e));
|
|
2954
|
+
workingChildren.forEach((e) => workingQueue.push(e));
|
|
2955
|
+
}
|
|
2956
|
+
|
|
2957
|
+
yield [baseEvent, workingEvent];
|
|
2958
|
+
}
|
|
2959
|
+
}
|
|
2960
|
+
|
|
2961
|
+
static getDiff(baseAppMap, workingAppMap) {
|
|
2962
|
+
const changeSummary = {
|
|
2963
|
+
changed: [],
|
|
2964
|
+
added: [],
|
|
2965
|
+
removed: [],
|
|
2966
|
+
};
|
|
2967
|
+
|
|
2968
|
+
const iter = AppMap.multiTreeIterator(baseAppMap, workingAppMap);
|
|
2969
|
+
let result = iter.next();
|
|
2970
|
+
while (!result.done) {
|
|
2971
|
+
const [nodeBase, nodeWorking] = result.value;
|
|
2972
|
+
|
|
2973
|
+
if (!nodeBase) {
|
|
2974
|
+
changeSummary.added.push(nodeWorking);
|
|
2975
|
+
} else if (!nodeWorking) {
|
|
2976
|
+
changeSummary.removed.push(nodeBase);
|
|
2977
|
+
} else if (nodeBase.hash !== nodeWorking.hash) {
|
|
2978
|
+
changeSummary.changed.push([nodeBase, nodeWorking]);
|
|
2979
|
+
}
|
|
2980
|
+
|
|
2981
|
+
result = iter.next();
|
|
2982
|
+
}
|
|
2983
|
+
|
|
2984
|
+
changeSummary.added = groupChanges(changeSummary.added);
|
|
2985
|
+
changeSummary.removed = groupChanges(changeSummary.removed);
|
|
2986
|
+
|
|
2987
|
+
return changeSummary;
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2990
|
+
toJSON() {
|
|
2991
|
+
return {
|
|
2992
|
+
...this.data,
|
|
2993
|
+
classMap: this.classMap,
|
|
2994
|
+
};
|
|
2995
|
+
}
|
|
2996
|
+
}
|
|
2997
|
+
|
|
2998
|
+
// This class supercedes `CallTree` and `CallNode`. Events are stored in a flat
|
|
2999
|
+
// array and can also be traversed like a tree via `parent` and `children`.
|
|
3000
|
+
class Event {
|
|
3001
|
+
constructor(obj) {
|
|
3002
|
+
let data = obj;
|
|
3003
|
+
|
|
3004
|
+
if (obj instanceof Event) {
|
|
3005
|
+
data = { ...obj };
|
|
3006
|
+
|
|
3007
|
+
if (obj.$hidden.parameters) {
|
|
3008
|
+
data.parameters = obj.$hidden.parameters.map((p) => ({ ...p }));
|
|
3009
|
+
}
|
|
3010
|
+
|
|
3011
|
+
if (Array.isArray(obj.$hidden.message)) {
|
|
3012
|
+
data.message = obj.$hidden.message.map((m) => ({ ...m }));
|
|
3013
|
+
}
|
|
3014
|
+
|
|
3015
|
+
if (obj.$hidden.labels) {
|
|
3016
|
+
data.labels = [...obj.$hidden.labels];
|
|
3017
|
+
}
|
|
3018
|
+
}
|
|
3019
|
+
|
|
3020
|
+
// Cyclic references shall not be enumerable
|
|
3021
|
+
if (data.event === 'call') {
|
|
3022
|
+
addHiddenProperty(this, 'parent');
|
|
3023
|
+
addHiddenProperty(this, 'children', { writable: false, value: [] });
|
|
3024
|
+
addHiddenProperty(this, 'dataReferences', { writable: false, value: [] });
|
|
3025
|
+
addHiddenProperty(this, 'codeObject');
|
|
3026
|
+
addHiddenProperty(this, 'parameters');
|
|
3027
|
+
addHiddenProperty(this, 'message');
|
|
3028
|
+
}
|
|
3029
|
+
|
|
3030
|
+
addHiddenProperty(this, 'linkedEvent');
|
|
3031
|
+
addHiddenProperty(this, 'labels');
|
|
3032
|
+
addHiddenProperty(this, 'next');
|
|
3033
|
+
addHiddenProperty(this, 'previous');
|
|
3034
|
+
addHiddenProperty(this, 'hash');
|
|
3035
|
+
addHiddenProperty(this, 'identityHash');
|
|
3036
|
+
addHiddenProperty(this, 'depth');
|
|
3037
|
+
|
|
3038
|
+
// Data must be written last, after our properties are configured.
|
|
3039
|
+
Object.assign(this, data);
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
get depth() {
|
|
3043
|
+
if (this.$hidden.depth === undefined) {
|
|
3044
|
+
let result = 0;
|
|
3045
|
+
let { parent } = this;
|
|
3046
|
+
while (parent) {
|
|
3047
|
+
result += 1;
|
|
3048
|
+
parent = parent.parent;
|
|
3049
|
+
}
|
|
3050
|
+
this.$hidden.depth = result;
|
|
3051
|
+
}
|
|
3052
|
+
return this.$hidden.depth;
|
|
3053
|
+
}
|
|
3054
|
+
|
|
3055
|
+
get methodId() {
|
|
3056
|
+
return this.method_id;
|
|
3057
|
+
}
|
|
3058
|
+
|
|
3059
|
+
get isFunction() {
|
|
3060
|
+
return this.definedClass && this.methodId;
|
|
3061
|
+
}
|
|
3062
|
+
|
|
3063
|
+
get isStatic() {
|
|
3064
|
+
return this.static;
|
|
3065
|
+
}
|
|
3066
|
+
|
|
3067
|
+
get sql() {
|
|
3068
|
+
return this.callEvent.sql_query;
|
|
3069
|
+
}
|
|
3070
|
+
|
|
3071
|
+
get returnValue() {
|
|
3072
|
+
return this.returnEvent.return_value;
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
get linkedEvent() {
|
|
3076
|
+
return this.$hidden.linkedEvent;
|
|
3077
|
+
}
|
|
3078
|
+
|
|
3079
|
+
get next() {
|
|
3080
|
+
return this.$hidden.next;
|
|
3081
|
+
}
|
|
3082
|
+
|
|
3083
|
+
get previous() {
|
|
3084
|
+
return this.$hidden.previous;
|
|
3085
|
+
}
|
|
3086
|
+
|
|
3087
|
+
get parent() {
|
|
3088
|
+
return this.$hidden.parent;
|
|
3089
|
+
}
|
|
3090
|
+
|
|
3091
|
+
get children() {
|
|
3092
|
+
return this.$hidden.children || [];
|
|
3093
|
+
}
|
|
3094
|
+
|
|
3095
|
+
get codeObject() {
|
|
3096
|
+
return this.callEvent.$hidden.codeObject;
|
|
3097
|
+
}
|
|
3098
|
+
|
|
3099
|
+
get parameters() {
|
|
3100
|
+
return this.callEvent.$hidden.parameters;
|
|
3101
|
+
}
|
|
3102
|
+
|
|
3103
|
+
get labels() {
|
|
3104
|
+
const eventLabels = this.callEvent.$hidden.labels || [];
|
|
3105
|
+
return new Set([...eventLabels, ...this.callEvent.codeObject.labels]);
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
get message() {
|
|
3109
|
+
return this.callEvent.$hidden.message;
|
|
3110
|
+
}
|
|
3111
|
+
|
|
3112
|
+
get httpServerRequest() {
|
|
3113
|
+
return this.callEvent.http_server_request;
|
|
3114
|
+
}
|
|
3115
|
+
|
|
3116
|
+
get httpServerResponse() {
|
|
3117
|
+
return this.returnEvent.http_server_response;
|
|
3118
|
+
}
|
|
3119
|
+
|
|
3120
|
+
get httpClientRequest() {
|
|
3121
|
+
return this.callEvent.http_client_request;
|
|
3122
|
+
}
|
|
3123
|
+
|
|
3124
|
+
get httpClientResponse() {
|
|
3125
|
+
return this.returnEvent.http_client_response;
|
|
3126
|
+
}
|
|
3127
|
+
|
|
3128
|
+
get definedClass() {
|
|
3129
|
+
return this.defined_class ? this.defined_class.replace(/\./g, '/') : null;
|
|
3130
|
+
}
|
|
3131
|
+
|
|
3132
|
+
get requestPath() {
|
|
3133
|
+
if (this.httpServerRequest) {
|
|
3134
|
+
return (
|
|
3135
|
+
this.httpServerRequest.normalized_path_info ||
|
|
3136
|
+
this.httpServerRequest.path_info
|
|
3137
|
+
);
|
|
3138
|
+
}
|
|
3139
|
+
if (this.httpClientRequest) {
|
|
3140
|
+
return this.httpClientRequest.url;
|
|
3141
|
+
}
|
|
3142
|
+
return null;
|
|
3143
|
+
}
|
|
3144
|
+
|
|
3145
|
+
get requestMethod() {
|
|
3146
|
+
if (this.httpServerRequest) {
|
|
3147
|
+
return this.httpServerRequest.request_method;
|
|
3148
|
+
}
|
|
3149
|
+
if (this.httpClientRequest) {
|
|
3150
|
+
return this.httpClientRequest.request_method;
|
|
3151
|
+
}
|
|
3152
|
+
return null;
|
|
3153
|
+
}
|
|
3154
|
+
|
|
3155
|
+
get route() {
|
|
3156
|
+
const { requestMethod, requestPath } = this;
|
|
3157
|
+
if (!requestMethod || !requestPath) {
|
|
3158
|
+
return null;
|
|
3159
|
+
}
|
|
3160
|
+
|
|
3161
|
+
return `${requestMethod} ${requestPath}`;
|
|
3162
|
+
}
|
|
3163
|
+
|
|
3164
|
+
get sqlQuery() {
|
|
3165
|
+
const { sql } = this;
|
|
3166
|
+
if (!sql) {
|
|
3167
|
+
return null;
|
|
3168
|
+
}
|
|
3169
|
+
return sql.normalized_sql || sql.sql;
|
|
3170
|
+
}
|
|
3171
|
+
|
|
3172
|
+
get fqid() {
|
|
3173
|
+
return `event:${this.id}`;
|
|
3174
|
+
}
|
|
3175
|
+
|
|
3176
|
+
get previousSibling() {
|
|
3177
|
+
const { parent } = this;
|
|
3178
|
+
if (!parent) {
|
|
3179
|
+
return null;
|
|
3180
|
+
}
|
|
3181
|
+
|
|
3182
|
+
const myIndex = parent.children.findIndex((e) => e === this);
|
|
3183
|
+
console.assert(
|
|
3184
|
+
myIndex !== -1,
|
|
3185
|
+
'attempted to locate index of an orphaned event'
|
|
3186
|
+
);
|
|
3187
|
+
|
|
3188
|
+
if (myIndex === 0) {
|
|
3189
|
+
return null;
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
return parent.children[myIndex - 1];
|
|
3193
|
+
}
|
|
3194
|
+
|
|
3195
|
+
get nextSibling() {
|
|
3196
|
+
const { parent } = this;
|
|
3197
|
+
|
|
3198
|
+
if (!parent) {
|
|
3199
|
+
let event = this.next;
|
|
3200
|
+
|
|
3201
|
+
// Get the next root level event
|
|
3202
|
+
while (event) {
|
|
3203
|
+
if (event.isCall() && !event.parent) {
|
|
3204
|
+
return event;
|
|
3205
|
+
}
|
|
3206
|
+
|
|
3207
|
+
event = event.next;
|
|
3208
|
+
}
|
|
3209
|
+
|
|
3210
|
+
return null;
|
|
3211
|
+
}
|
|
3212
|
+
|
|
3213
|
+
const myIndex = this.parent.children.findIndex((e) => e === this);
|
|
3214
|
+
console.assert(
|
|
3215
|
+
myIndex !== -1,
|
|
3216
|
+
'attempted to locate index of an orphaned event'
|
|
3217
|
+
);
|
|
3218
|
+
|
|
3219
|
+
if (myIndex === parent.children.length - 1) {
|
|
3220
|
+
return null;
|
|
3221
|
+
}
|
|
3222
|
+
|
|
3223
|
+
return parent.children[myIndex + 1];
|
|
3224
|
+
}
|
|
3225
|
+
|
|
3226
|
+
set codeObject(value) {
|
|
3227
|
+
if (hasProp(this.$hidden, 'codeObject')) {
|
|
3228
|
+
this.$hidden.codeObject = value;
|
|
3229
|
+
}
|
|
3230
|
+
}
|
|
3231
|
+
|
|
3232
|
+
set parameters(value) {
|
|
3233
|
+
if (hasProp(this.$hidden, 'parameters')) {
|
|
3234
|
+
this.$hidden.parameters = value;
|
|
3235
|
+
}
|
|
3236
|
+
}
|
|
3237
|
+
|
|
3238
|
+
set labels(value) {
|
|
3239
|
+
if (hasProp(this.$hidden, 'labels')) {
|
|
3240
|
+
this.$hidden.labels = value;
|
|
3241
|
+
}
|
|
3242
|
+
}
|
|
3243
|
+
|
|
3244
|
+
set message(value) {
|
|
3245
|
+
if (hasProp(this.$hidden, 'message')) {
|
|
3246
|
+
this.$hidden.message = value;
|
|
3247
|
+
}
|
|
3248
|
+
}
|
|
3249
|
+
|
|
3250
|
+
set linkedEvent(value) {
|
|
3251
|
+
this.$hidden.linkedEvent = value;
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3254
|
+
set next(value) {
|
|
3255
|
+
this.$hidden.next = value;
|
|
3256
|
+
}
|
|
3257
|
+
|
|
3258
|
+
set previous(value) {
|
|
3259
|
+
this.$hidden.previous = value;
|
|
3260
|
+
}
|
|
3261
|
+
|
|
3262
|
+
set parent(value) {
|
|
3263
|
+
this.$hidden.parent = value;
|
|
3264
|
+
}
|
|
3265
|
+
|
|
3266
|
+
link(event) {
|
|
3267
|
+
/* eslint-disable no-param-reassign */
|
|
3268
|
+
if (event.linkedEvent || this.linkedEvent) {
|
|
3269
|
+
return;
|
|
3270
|
+
}
|
|
3271
|
+
|
|
3272
|
+
event.linkedEvent = this;
|
|
3273
|
+
this.linkedEvent = event;
|
|
3274
|
+
/* eslint-enable no-param-reassign */
|
|
3275
|
+
}
|
|
3276
|
+
|
|
3277
|
+
isCall() {
|
|
3278
|
+
return this.event === 'call';
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
isReturn() {
|
|
3282
|
+
return this.event === 'return';
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
get callEvent() {
|
|
3286
|
+
return this.isCall() ? this : this.$hidden.linkedEvent;
|
|
3287
|
+
}
|
|
3288
|
+
|
|
3289
|
+
get returnEvent() {
|
|
3290
|
+
return this.isReturn() ? this : this.$hidden.linkedEvent;
|
|
3291
|
+
}
|
|
3292
|
+
|
|
3293
|
+
get hash() {
|
|
3294
|
+
if (!this.$hidden.hash) {
|
|
3295
|
+
this.$hidden.hash = hashEvent(this);
|
|
3296
|
+
}
|
|
3297
|
+
return this.$hidden.hash;
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
get identityHash() {
|
|
3301
|
+
if (!this.$hidden.identityHash) {
|
|
3302
|
+
this.$hidden.identityHash = identityHashEvent(this);
|
|
3303
|
+
}
|
|
3304
|
+
return this.$hidden.identityHash;
|
|
3305
|
+
}
|
|
3306
|
+
|
|
3307
|
+
callStack() {
|
|
3308
|
+
const stack = this.ancestors().reverse();
|
|
3309
|
+
stack.push(this.callEvent);
|
|
3310
|
+
return stack;
|
|
3311
|
+
}
|
|
3312
|
+
|
|
3313
|
+
ancestors() {
|
|
3314
|
+
const ancestorArray = [];
|
|
3315
|
+
let event = this.callEvent.parent;
|
|
3316
|
+
|
|
3317
|
+
while (event) {
|
|
3318
|
+
ancestorArray.push(event);
|
|
3319
|
+
event = event.parent;
|
|
3320
|
+
}
|
|
3321
|
+
|
|
3322
|
+
return ancestorArray;
|
|
3323
|
+
}
|
|
3324
|
+
|
|
3325
|
+
descendants() {
|
|
3326
|
+
const descendantArray = [];
|
|
3327
|
+
const queue = [...this.children];
|
|
3328
|
+
|
|
3329
|
+
while (queue.length) {
|
|
3330
|
+
const event = queue.pop();
|
|
3331
|
+
event.children.forEach((child) => queue.push(child));
|
|
3332
|
+
descendantArray.push(event);
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
return descendantArray;
|
|
3336
|
+
}
|
|
3337
|
+
|
|
3338
|
+
traverse(fn) {
|
|
3339
|
+
let event = this;
|
|
3340
|
+
const boundaryEvent = this.nextSibling;
|
|
3341
|
+
let { onEnter } = fn;
|
|
3342
|
+
let { onExit } = fn;
|
|
3343
|
+
|
|
3344
|
+
if (typeof fn === 'function') {
|
|
3345
|
+
onEnter = fn;
|
|
3346
|
+
onExit = fn;
|
|
3347
|
+
}
|
|
3348
|
+
|
|
3349
|
+
while (event) {
|
|
3350
|
+
if (event.isCall() && onEnter) {
|
|
3351
|
+
onEnter(event);
|
|
3352
|
+
} else if (event.isReturn() && onExit) {
|
|
3353
|
+
onExit(event);
|
|
3354
|
+
}
|
|
3355
|
+
|
|
3356
|
+
event = event.next;
|
|
3357
|
+
if (!event || event === boundaryEvent) {
|
|
3358
|
+
break;
|
|
3359
|
+
}
|
|
3360
|
+
}
|
|
3361
|
+
}
|
|
3362
|
+
|
|
3363
|
+
dataObjects() {
|
|
3364
|
+
return [this.parameters, this.message, this.returnValue]
|
|
3365
|
+
.flat()
|
|
3366
|
+
.filter(Boolean);
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
toString() {
|
|
3370
|
+
const { sqlQuery } = this;
|
|
3371
|
+
if (sqlQuery) {
|
|
3372
|
+
return sqlQuery;
|
|
3373
|
+
}
|
|
3374
|
+
|
|
3375
|
+
const { route } = this;
|
|
3376
|
+
if (route) {
|
|
3377
|
+
return route;
|
|
3378
|
+
}
|
|
3379
|
+
|
|
3380
|
+
const { definedClass, isStatic, methodId } = this;
|
|
3381
|
+
return `${definedClass}${isStatic ? '.' : '#'}${methodId}`;
|
|
3382
|
+
}
|
|
3383
|
+
}
|
|
3384
|
+
|
|
3385
|
+
class EventStack {
|
|
3386
|
+
constructor(id) {
|
|
3387
|
+
this.events = [];
|
|
3388
|
+
this.stack = [];
|
|
3389
|
+
this.id = id;
|
|
3390
|
+
this.eventMap = {};
|
|
3391
|
+
}
|
|
3392
|
+
|
|
3393
|
+
add(event) {
|
|
3394
|
+
// Don't begin a stack with a return, we likely started recording in the
|
|
3395
|
+
// middle of thread execution.
|
|
3396
|
+
if (event.isReturn() && this.events.length === 0) {
|
|
3397
|
+
return;
|
|
3398
|
+
}
|
|
3399
|
+
|
|
3400
|
+
if (event.isCall()) {
|
|
3401
|
+
this.stack.push(event);
|
|
3402
|
+
this.eventMap[event.id] = event;
|
|
3403
|
+
} else {
|
|
3404
|
+
if (typeof event.parent_id === 'undefined') {
|
|
3405
|
+
const lastEvent = this.stack[this.stack.length - 1];
|
|
3406
|
+
if (
|
|
3407
|
+
lastEvent &&
|
|
3408
|
+
lastEvent.defined_class === event.defined_class &&
|
|
3409
|
+
lastEvent.method_id === event.method_id &&
|
|
3410
|
+
lastEvent.path === event.path &&
|
|
3411
|
+
lastEvent.static === event.static
|
|
3412
|
+
) {
|
|
3413
|
+
event.parent_id = lastEvent.id; // eslint-disable-line no-param-reassign
|
|
3414
|
+
} else {
|
|
3415
|
+
// An event has returned but the last call in the stack was not its
|
|
3416
|
+
// caller. There's not really anything we can do to rectify this, so
|
|
3417
|
+
// the event will be discarded.
|
|
3418
|
+
return;
|
|
3419
|
+
}
|
|
3420
|
+
}
|
|
3421
|
+
|
|
3422
|
+
const call = this.eventMap[event.parent_id];
|
|
3423
|
+
if (call) {
|
|
3424
|
+
call.link(event);
|
|
3425
|
+
this.stack.pop();
|
|
3426
|
+
|
|
3427
|
+
const parent = this.stack[this.stack.length - 1];
|
|
3428
|
+
if (parent) {
|
|
3429
|
+
parent.children.push(call);
|
|
3430
|
+
call.parent = parent;
|
|
3431
|
+
}
|
|
3432
|
+
} else {
|
|
3433
|
+
throw new Error(
|
|
3434
|
+
`return #${event.id} is missing call #${event.parent_id}`
|
|
3435
|
+
);
|
|
3436
|
+
}
|
|
3437
|
+
}
|
|
3438
|
+
|
|
3439
|
+
this.events.push(event);
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
unwound() {
|
|
3443
|
+
return this.events.length > 0 && this.stack.length === 0;
|
|
3444
|
+
}
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
function getStackId(collection) {
|
|
3448
|
+
return (
|
|
3449
|
+
Object.keys(collection.activeStacks).length +
|
|
3450
|
+
collection.finalizedStacks.length
|
|
3451
|
+
);
|
|
3452
|
+
}
|
|
3453
|
+
|
|
3454
|
+
// EventSorter is responsible for untangling an event array. It sorts events by
|
|
3455
|
+
// thread execution order and drops leading return statements.
|
|
3456
|
+
class EventSorter {
|
|
3457
|
+
constructor() {
|
|
3458
|
+
this.activeStacks = {};
|
|
3459
|
+
this.finalizedStacks = [];
|
|
3460
|
+
}
|
|
3461
|
+
|
|
3462
|
+
// Add an event to be sorted. An event must be added through this method to
|
|
3463
|
+
// be collected.
|
|
3464
|
+
add(event) {
|
|
3465
|
+
let stack = this.activeStacks[event.thread_id];
|
|
3466
|
+
if (!stack) {
|
|
3467
|
+
const id = getStackId(this);
|
|
3468
|
+
stack = new EventStack(id);
|
|
3469
|
+
this.activeStacks[event.thread_id] = stack;
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3472
|
+
stack.add(event);
|
|
3473
|
+
|
|
3474
|
+
if (stack.unwound()) {
|
|
3475
|
+
this.finalizedStacks.splice(stack.id, 0, stack.events);
|
|
3476
|
+
delete this.activeStacks[event.thread_id];
|
|
3477
|
+
}
|
|
3478
|
+
}
|
|
3479
|
+
|
|
3480
|
+
// Calculate the serialized size of all events. This is more of an
|
|
3481
|
+
// approximation than an exact number.
|
|
3482
|
+
size() {
|
|
3483
|
+
let size = sizeof(Object.values(this.activeStacks));
|
|
3484
|
+
size += sizeof(this.finalizedStacks);
|
|
3485
|
+
return size;
|
|
3486
|
+
}
|
|
3487
|
+
|
|
3488
|
+
// Returns an array of "chunks". A chunk is an array consisting of many
|
|
3489
|
+
// stacks. A stack is an array consisting of many events.
|
|
3490
|
+
collect() {
|
|
3491
|
+
// Join active and finalized stacks. We want to make sure we iterate over
|
|
3492
|
+
// every event.
|
|
3493
|
+
const stacks = [...this.finalizedStacks];
|
|
3494
|
+
Object.values(this.activeStacks).forEach((s) =>
|
|
3495
|
+
stacks.splice(s.id, 0, s.events)
|
|
3496
|
+
);
|
|
3497
|
+
|
|
3498
|
+
return stacks.reduce((chunks, stack) => {
|
|
3499
|
+
if (stack.length === 0) {
|
|
3500
|
+
return chunks;
|
|
3501
|
+
}
|
|
3502
|
+
|
|
3503
|
+
// We're the first chunk in, meaning we don't need to worry about any
|
|
3504
|
+
// chunks behind us. Just push it.
|
|
3505
|
+
if (chunks.length === 0) {
|
|
3506
|
+
chunks.push([stack]);
|
|
3507
|
+
return chunks;
|
|
3508
|
+
}
|
|
3509
|
+
|
|
3510
|
+
// If the root event is an HTTP request, this a complete chunk. Push it.
|
|
3511
|
+
if (stack[0].http_server_request) {
|
|
3512
|
+
chunks.push([stack]);
|
|
3513
|
+
return chunks;
|
|
3514
|
+
}
|
|
3515
|
+
|
|
3516
|
+
if (stack[0].http_client_request) {
|
|
3517
|
+
chunks.push([stack]);
|
|
3518
|
+
return chunks;
|
|
3519
|
+
}
|
|
3520
|
+
|
|
3521
|
+
// Check to see if the previous chunk began with an HTTP request. If it
|
|
3522
|
+
// does, push a new chunk. Otherwise, append to the last chunk.
|
|
3523
|
+
const prevChunk = chunks[chunks.length - 1];
|
|
3524
|
+
const prevStack = prevChunk[prevChunk.length - 1];
|
|
3525
|
+
if (
|
|
3526
|
+
prevStack[0].http_server_request ||
|
|
3527
|
+
prevStack[0].http_client_request
|
|
3528
|
+
) {
|
|
3529
|
+
chunks.push([stack]);
|
|
3530
|
+
} else {
|
|
3531
|
+
prevChunk.push(stack);
|
|
3532
|
+
}
|
|
3533
|
+
|
|
3534
|
+
return chunks;
|
|
3535
|
+
}, []);
|
|
3536
|
+
}
|
|
3537
|
+
}
|
|
3538
|
+
|
|
3539
|
+
function eventName(classMap, e) {
|
|
3540
|
+
const { callEvent } = e;
|
|
3541
|
+
const obj = classMap.codeObjectFromEvent(callEvent);
|
|
3542
|
+
if (obj) {
|
|
3543
|
+
return obj.id;
|
|
3544
|
+
}
|
|
3545
|
+
|
|
3546
|
+
return `${callEvent.defined_class}${callEvent.static ? '.' : '#'}${
|
|
3547
|
+
callEvent.method_id
|
|
3548
|
+
}`;
|
|
3549
|
+
}
|
|
3550
|
+
|
|
3551
|
+
// Performs an array of transform functions on an object. The transform function
|
|
3552
|
+
// is expected to return the transformed object.
|
|
3553
|
+
const transform = (transforms, obj, ...args) =>
|
|
3554
|
+
transforms.reduce((x, fn) => fn(x, ...args), obj);
|
|
3555
|
+
|
|
3556
|
+
// AppMapBuilder is responsible for transforming appmap data before returning
|
|
3557
|
+
// an AppMap model.
|
|
3558
|
+
class AppMapBuilder extends EventSource {
|
|
3559
|
+
constructor(data) {
|
|
3560
|
+
super();
|
|
3561
|
+
|
|
3562
|
+
this.sorter = new EventSorter();
|
|
3563
|
+
this.transforms = {
|
|
3564
|
+
event: [],
|
|
3565
|
+
stack: [],
|
|
3566
|
+
chunk: [],
|
|
3567
|
+
};
|
|
3568
|
+
|
|
3569
|
+
if (data) {
|
|
3570
|
+
this.source(data);
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
|
|
3574
|
+
// Provide a source of data - i.e. an appmap JSON object
|
|
3575
|
+
source(data) {
|
|
3576
|
+
const dataType = typeof data;
|
|
3577
|
+
if (dataType === 'object') {
|
|
3578
|
+
this.data = { ...data };
|
|
3579
|
+
} else if (dataType === 'string') {
|
|
3580
|
+
this.data = JSON.parse(data);
|
|
3581
|
+
} else {
|
|
3582
|
+
throw new Error(
|
|
3583
|
+
`got invalid type ${dataType}, expected object or string`
|
|
3584
|
+
);
|
|
3585
|
+
}
|
|
3586
|
+
|
|
3587
|
+
(this.data.events || [])
|
|
3588
|
+
.map((e) => new Event(e))
|
|
3589
|
+
.forEach((e) => this.sorter.add(e));
|
|
3590
|
+
|
|
3591
|
+
delete this.data.events;
|
|
3592
|
+
|
|
3593
|
+
return this;
|
|
3594
|
+
}
|
|
3595
|
+
|
|
3596
|
+
// register an optional event transform
|
|
3597
|
+
event(fn) {
|
|
3598
|
+
console.assert(typeof fn === 'function');
|
|
3599
|
+
this.transforms.event.push(fn);
|
|
3600
|
+
return this;
|
|
3601
|
+
}
|
|
3602
|
+
|
|
3603
|
+
// register a optional stack transform
|
|
3604
|
+
stack(fn) {
|
|
3605
|
+
console.assert(typeof fn === 'function');
|
|
3606
|
+
this.transforms.stack.push(fn);
|
|
3607
|
+
return this;
|
|
3608
|
+
}
|
|
3609
|
+
|
|
3610
|
+
// register a optional chunk transform
|
|
3611
|
+
chunk(fn) {
|
|
3612
|
+
console.assert(typeof fn === 'function');
|
|
3613
|
+
this.transforms.chunk.push(fn);
|
|
3614
|
+
return this;
|
|
3615
|
+
}
|
|
3616
|
+
|
|
3617
|
+
// normalize the appmap data before returning an Appmap model
|
|
3618
|
+
normalize() {
|
|
3619
|
+
// Re-index events
|
|
3620
|
+
let eventId = 1;
|
|
3621
|
+
this.event((event) => {
|
|
3622
|
+
/* eslint-disable no-param-reassign */
|
|
3623
|
+
event.id = eventId;
|
|
3624
|
+
eventId += 1;
|
|
3625
|
+
|
|
3626
|
+
if (event.isCall() && event.returnEvent) {
|
|
3627
|
+
event.returnEvent.parent_id = event.id;
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3630
|
+
// Normalize status/status_code properties
|
|
3631
|
+
const { httpServerResponse, httpClientResponse } = event;
|
|
3632
|
+
if (event.isReturn()) {
|
|
3633
|
+
if (httpServerResponse && httpServerResponse.status_code) {
|
|
3634
|
+
httpServerResponse.status = httpServerResponse.status_code;
|
|
3635
|
+
delete httpServerResponse.status_code;
|
|
3636
|
+
}
|
|
3637
|
+
if (httpClientResponse && httpClientResponse.status_code) {
|
|
3638
|
+
httpClientResponse.status = httpClientResponse.status_code;
|
|
3639
|
+
delete httpClientResponse.status_code;
|
|
3640
|
+
}
|
|
3641
|
+
}
|
|
3642
|
+
|
|
3643
|
+
return event;
|
|
3644
|
+
/* eslint-enable no-param-reassign */
|
|
3645
|
+
});
|
|
3646
|
+
|
|
3647
|
+
// Balance the stack by adding dummy returns to calls which never return
|
|
3648
|
+
return this.stack((events) => {
|
|
3649
|
+
events
|
|
3650
|
+
.filter((e) => e.isCall() && !e.returnEvent)
|
|
3651
|
+
.reverse()
|
|
3652
|
+
.map((e) => {
|
|
3653
|
+
const returnEvent = new Event({
|
|
3654
|
+
event: 'return',
|
|
3655
|
+
thread_id: e.thread_id,
|
|
3656
|
+
parent_id: e.id,
|
|
3657
|
+
});
|
|
3658
|
+
returnEvent.link(e);
|
|
3659
|
+
return returnEvent;
|
|
3660
|
+
})
|
|
3661
|
+
.forEach((e) => events.push(e));
|
|
3662
|
+
|
|
3663
|
+
return events;
|
|
3664
|
+
});
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3667
|
+
// Cut down the size of the event array before creating the Appmap model
|
|
3668
|
+
prune(sizeBytes) {
|
|
3669
|
+
console.assert(typeof sizeBytes === 'number');
|
|
3670
|
+
|
|
3671
|
+
let classMap;
|
|
3672
|
+
let pruneRatio = 0;
|
|
3673
|
+
return this.on('preprocess', (d) => {
|
|
3674
|
+
classMap = new ClassMap(d.data.classMap);
|
|
3675
|
+
pruneRatio = Math.min(sizeBytes / d.size, 1);
|
|
3676
|
+
}).chunk((stacks) => {
|
|
3677
|
+
// We're storing size/count state in the global class map. This isn't
|
|
3678
|
+
// great but it works for now. Reset the counts for each chunk.
|
|
3679
|
+
classMap.visit((obj) => {
|
|
3680
|
+
/* eslint-disable no-param-reassign */
|
|
3681
|
+
obj.size = 0;
|
|
3682
|
+
obj.count = 0;
|
|
3683
|
+
/* eslint-enable no-param-reassign */
|
|
3684
|
+
});
|
|
3685
|
+
|
|
3686
|
+
// Iterate each event, regardless of the stack
|
|
3687
|
+
stacks.flat(2).forEach((e) => {
|
|
3688
|
+
if (
|
|
3689
|
+
e.event !== 'call' ||
|
|
3690
|
+
e.sql_query ||
|
|
3691
|
+
e.http_server_request ||
|
|
3692
|
+
e.http_client_request
|
|
3693
|
+
) {
|
|
3694
|
+
return;
|
|
3695
|
+
}
|
|
3696
|
+
|
|
3697
|
+
const obj = classMap.codeObjectFromEvent(e);
|
|
3698
|
+
if (obj) {
|
|
3699
|
+
const objSize = sizeof(e);
|
|
3700
|
+
obj.size = obj.size + objSize || objSize;
|
|
3701
|
+
obj.count = obj.count + 1 || 1;
|
|
3702
|
+
}
|
|
3703
|
+
});
|
|
3704
|
+
|
|
3705
|
+
// Build an array of code objects sorted by size. The largest object
|
|
3706
|
+
// will always be index 0.
|
|
3707
|
+
let totalBytes = 0;
|
|
3708
|
+
const eventAggregates = classMap.codeObjects
|
|
3709
|
+
.filter((obj) => obj.size)
|
|
3710
|
+
.sort((a, b) => a.size - b.size)
|
|
3711
|
+
.map((obj) => {
|
|
3712
|
+
totalBytes += obj.size;
|
|
3713
|
+
return {
|
|
3714
|
+
id: obj.id,
|
|
3715
|
+
count: obj.count,
|
|
3716
|
+
size: obj.size,
|
|
3717
|
+
totalBytes,
|
|
3718
|
+
};
|
|
3719
|
+
})
|
|
3720
|
+
.reverse();
|
|
3721
|
+
|
|
3722
|
+
// Build a list of unique exclusions, starting with the largest event
|
|
3723
|
+
// type. Iterate until the estimated event array size is under our
|
|
3724
|
+
// threshold.
|
|
3725
|
+
const exclusions = new Set();
|
|
3726
|
+
for (let i = 0; i < eventAggregates.length; i += 1) {
|
|
3727
|
+
const eventInfo = eventAggregates[i];
|
|
3728
|
+
if (eventInfo.totalBytes <= totalBytes * pruneRatio) {
|
|
3729
|
+
break;
|
|
3730
|
+
}
|
|
3731
|
+
exclusions.add(eventInfo.id);
|
|
3732
|
+
}
|
|
3733
|
+
|
|
3734
|
+
return stacks.map((events) =>
|
|
3735
|
+
events.filter((e) => {
|
|
3736
|
+
const { callEvent } = e;
|
|
3737
|
+
|
|
3738
|
+
// If there's no call event, there's no need to retain this event
|
|
3739
|
+
if (!callEvent) {
|
|
3740
|
+
return false;
|
|
3741
|
+
}
|
|
3742
|
+
|
|
3743
|
+
if (
|
|
3744
|
+
callEvent.http_server_request ||
|
|
3745
|
+
callEvent.http_client_request ||
|
|
3746
|
+
callEvent.sql_query
|
|
3747
|
+
) {
|
|
3748
|
+
return true;
|
|
3749
|
+
}
|
|
3750
|
+
|
|
3751
|
+
const name = eventName(classMap, e);
|
|
3752
|
+
return !exclusions.has(name);
|
|
3753
|
+
})
|
|
3754
|
+
);
|
|
3755
|
+
});
|
|
3756
|
+
}
|
|
3757
|
+
|
|
3758
|
+
removeNoise() {
|
|
3759
|
+
if (!this.data.events) {
|
|
3760
|
+
return this;
|
|
3761
|
+
}
|
|
3762
|
+
|
|
3763
|
+
const hasHttp = Boolean(
|
|
3764
|
+
this.data.events.find((e) => e.httpServerRequest || e.httpClientRequest)
|
|
3765
|
+
);
|
|
3766
|
+
if (!hasHttp) {
|
|
3767
|
+
// the entire file is noise - do nothing
|
|
3768
|
+
return this;
|
|
3769
|
+
}
|
|
3770
|
+
|
|
3771
|
+
return this.chunk((stacks) =>
|
|
3772
|
+
stacks.filter((stack) => {
|
|
3773
|
+
if (!stack.length) {
|
|
3774
|
+
return false;
|
|
3775
|
+
}
|
|
3776
|
+
|
|
3777
|
+
return (
|
|
3778
|
+
Boolean(stack[0].httpServerRequest) ||
|
|
3779
|
+
Boolean(stack[0].httpClientRequest)
|
|
3780
|
+
);
|
|
3781
|
+
})
|
|
3782
|
+
);
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
collectEvents() {
|
|
3786
|
+
return this.sorter
|
|
3787
|
+
.collect()
|
|
3788
|
+
.map((chunk) => {
|
|
3789
|
+
const transformedChunk = transform(this.transforms.chunk, chunk);
|
|
3790
|
+
return transformedChunk.map((stack) => {
|
|
3791
|
+
const transformedStack = transform(this.transforms.stack, stack);
|
|
3792
|
+
return transformedStack.map((event) =>
|
|
3793
|
+
transform(this.transforms.event, event)
|
|
3794
|
+
);
|
|
3795
|
+
});
|
|
3796
|
+
})
|
|
3797
|
+
.flat(2);
|
|
3798
|
+
}
|
|
3799
|
+
|
|
3800
|
+
// Returns an Appmap model after running transforms such as normalize, prune,
|
|
3801
|
+
// etc.
|
|
3802
|
+
build() {
|
|
3803
|
+
const size = this.sorter.size();
|
|
3804
|
+
this.emit('preprocess', { size, data: this.data });
|
|
3805
|
+
return new AppMap({ ...this.data, events: this.collectEvents() });
|
|
3806
|
+
}
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3809
|
+
function buildAppMap(data = null) {
|
|
3810
|
+
return new AppMapBuilder(data);
|
|
3811
|
+
}
|
|
3812
|
+
|
|
3813
|
+
class EventNavigator {
|
|
3814
|
+
constructor(event) {
|
|
3815
|
+
this.event = event;
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
get callEvent() {
|
|
3819
|
+
return this.event.callEvent;
|
|
3820
|
+
}
|
|
3821
|
+
|
|
3822
|
+
get labels() {
|
|
3823
|
+
const { codeObject } = this.event;
|
|
3824
|
+
if (codeObject && codeObject.labels) {
|
|
3825
|
+
return codeObject.labels;
|
|
3826
|
+
}
|
|
3827
|
+
return null;
|
|
3828
|
+
}
|
|
3829
|
+
|
|
3830
|
+
*self() {
|
|
3831
|
+
yield this;
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
*ancestors() {
|
|
3835
|
+
let event = this.callEvent.parent;
|
|
3836
|
+
|
|
3837
|
+
while (event) {
|
|
3838
|
+
yield new EventNavigator(event);
|
|
3839
|
+
event = event.parent;
|
|
3840
|
+
}
|
|
3841
|
+
}
|
|
3842
|
+
|
|
3843
|
+
/**
|
|
3844
|
+
* Generates all events which precede this event in the scenario.
|
|
3845
|
+
*/
|
|
3846
|
+
*preceding() {
|
|
3847
|
+
const ancestors = this.ancestors();
|
|
3848
|
+
let ancestor = ancestors.next();
|
|
3849
|
+
while (!ancestor.done) {
|
|
3850
|
+
yield new EventNavigator(ancestor.value);
|
|
3851
|
+
let precedingSibling = this.precedingSiblings.next();
|
|
3852
|
+
while (!precedingSibling.done) {
|
|
3853
|
+
yield new EventNavigator(precedingSibling.value);
|
|
3854
|
+
const descendants = precedingSibling.value.descendants();
|
|
3855
|
+
let descendant = descendants.next();
|
|
3856
|
+
while (!descendant.done) {
|
|
3857
|
+
yield new EventNavigator(descendant.value);
|
|
3858
|
+
descendant = descendants.next();
|
|
3859
|
+
}
|
|
3860
|
+
precedingSibling = this.precedingSiblings.next();
|
|
3861
|
+
}
|
|
3862
|
+
ancestor = ancestors.next();
|
|
3863
|
+
}
|
|
3864
|
+
}
|
|
3865
|
+
|
|
3866
|
+
*precedingSiblings() {
|
|
3867
|
+
const { parent } = this.callEvent;
|
|
3868
|
+
if (!parent) {
|
|
3869
|
+
return;
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3872
|
+
const index = parent.children.indexOf(this.callEvent);
|
|
3873
|
+
for (let i = index - 1; i >= 0; i -= 1) {
|
|
3874
|
+
yield new EventNavigator(parent.children[i]);
|
|
3875
|
+
}
|
|
3876
|
+
}
|
|
3877
|
+
|
|
3878
|
+
*followingSiblings() {
|
|
3879
|
+
const { parent } = this.callEvent;
|
|
3880
|
+
if (!parent) {
|
|
3881
|
+
return;
|
|
3882
|
+
}
|
|
3883
|
+
|
|
3884
|
+
const index = parent.children.indexOf(this.callEvent);
|
|
3885
|
+
for (let i = index + 1; i < parent.children.length; i += 1) {
|
|
3886
|
+
yield new EventNavigator(parent.children[i]);
|
|
3887
|
+
}
|
|
3888
|
+
}
|
|
3889
|
+
|
|
3890
|
+
*descendants(filterFn = () => true) {
|
|
3891
|
+
if (!this.event.children || this.event.children.length === 0) {
|
|
3892
|
+
return;
|
|
3893
|
+
}
|
|
3894
|
+
|
|
3895
|
+
// We want to traverse in order. So we use this type of traversal,
|
|
3896
|
+
// rather than pushing all the events onto a queue. We avoid using
|
|
3897
|
+
// Array.shift which can be expensive.
|
|
3898
|
+
const queue = [this.event.children];
|
|
3899
|
+
let queueIndex = 0;
|
|
3900
|
+
let childIndex = 0;
|
|
3901
|
+
|
|
3902
|
+
while (queueIndex < queue.length) {
|
|
3903
|
+
const event = queue[queueIndex][childIndex];
|
|
3904
|
+
if (filterFn(event)) {
|
|
3905
|
+
yield new EventNavigator(event);
|
|
3906
|
+
}
|
|
3907
|
+
if (childIndex === queue[queueIndex].length - 1) {
|
|
3908
|
+
queueIndex += 1;
|
|
3909
|
+
childIndex = 0;
|
|
3910
|
+
} else {
|
|
3911
|
+
childIndex += 1;
|
|
3912
|
+
}
|
|
3913
|
+
if (event.children.length > 0) {
|
|
3914
|
+
queue.push(event.children);
|
|
3915
|
+
}
|
|
3916
|
+
}
|
|
3917
|
+
}
|
|
3918
|
+
|
|
3919
|
+
hasLabel(label) {
|
|
3920
|
+
return this.hasLabels([label]);
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3923
|
+
hasLabels(...searchLabels) {
|
|
3924
|
+
if (!this.labels) {
|
|
3925
|
+
return false;
|
|
3926
|
+
}
|
|
3927
|
+
|
|
3928
|
+
if (!searchLabels || !searchLabels.length) {
|
|
3929
|
+
return this.labels.size > 0;
|
|
3930
|
+
}
|
|
3931
|
+
|
|
3932
|
+
return (
|
|
3933
|
+
searchLabels.filter((l) => this.labels.has(l)).length ===
|
|
3934
|
+
searchLabels.length
|
|
3935
|
+
);
|
|
3936
|
+
}
|
|
3937
|
+
}
|
|
3938
|
+
|
|
3939
|
+
function mapFunctionLocations(memo, obj) {
|
|
3940
|
+
/* eslint-disable no-param-reassign */
|
|
3941
|
+
if (obj.type === 'function') {
|
|
3942
|
+
memo[obj.location] = obj;
|
|
3943
|
+
}
|
|
3944
|
+
|
|
3945
|
+
if (obj.children) {
|
|
3946
|
+
obj.children.reduce(mapFunctionLocations, memo);
|
|
3947
|
+
}
|
|
3948
|
+
|
|
3949
|
+
return memo;
|
|
3950
|
+
/* eslint-enable no-param-reassign */
|
|
3951
|
+
}
|
|
3952
|
+
|
|
3953
|
+
class EventInfo {
|
|
3954
|
+
constructor(classMap) {
|
|
3955
|
+
this.functionObjects = classMap.reduce(mapFunctionLocations, {});
|
|
3956
|
+
}
|
|
3957
|
+
|
|
3958
|
+
getName(event) {
|
|
3959
|
+
const label = getLabel(event);
|
|
3960
|
+
if (label) {
|
|
3961
|
+
return label;
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
const codeObj = this.getCodeObject(event);
|
|
3965
|
+
if (codeObj) {
|
|
3966
|
+
return codeObj.display_name;
|
|
3967
|
+
}
|
|
3968
|
+
|
|
3969
|
+
// Fallback algorithm
|
|
3970
|
+
const separator = event.static ? '.' : '#';
|
|
3971
|
+
return [event.defined_class, separator, event.method_id].join('');
|
|
3972
|
+
}
|
|
3973
|
+
|
|
3974
|
+
getLabels(event) {
|
|
3975
|
+
const labels = [];
|
|
3976
|
+
|
|
3977
|
+
if (event.labels) {
|
|
3978
|
+
labels.push(...event.labels);
|
|
3979
|
+
}
|
|
3980
|
+
|
|
3981
|
+
const codeObj = this.getCodeObject(event);
|
|
3982
|
+
if (codeObj && codeObj.labels.length) {
|
|
3983
|
+
labels.push(...codeObj.labels);
|
|
3984
|
+
}
|
|
3985
|
+
|
|
3986
|
+
return labels;
|
|
3987
|
+
}
|
|
3988
|
+
|
|
3989
|
+
getCodeObject(event) {
|
|
3990
|
+
return this.functionObjects[`${event.path}:${event.lineno}`];
|
|
3991
|
+
}
|
|
3992
|
+
}
|
|
3993
|
+
|
|
3994
|
+
const PUBLIC = 'public';
|
|
3995
|
+
const MVC_MODEL = 'model';
|
|
3996
|
+
const MVC_VIEW = 'view';
|
|
3997
|
+
const MVC_CONTROLLER = 'controller';
|
|
3998
|
+
const PROVIDER_AUTHENTICATION = 'provider.authentication';
|
|
3999
|
+
const PROVIDER_AUTHORIZATION = 'provider.authorization';
|
|
4000
|
+
|
|
4001
|
+
/**
|
|
4002
|
+
* Indicates that a scan has detected an illegal condition on an event.
|
|
4003
|
+
*/
|
|
4004
|
+
class ScanError extends Error {
|
|
4005
|
+
constructor(message, event) {
|
|
4006
|
+
super(message);
|
|
4007
|
+
this.event = event;
|
|
4008
|
+
}
|
|
4009
|
+
}
|
|
4010
|
+
|
|
4011
|
+
/* eslint-disable no-restricted-syntax */
|
|
4012
|
+
|
|
4013
|
+
class Public {
|
|
4014
|
+
constructor(event) {
|
|
4015
|
+
this.event = event;
|
|
4016
|
+
}
|
|
4017
|
+
|
|
4018
|
+
toString() {
|
|
4019
|
+
return `${this.event.toString()} is public`;
|
|
4020
|
+
}
|
|
4021
|
+
}
|
|
4022
|
+
|
|
4023
|
+
class Authenticator {
|
|
4024
|
+
constructor(event) {
|
|
4025
|
+
this.event = event;
|
|
4026
|
+
}
|
|
4027
|
+
|
|
4028
|
+
toString() {
|
|
4029
|
+
return `Authentication is provided by ${this.event.toString()}`;
|
|
4030
|
+
}
|
|
4031
|
+
}
|
|
4032
|
+
|
|
4033
|
+
function isPublic(event) {
|
|
4034
|
+
return event.codeObject && event.codeObject.labels.has(PUBLIC);
|
|
4035
|
+
}
|
|
4036
|
+
|
|
4037
|
+
function providesAuthentication(event) {
|
|
4038
|
+
return (
|
|
4039
|
+
event.codeObject &&
|
|
4040
|
+
event.codeObject.labels.has(PROVIDER_AUTHENTICATION) &&
|
|
4041
|
+
!isFalsey(event.returnValue)
|
|
4042
|
+
);
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
class Target$1 {
|
|
4046
|
+
constructor(event) {
|
|
4047
|
+
this.event = event;
|
|
4048
|
+
}
|
|
4049
|
+
|
|
4050
|
+
toString() {
|
|
4051
|
+
return this.event.toString();
|
|
4052
|
+
}
|
|
4053
|
+
|
|
4054
|
+
/**
|
|
4055
|
+
* Finds the labeled authenticator within the scope.
|
|
4056
|
+
*/
|
|
4057
|
+
// eslint-disable-next-line require-yield
|
|
4058
|
+
*evaluate() {
|
|
4059
|
+
const pub = this.event.descendants(isPublic).next();
|
|
4060
|
+
if (pub.value) {
|
|
4061
|
+
yield new Public(pub);
|
|
4062
|
+
return;
|
|
4063
|
+
}
|
|
4064
|
+
|
|
4065
|
+
const authenticator = this.event.descendants(providesAuthentication).next();
|
|
4066
|
+
if (authenticator.value) {
|
|
4067
|
+
yield new Authenticator(authenticator.value.event);
|
|
4068
|
+
return;
|
|
4069
|
+
}
|
|
4070
|
+
yield new ScanError(
|
|
4071
|
+
`No authentication provider found in ${this.event.event.route}`,
|
|
4072
|
+
this.event.event
|
|
4073
|
+
);
|
|
4074
|
+
}
|
|
4075
|
+
}
|
|
4076
|
+
|
|
4077
|
+
class Scope$1 {
|
|
4078
|
+
constructor(event) {
|
|
4079
|
+
this.event = event;
|
|
4080
|
+
}
|
|
4081
|
+
|
|
4082
|
+
toString() {
|
|
4083
|
+
return this.event.toString();
|
|
4084
|
+
}
|
|
4085
|
+
|
|
4086
|
+
*targets() {
|
|
4087
|
+
yield new Target$1(this.event);
|
|
4088
|
+
}
|
|
4089
|
+
}
|
|
4090
|
+
|
|
4091
|
+
function isAcceptedRoute(event) {
|
|
4092
|
+
if (!event.isCall()) {
|
|
4093
|
+
return false;
|
|
4094
|
+
}
|
|
4095
|
+
|
|
4096
|
+
if (!event.httpServerRequest) {
|
|
4097
|
+
return false;
|
|
4098
|
+
}
|
|
4099
|
+
|
|
4100
|
+
if (event.httpServerResponse && event.httpServerResponse.status >= 300) {
|
|
4101
|
+
return false;
|
|
4102
|
+
}
|
|
4103
|
+
|
|
4104
|
+
return true;
|
|
4105
|
+
}
|
|
4106
|
+
|
|
4107
|
+
/**
|
|
4108
|
+
* Ensures non-public routes have authentication.
|
|
4109
|
+
*/
|
|
4110
|
+
class AuthenticationMissing {
|
|
4111
|
+
// eslint-disable-next-line class-methods-use-this
|
|
4112
|
+
toString() {
|
|
4113
|
+
return 'Authentication is required';
|
|
4114
|
+
}
|
|
4115
|
+
|
|
4116
|
+
// eslint-disable-next-line class-methods-use-this
|
|
4117
|
+
*scopes(events) {
|
|
4118
|
+
for (let index = 0; index < events.length; index += 1) {
|
|
4119
|
+
const evt = events[index];
|
|
4120
|
+
if (isAcceptedRoute(evt)) {
|
|
4121
|
+
yield new Scope$1(new EventNavigator(evt));
|
|
4122
|
+
}
|
|
4123
|
+
}
|
|
4124
|
+
}
|
|
4125
|
+
}
|
|
4126
|
+
|
|
4127
|
+
/* eslint-disable import/prefer-default-export */
|
|
4128
|
+
|
|
4129
|
+
class Target {
|
|
4130
|
+
// eslint-disable-next-line class-methods-use-this
|
|
4131
|
+
toString() {
|
|
4132
|
+
return 'Target';
|
|
4133
|
+
}
|
|
4134
|
+
|
|
4135
|
+
*evaluate() {
|
|
4136
|
+
for (const event of this.event.descendants((evt) => evt.sql_query)) {
|
|
4137
|
+
yield new ScanError(
|
|
4138
|
+
`Query ${event.toString()} performed from view`,
|
|
4139
|
+
event
|
|
4140
|
+
);
|
|
4141
|
+
}
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
|
|
4145
|
+
class Scope {
|
|
4146
|
+
constructor(event) {
|
|
4147
|
+
this.event = event;
|
|
4148
|
+
}
|
|
4149
|
+
|
|
4150
|
+
toString() {
|
|
4151
|
+
return this.event.toString();
|
|
4152
|
+
}
|
|
4153
|
+
|
|
4154
|
+
/**
|
|
4155
|
+
* Finds the labeled mvc.view.
|
|
4156
|
+
*/
|
|
4157
|
+
*targets() {
|
|
4158
|
+
for (const event of this.event.descendants((evt) =>
|
|
4159
|
+
evt.hasLabel(MVC_VIEW)
|
|
4160
|
+
)) {
|
|
4161
|
+
yield new Target(event);
|
|
4162
|
+
}
|
|
4163
|
+
}
|
|
4164
|
+
}
|
|
4165
|
+
|
|
4166
|
+
/**
|
|
4167
|
+
* Forbids SQL queries from the view layer.
|
|
4168
|
+
*/
|
|
4169
|
+
class QueryFromView {
|
|
4170
|
+
// eslint-disable-next-line class-methods-use-this
|
|
4171
|
+
*scopes(event) {
|
|
4172
|
+
for (const scope of new EventNavigator(event).descendants(
|
|
4173
|
+
(evt) => evt.httpServerRequest
|
|
4174
|
+
)) {
|
|
4175
|
+
yield new Scope(scope);
|
|
4176
|
+
}
|
|
4177
|
+
}
|
|
4178
|
+
}
|
|
4179
|
+
|
|
4180
|
+
/* eslint-disable no-restricted-syntax */
|
|
4181
|
+
function scan(scanner) {
|
|
4182
|
+
return (events) => {
|
|
4183
|
+
const targets = [];
|
|
4184
|
+
const matches = [];
|
|
4185
|
+
const errors = [];
|
|
4186
|
+
for (const scope of scanner.scopes(events)) {
|
|
4187
|
+
for (const target of scope.targets()) {
|
|
4188
|
+
targets.push(target);
|
|
4189
|
+
for (const result of target.evaluate()) {
|
|
4190
|
+
if (result instanceof ScanError) {
|
|
4191
|
+
errors.push(result);
|
|
4192
|
+
} else {
|
|
4193
|
+
matches.push(result);
|
|
4194
|
+
}
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
}
|
|
4198
|
+
return { targets, matches, errors };
|
|
4199
|
+
};
|
|
4200
|
+
}
|
|
4201
|
+
|
|
4202
|
+
exports.AppMap = AppMap;
|
|
4203
|
+
exports.AuthenticationMissing = AuthenticationMissing;
|
|
4204
|
+
exports.Authenticator = Authenticator;
|
|
4205
|
+
exports.CallTree = CallTree;
|
|
4206
|
+
exports.ClassMap = ClassMap;
|
|
4207
|
+
exports.CodeObject = CodeObject;
|
|
4208
|
+
exports.CodeObjectType = CodeObjectType;
|
|
4209
|
+
exports.Event = Event;
|
|
4210
|
+
exports.EventInfo = EventInfo;
|
|
4211
|
+
exports.EventNavigator = EventNavigator;
|
|
4212
|
+
exports.EventSource = EventSource;
|
|
4213
|
+
exports.MVC_CONTROLLER = MVC_CONTROLLER;
|
|
4214
|
+
exports.MVC_MODEL = MVC_MODEL;
|
|
4215
|
+
exports.MVC_VIEW = MVC_VIEW;
|
|
4216
|
+
exports.PROVIDER_AUTHENTICATION = PROVIDER_AUTHENTICATION;
|
|
4217
|
+
exports.PROVIDER_AUTHORIZATION = PROVIDER_AUTHORIZATION;
|
|
4218
|
+
exports.PUBLIC = PUBLIC;
|
|
4219
|
+
exports.Public = Public;
|
|
4220
|
+
exports.QueryFromView = QueryFromView;
|
|
4221
|
+
exports.ScanError = ScanError;
|
|
4222
|
+
exports.addHiddenProperty = addHiddenProperty;
|
|
4223
|
+
exports.appMapObjectCompare = appMapObjectCompare;
|
|
4224
|
+
exports.arrayCompare = arrayCompare;
|
|
4225
|
+
exports.buildAppMap = buildAppMap;
|
|
4226
|
+
exports.buildLabels = buildLabels;
|
|
4227
|
+
exports.capitalizeString = capitalizeString;
|
|
4228
|
+
exports.fullyQualifiedFunctionName = fullyQualifiedFunctionName;
|
|
4229
|
+
exports.getHttpLabel = getHttpLabel;
|
|
4230
|
+
exports.getLabel = getLabel;
|
|
4231
|
+
exports.getRepositoryUrl = getRepositoryUrl;
|
|
4232
|
+
exports.getRootEvents = getRootEvents;
|
|
4233
|
+
exports.getSqlLabel = getSqlLabel;
|
|
4234
|
+
exports.getSqlLabelFromString = getSqlLabelFromString;
|
|
4235
|
+
exports.hasProp = hasProp;
|
|
4236
|
+
exports.hashEvent = hashEvent;
|
|
4237
|
+
exports.hashHttp = hashHttp;
|
|
4238
|
+
exports.hashSql = hashSql;
|
|
4239
|
+
exports.hashify = hashify;
|
|
4240
|
+
exports.httpCompare = httpCompare;
|
|
4241
|
+
exports.identityHashEvent = identityHashEvent;
|
|
4242
|
+
exports.isCommand = isCommand;
|
|
4243
|
+
exports.isFalsey = isFalsey;
|
|
4244
|
+
exports.normalizeSQL = normalizeSQL;
|
|
4245
|
+
exports.resolveDifferences = resolveDifferences;
|
|
4246
|
+
exports.scan = scan;
|
|
4247
|
+
exports.setCompare = setCompare;
|
|
4248
|
+
exports.sizeof = sizeof;
|
|
4249
|
+
exports.sqlCompare = sqlCompare;
|
|
4250
|
+
exports.tokenizeIdentifier = tokenizeIdentifier;
|