Full Code of wix/quix for AI

master dca0b4b6f10e cached
1185 files
3.1 MB
900.3k tokens
2476 symbols
1 requests
Download .txt
Showing preview only (3,587K chars total). Download the full file or copy to clipboard to get everything.
Repository: wix/quix
Branch: master
Commit: dca0b4b6f10e
Files: 1185
Total size: 3.1 MB

Directory structure:
gitextract_w_z6e63k/

├── .dockerignore
├── .github/
│   └── workflows/
│       ├── quix-backend-build.yml
│       ├── quix-documentation-publish.yml
│       ├── quix-frontend-publish.yml
│       └── quix-frontend-release.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build-selector.sh
├── docker-compose.prebuilt.yml
├── docker-compose.yml
├── documentation/
│   ├── docs/
│   │   ├── about.md
│   │   ├── architecture.md
│   │   ├── athena.md
│   │   ├── bigquery.md
│   │   ├── clickhouse.md
│   │   ├── installation.md
│   │   ├── jdbc.md
│   │   ├── mariadb.md
│   │   ├── mysql.md
│   │   ├── oracle.md
│   │   ├── postgresql.md
│   │   ├── presto.md
│   │   ├── python.md
│   │   └── redshift.md
│   └── website/
│       ├── README.md
│       ├── blog/
│       │   └── 2019-11-25-first-release.md
│       ├── core/
│       │   └── Footer.js
│       ├── i18n/
│       │   └── en.json
│       ├── package.json
│       ├── pages/
│       │   └── en/
│       │       ├── help.js
│       │       ├── index.js
│       │       └── users.js
│       ├── sidebars.json
│       ├── siteConfig.js
│       └── static/
│           └── css/
│               └── custom.css
├── env-example
├── quix-backend/
│   ├── Dockerfile
│   ├── README.md
│   ├── build.sbt
│   ├── quix-api/
│   │   └── src/
│   │       └── main/
│   │           └── scala/
│   │               └── quix/
│   │                   └── api/
│   │                       ├── v1/
│   │                       │   ├── db/
│   │                       │   │   └── Db.scala
│   │                       │   ├── execute/
│   │                       │   │   ├── Api.scala
│   │                       │   │   ├── Batch.scala
│   │                       │   │   ├── ExecutionEngine.scala
│   │                       │   │   └── ExecutionProtocol.scala
│   │                       │   ├── module/
│   │                       │   │   └── ExecutionModule.scala
│   │                       │   └── users/
│   │                       │       └── Users.scala
│   │                       └── v2/
│   │                           └── execute/
│   │                               ├── Builder.scala
│   │                               ├── ExecutionModule.scala
│   │                               ├── Executor.scala
│   │                               ├── Session.scala
│   │                               └── SubQuery.scala
│   ├── quix-core/
│   │   └── src/
│   │       ├── main/
│   │       │   └── scala/
│   │       │       └── quix/
│   │       │           └── core/
│   │       │               ├── db/
│   │       │               │   ├── DbOps.scala
│   │       │               │   ├── RefreshableAutocomplete.scala
│   │       │               │   ├── RefreshableCatalogs.scala
│   │       │               │   ├── RefreshableDb.scala
│   │       │               │   └── State.scala
│   │       │               ├── download/
│   │       │               │   ├── DownloadConfig.scala
│   │       │               │   └── DownloadableBuilder.scala
│   │       │               ├── executions/
│   │       │               │   ├── DelegatingBuilder.scala
│   │       │               │   ├── SingleQueryExecutor.scala
│   │       │               │   └── SqlModule.scala
│   │       │               ├── history/
│   │       │               │   ├── Execution.scala
│   │       │               │   ├── HistoryBuilder.scala
│   │       │               │   └── dao/
│   │       │               │       ├── HistoryReadDao.scala
│   │       │               │       ├── HistoryWriteDao.scala
│   │       │               │       ├── InMemoryHistoryDao.scala
│   │       │               │       └── MySqlHistoryDao.scala
│   │       │               ├── results/
│   │       │               │   ├── MultiBuilder.scala
│   │       │               │   └── SingleBuilder.scala
│   │       │               ├── sql/
│   │       │               │   ├── PrestoSqlOps.scala
│   │       │               │   └── SqlSplitter.scala
│   │       │               └── utils/
│   │       │                   ├── Chores.scala
│   │       │                   ├── JsonOps.scala
│   │       │                   └── TaskOps.scala
│   │       └── test/
│   │           ├── resources/
│   │           │   └── db/
│   │           │       └── 001_init.sql
│   │           └── scala/
│   │               └── quix/
│   │                   └── core/
│   │                       ├── db/
│   │                       │   ├── DbOpsTest.scala
│   │                       │   └── DbQueryTest.scala
│   │                       ├── executions/
│   │                       │   └── SqlModuleTest.scala
│   │                       ├── history/
│   │                       │   ├── ExecutionMatchers.scala
│   │                       │   ├── FakeBuilder.scala
│   │                       │   ├── FakeClock.scala
│   │                       │   ├── HistoryBuilderTest.scala
│   │                       │   └── dao/
│   │                       │       ├── HistoryDaoContractTest.scala
│   │                       │       ├── InMemoryHistoryDaoTest.scala
│   │                       │       └── MySqlHistoryDaoTest.scala
│   │                       ├── results/
│   │                       │   └── MultiBuilderTest.scala
│   │                       └── sql/
│   │                           ├── PrestoSqlOpsTest.scala
│   │                           └── StopWordsSplitterTest.scala
│   ├── quix-modules/
│   │   ├── quix-athena-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── athena/
│   │   │       │               ├── AthenaAutocomplete.scala
│   │   │       │               ├── AthenaCatalogs.scala
│   │   │       │               ├── AthenaClient.scala
│   │   │       │               ├── AthenaConfig.scala
│   │   │       │               ├── AthenaQueryExecutor.scala
│   │   │       │               ├── AthenaTables.scala
│   │   │       │               ├── AwsAthenaClient.scala
│   │   │       │               └── TryAthena.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── athena/
│   │   │                       └── AthenaQueryExecutorTest.scala
│   │   ├── quix-bigquery-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── bigquery/
│   │   │       │               ├── BigQueryClient.scala
│   │   │       │               ├── BigQueryConfig.scala
│   │   │       │               ├── BigQueryQueryExecutor.scala
│   │   │       │               ├── BigQueryTestQueryExecutor.scala
│   │   │       │               ├── GoogleBigQueryClient.scala
│   │   │       │               ├── TryBigQuery.scala
│   │   │       │               └── db/
│   │   │       │                   ├── BigQueryAutocomplete.scala
│   │   │       │                   ├── BigQueryCatalogs.scala
│   │   │       │                   └── BigQueryTables.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── bigquery/
│   │   │                       └── BigQueryQueryExecutorTest.scala
│   │   ├── quix-dummy-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── dummy/
│   │   │       │               └── DummyQueryExecutor.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── dummy/
│   │   │                       └── DummyQueryExecutorTest.scala
│   │   ├── quix-jdbc-module/
│   │   │   └── src/
│   │   │       ├── it/
│   │   │       │   ├── resources/
│   │   │       │   │   └── db/
│   │   │       │   │       └── 001_init.sql
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── jdbc/
│   │   │       │               ├── EmbeddedMysqlDb.scala
│   │   │       │               ├── MysqlJdbcIntegrationTest.scala
│   │   │       │               ├── MysqlJdbcQueryExecutorIntegrationTest.scala
│   │   │       │               └── MysqlJdbcTablesIntegrationTest.scala
│   │   │       └── main/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── jdbc/
│   │   │                       ├── JdbcAutocomplete.scala
│   │   │                       ├── JdbcCatalogs.scala
│   │   │                       ├── JdbcQueryExecutor.scala
│   │   │                       └── JdbcTables.scala
│   │   ├── quix-presto-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── presto/
│   │   │       │               ├── PrestoConfig.scala
│   │   │       │               ├── QueryExecutor.scala
│   │   │       │               ├── TestQueryExecutor.scala
│   │   │       │               ├── TryPresto.scala
│   │   │       │               ├── db/
│   │   │       │               │   ├── PrestoAutocomplete.scala
│   │   │       │               │   ├── PrestoCatalogs.scala
│   │   │       │               │   └── PrestoTables.scala
│   │   │       │               └── rest/
│   │   │       │                   ├── PrestoRestApi.scala
│   │   │       │                   ├── PrestoStateClient.scala
│   │   │       │                   ├── ScalaJPrestoOps.scala
│   │   │       │                   └── ScalaJPrestoStateClient.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── presto/
│   │   │                       ├── QueryExecutorTest.scala
│   │   │                       ├── db/
│   │   │                       │   ├── PrestoAutocompleteTest.scala
│   │   │                       │   ├── PrestoCatalogsTest.scala
│   │   │                       │   └── PrestoTablesTest.scala
│   │   │                       └── rest/
│   │   │                           ├── ScalaJPrestoOpsTest.scala
│   │   │                           └── ScalaJPrestoStateClientTest.scala
│   │   └── quix-python-module/
│   │       └── src/
│   │           ├── main/
│   │           │   ├── resources/
│   │           │   │   ├── activator.py
│   │           │   │   ├── packages.py
│   │           │   │   └── quix.py
│   │           │   └── scala/
│   │           │       └── quix/
│   │           │           └── python/
│   │           │               ├── PythonApi.scala
│   │           │               ├── PythonBridge.scala
│   │           │               ├── PythonConfig.scala
│   │           │               ├── PythonExecutor.scala
│   │           │               ├── PythonModule.scala
│   │           │               ├── PythonProcessHandler.scala
│   │           │               ├── PythonRunningProcess.scala
│   │           │               └── TryPython.scala
│   │           └── test/
│   │               └── scala/
│   │                   └── quix/
│   │                       └── python/
│   │                           ├── PythonBridgeTest.scala
│   │                           └── PythonExecutorTest.scala
│   ├── quix-webapps/
│   │   └── quix-web-spring/
│   │       ├── pom.xml
│   │       └── src/
│   │           ├── main/
│   │           │   ├── resources/
│   │           │   │   ├── application.properties
│   │           │   │   └── logback-spring.xml
│   │           │   └── scala/
│   │           │       └── quix/
│   │           │           └── web/
│   │           │               ├── Server.scala
│   │           │               ├── auth/
│   │           │               │   ├── DemoUsers.scala
│   │           │               │   └── JwtUsers.scala
│   │           │               ├── controllers/
│   │           │               │   ├── DbController.scala
│   │           │               │   ├── DownloadController.scala
│   │           │               │   ├── HealthController.scala
│   │           │               │   ├── HistoryController.scala
│   │           │               │   └── SqlStreamingController.scala
│   │           │               └── spring/
│   │           │                   ├── HistoryDaoConfig.scala
│   │           │                   ├── SpringConfig.scala
│   │           │                   └── WebsocketsConfig.scala
│   │           └── test/
│   │               ├── resources/
│   │               │   ├── db/
│   │               │   │   └── 001_init.sql
│   │               │   ├── logback-test.xml
│   │               │   └── test.properties
│   │               └── scala/
│   │                   └── quix/
│   │                       └── web/
│   │                           ├── E2EContext.scala
│   │                           ├── SpringConfigWithTestExecutor.scala
│   │                           ├── auth/
│   │                           │   ├── DemoUsersTest.scala
│   │                           │   └── JwtUsersTest.scala
│   │                           └── controllers/
│   │                               ├── DownloadControllerTest.scala
│   │                               ├── EmbeddedMySql.scala
│   │                               ├── ExecutionEventTest.scala
│   │                               ├── HealthControllerTest.scala
│   │                               ├── HistoryControllerTest.scala
│   │                               ├── JdbcSqlStreamingControllerTest.scala
│   │                               ├── PrestoDbControllerTest.scala
│   │                               ├── PythonStreamingControllerTest.scala
│   │                               └── SqlStreamingControllerTest.scala
│   └── version.sbt
├── quix-frontend/
│   ├── .dockerignore
│   ├── .nvmrc
│   ├── Dockerfile
│   ├── README.md
│   ├── client/
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── .npmignore
│   │   ├── .npmrc
│   │   ├── .nvmrc
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.scss
│   │   │   ├── app.ts
│   │   │   ├── bootstrap.ts
│   │   │   ├── components/
│   │   │   │   ├── User/
│   │   │   │   │   ├── UserAvatar.tsx
│   │   │   │   │   └── UserAvatarAndName.tsx
│   │   │   │   ├── actions/
│   │   │   │   │   ├── actions-testkit.ts
│   │   │   │   │   ├── actions-types.ts
│   │   │   │   │   ├── actions.html
│   │   │   │   │   ├── actions.scss
│   │   │   │   │   └── actions.ts
│   │   │   │   ├── breadcrumbs/
│   │   │   │   │   ├── breadcrumbs-testkit.ts
│   │   │   │   │   ├── breadcrumbs-types.ts
│   │   │   │   │   ├── breadcrumbs.html
│   │   │   │   │   ├── breadcrumbs.scss
│   │   │   │   │   └── breadcrumbs.ts
│   │   │   │   ├── db-sidebar/
│   │   │   │   │   ├── db-sidebar-testkit.ts
│   │   │   │   │   ├── db-sidebar-types.ts
│   │   │   │   │   ├── db-sidebar.html
│   │   │   │   │   ├── db-sidebar.scss
│   │   │   │   │   └── db-sidebar.ts
│   │   │   │   ├── destination-picker/
│   │   │   │   │   ├── destination-picker-testkit.ts
│   │   │   │   │   ├── destination-picker-types.ts
│   │   │   │   │   ├── destination-picker.html
│   │   │   │   │   ├── destination-picker.scss
│   │   │   │   │   └── destination-picker.ts
│   │   │   │   ├── files-sidebar/
│   │   │   │   │   ├── files-sidebar-testkit.ts
│   │   │   │   │   ├── files-sidebar-types.ts
│   │   │   │   │   ├── files-sidebar.html
│   │   │   │   │   ├── files-sidebar.scss
│   │   │   │   │   └── files-sidebar.ts
│   │   │   │   ├── header/
│   │   │   │   │   ├── header-testkit.ts
│   │   │   │   │   ├── header-types.ts
│   │   │   │   │   ├── header.html
│   │   │   │   │   ├── header.scss
│   │   │   │   │   └── header.ts
│   │   │   │   ├── image/
│   │   │   │   │   ├── image-types.ts
│   │   │   │   │   ├── image.html
│   │   │   │   │   ├── image.scss
│   │   │   │   │   └── image.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── meta/
│   │   │   │   │   ├── meta-testkit.ts
│   │   │   │   │   ├── meta-types.ts
│   │   │   │   │   ├── meta.html
│   │   │   │   │   ├── meta.scss
│   │   │   │   │   └── meta.ts
│   │   │   │   ├── note/
│   │   │   │   │   ├── note-events.ts
│   │   │   │   │   ├── note-testkit.ts
│   │   │   │   │   ├── note-types.ts
│   │   │   │   │   ├── note.html
│   │   │   │   │   ├── note.scss
│   │   │   │   │   └── note.ts
│   │   │   │   ├── note-hints/
│   │   │   │   │   ├── note-hints.html
│   │   │   │   │   ├── note-hints.scss
│   │   │   │   │   └── note-hints.ts
│   │   │   │   ├── note-share/
│   │   │   │   │   ├── note-share-testkit.ts
│   │   │   │   │   ├── note-share-types.ts
│   │   │   │   │   ├── note-share.html
│   │   │   │   │   ├── note-share.scss
│   │   │   │   │   └── note-share.ts
│   │   │   │   ├── npc/
│   │   │   │   │   ├── npc.html
│   │   │   │   │   ├── npc.scss
│   │   │   │   │   └── npc.ts
│   │   │   │   ├── plugin-picker/
│   │   │   │   │   ├── plugin-picker-testkit.ts
│   │   │   │   │   ├── plugin-picker-types.ts
│   │   │   │   │   ├── plugin-picker.html
│   │   │   │   │   ├── plugin-picker.scss
│   │   │   │   │   └── plugin-picker.ts
│   │   │   │   ├── runner/
│   │   │   │   │   ├── runner-results-formatter.ts
│   │   │   │   │   ├── runner-testkit.ts
│   │   │   │   │   ├── runner-types.ts
│   │   │   │   │   ├── runner.html
│   │   │   │   │   ├── runner.scss
│   │   │   │   │   └── runner.ts
│   │   │   │   ├── search-results/
│   │   │   │   │   ├── search-results-testkit.ts
│   │   │   │   │   ├── search-results-types.ts
│   │   │   │   │   ├── search-results.html
│   │   │   │   │   ├── search-results.scss
│   │   │   │   │   └── search-results.ts
│   │   │   │   └── temp-query/
│   │   │   │       ├── temp-query-testkit.ts
│   │   │   │       ├── temp-query-types.ts
│   │   │   │       ├── temp-query.html
│   │   │   │       ├── temp-query.scss
│   │   │   │       └── temp-query.ts
│   │   │   ├── config.ts
│   │   │   ├── custom.d.ts
│   │   │   ├── data/
│   │   │   │   ├── examples-notebook.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── quix-folder.ts
│   │   │   ├── external-types.d.ts
│   │   │   ├── hooks.ts
│   │   │   ├── index.vm
│   │   │   ├── lib/
│   │   │   │   ├── app/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── constants.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   ├── app.html
│   │   │   │   │   │   │   ├── app.scss
│   │   │   │   │   │   │   └── app.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── login/
│   │   │   │   │   │       ├── login.html
│   │   │   │   │   │       ├── login.scss
│   │   │   │   │   │       └── login.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── app.ts
│   │   │   │   │   │   ├── appStoreProvider.tsx
│   │   │   │   │   │   ├── builder.ts
│   │   │   │   │   │   ├── navigator.ts
│   │   │   │   │   │   ├── plugin-builder.ts
│   │   │   │   │   │   ├── sso.ts
│   │   │   │   │   │   └── user.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── typings/
│   │   │   │   │   │   ├── story-builder.ts
│   │   │   │   │   │   ├── types.d.ts
│   │   │   │   │   │   └── window.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       └── scope-utils.ts
│   │   │   │   ├── code-editor/
│   │   │   │   │   ├── ace-extensions/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── language-tools.ts
│   │   │   │   │   │   ├── presto-snippets.ts
│   │   │   │   │   │   ├── presto.mode.ts
│   │   │   │   │   │   └── searchbox.ts
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── code-editor.html
│   │   │   │   │   │   ├── code-editor.scss
│   │   │   │   │   │   ├── code-editor.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   └── services/
│   │   │   │   │       ├── code-editor-annotator.ts
│   │   │   │   │       ├── code-editor-completer.ts
│   │   │   │   │       ├── code-editor-instance.ts
│   │   │   │   │       ├── code-editor-params.ts
│   │   │   │   │       ├── code-editor-selection.ts
│   │   │   │   │       ├── code-editor-service.ts
│   │   │   │   │       ├── code-editor-shortcuts.ts
│   │   │   │   │       └── param-parser/
│   │   │   │   │           ├── index.ts
│   │   │   │   │           ├── param-renderers/
│   │   │   │   │           │   ├── boolean-param-renderer.ts
│   │   │   │   │           │   ├── datetime-param-renderer.ts
│   │   │   │   │           │   ├── index.ts
│   │   │   │   │           │   ├── input-param-renderer.ts
│   │   │   │   │           │   ├── list-param-renderer.ts
│   │   │   │   │           │   ├── option-param-renderer.ts
│   │   │   │   │           │   └── textarea-param-renderer.ts
│   │   │   │   │           ├── param-serializers/
│   │   │   │   │           │   ├── default-param-serializer.ts
│   │   │   │   │           │   ├── index.ts
│   │   │   │   │           │   ├── param-serializer.ts
│   │   │   │   │           │   └── python-param-serializer.ts
│   │   │   │   │           ├── param-types.ts
│   │   │   │   │           ├── params-parser.ts
│   │   │   │   │           └── params-predefined-types.ts
│   │   │   │   ├── core/
│   │   │   │   │   ├── ang/
│   │   │   │   │   │   ├── drv/
│   │   │   │   │   │   │   ├── bi-options.drv.ts
│   │   │   │   │   │   │   └── bi-validator.drv.ts
│   │   │   │   │   │   └── srv/
│   │   │   │   │   │       ├── ng-model/
│   │   │   │   │   │       │   ├── ng-model-test.drv.ts
│   │   │   │   │   │       │   ├── ng-model.test.ts
│   │   │   │   │   │       │   └── ng-model.ts
│   │   │   │   │   │       └── scope/
│   │   │   │   │   │           ├── index.ts
│   │   │   │   │   │           ├── scope.test.ts
│   │   │   │   │   │           └── scope.ts
│   │   │   │   │   ├── config/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── main.angular.ts
│   │   │   │   │   ├── srv/
│   │   │   │   │   │   ├── collections/
│   │   │   │   │   │   │   ├── buffered-collection.test.ts
│   │   │   │   │   │   │   ├── buffered-collection.ts
│   │   │   │   │   │   │   ├── collection.test.ts
│   │   │   │   │   │   │   ├── collection.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── partitioned-collection.test.ts
│   │   │   │   │   │   │   └── partitioned-collection.ts
│   │   │   │   │   │   ├── event-emitter/
│   │   │   │   │   │   │   ├── event-emitter.test.ts
│   │   │   │   │   │   │   ├── event-emitter.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── injector/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── local-storage/
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── local-storage.test.ts
│   │   │   │   │   │   │   └── local-storage.ts
│   │   │   │   │   │   ├── model/
│   │   │   │   │   │   │   ├── model.test.ts
│   │   │   │   │   │   │   └── model.ts
│   │   │   │   │   │   ├── socket/
│   │   │   │   │   │   │   └── socket.ts
│   │   │   │   │   │   ├── state/
│   │   │   │   │   │   │   ├── localstorage-state-provider.test.ts
│   │   │   │   │   │   │   ├── localstorage-state-provider.ts
│   │   │   │   │   │   │   ├── state-wrapper.test.ts
│   │   │   │   │   │   │   ├── state-wrapper.ts
│   │   │   │   │   │   │   ├── state.test.ts
│   │   │   │   │   │   │   ├── state.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   ├── url-params.test.ts
│   │   │   │   │   │   │   ├── url-params.ts
│   │   │   │   │   │   │   ├── url-state-provider.test.ts
│   │   │   │   │   │   │   └── url-state-provider.ts
│   │   │   │   │   │   └── view-model/
│   │   │   │   │   │       ├── view-model.test.ts
│   │   │   │   │   │       └── view-model.ts
│   │   │   │   │   ├── types/
│   │   │   │   │   │   └── angular-promise.d.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── lodash4-polyfill.ts
│   │   │   │   │       ├── lodash4-polyfill.types.ts
│   │   │   │   │       ├── utils.test-prepare.ts
│   │   │   │   │       └── utils.test.ts
│   │   │   │   ├── file-explorer/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── file-explorer-dynamic.html
│   │   │   │   │   │   ├── file-explorer-static.html
│   │   │   │   │   │   ├── file-explorer-vm.ts
│   │   │   │   │   │   ├── file-explorer.scss
│   │   │   │   │   │   ├── file-explorer.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   └── services/
│   │   │   │   │       ├── file-explorer-controller.ts
│   │   │   │   │       ├── file-explorer-instance.ts
│   │   │   │   │       ├── file-explorer-models.ts
│   │   │   │   │       ├── file-explorer-tools.ts
│   │   │   │   │       └── index.ts
│   │   │   │   ├── language-parsers/
│   │   │   │   │   ├── presto-grammar/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── lang/
│   │   │   │   │   │       └── presto/
│   │   │   │   │   │           ├── SqlBase.tokens
│   │   │   │   │   │           ├── SqlBaseLexer.tokens
│   │   │   │   │   │           ├── SqlBaseLexer.ts
│   │   │   │   │   │           ├── SqlBaseListener.ts
│   │   │   │   │   │           ├── SqlBaseParser.ts
│   │   │   │   │   │           └── SqlBaseVisitor.ts
│   │   │   │   │   ├── python-grammar/
│   │   │   │   │   │   └── lang/
│   │   │   │   │   │       └── python/
│   │   │   │   │   │           ├── Python3Lexer.js
│   │   │   │   │   │           ├── Python3Lexer.tokens
│   │   │   │   │   │           ├── Python3Listener.js
│   │   │   │   │   │           ├── Python3Parser.js
│   │   │   │   │   │           ├── Python3Visitor.js
│   │   │   │   │   │           └── index.js
│   │   │   │   │   ├── python-parser/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── parser/
│   │   │   │   │   │   │   ├── errors-listener.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── parser.spec.ts
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   ├── tokenizer/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── types/
│   │   │   │   │   │   │   ├── 3rd-party.d.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── web-worker/
│   │   │   │   │   │       ├── types.ts
│   │   │   │   │   │       ├── web-worker-entry.ts
│   │   │   │   │   │       ├── web-worker-manager.ts
│   │   │   │   │   │       └── web-worker.ts
│   │   │   │   │   └── sql-parser/
│   │   │   │   │       ├── auto-format/
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── parser/
│   │   │   │   │       │   ├── errors-listener.ts
│   │   │   │   │       │   ├── index.ts
│   │   │   │   │       │   ├── parser.spec.ts
│   │   │   │   │       │   ├── presto-listener.ts
│   │   │   │   │       │   └── types.ts
│   │   │   │   │       ├── tokenizer/
│   │   │   │   │       │   ├── index.ts
│   │   │   │   │       │   ├── tokenizer.spec.ts
│   │   │   │   │       │   └── tokensMap.ts
│   │   │   │   │       ├── types/
│   │   │   │   │       │   ├── 3rd-party.d.ts
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       └── web-worker/
│   │   │   │   │           ├── types.ts
│   │   │   │   │           ├── web-worker-entry.ts
│   │   │   │   │           ├── web-worker-manager.ts
│   │   │   │   │           └── web-worker.ts
│   │   │   │   ├── runner/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── config/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── python-runner/
│   │   │   │   │   │   │   ├── python-runner-init.ts
│   │   │   │   │   │   │   ├── python-runner.html
│   │   │   │   │   │   │   ├── python-runner.scss
│   │   │   │   │   │   │   └── python-runner.ts
│   │   │   │   │   │   ├── results/
│   │   │   │   │   │   │   └── console/
│   │   │   │   │   │   │       ├── console-result-testkit.ts
│   │   │   │   │   │   │       ├── console-result.html
│   │   │   │   │   │   │       ├── console-result.scss
│   │   │   │   │   │   │       ├── console-result.ts
│   │   │   │   │   │   │       └── console-types.ts
│   │   │   │   │   │   ├── runner/
│   │   │   │   │   │   │   ├── runner.html
│   │   │   │   │   │   │   ├── runner.scss
│   │   │   │   │   │   │   └── runner.ts
│   │   │   │   │   │   └── sql-runner/
│   │   │   │   │   │       ├── sql-runner.html
│   │   │   │   │   │       ├── sql-runner.scss
│   │   │   │   │   │       └── sql-runner.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── autocomplete/
│   │   │   │   │   │   │   ├── autocomplete-service.ts
│   │   │   │   │   │   │   ├── autocomplete-utils.ts
│   │   │   │   │   │   │   ├── highlight-and-score.ts
│   │   │   │   │   │   │   └── old-autocomplete-service.ts
│   │   │   │   │   │   ├── db/
│   │   │   │   │   │   │   └── db-service.ts
│   │   │   │   │   │   ├── permissions/
│   │   │   │   │   │   │   └── permissions-service.ts
│   │   │   │   │   │   ├── runner-event.ts
│   │   │   │   │   │   ├── runner-events.ts
│   │   │   │   │   │   ├── runner-query.ts
│   │   │   │   │   │   ├── runner-service.ts
│   │   │   │   │   │   ├── runner-socket.ts
│   │   │   │   │   │   ├── runner-state.ts
│   │   │   │   │   │   ├── syntax-valdator/
│   │   │   │   │   │   │   └── syntax-validator-service.ts
│   │   │   │   │   │   └── workers/
│   │   │   │   │   │       ├── python-parser-worker.ts
│   │   │   │   │   │       └── sql-parser-worker.ts
│   │   │   │   │   └── typings/
│   │   │   │   │       ├── angular-promise.d.ts
│   │   │   │   │       ├── runner-types.ts
│   │   │   │   │       └── types.d.ts
│   │   │   │   ├── sql-autocomplete/
│   │   │   │   │   ├── adapter/
│   │   │   │   │   │   ├── sql-autocomplete-adapter-utills.ts
│   │   │   │   │   │   ├── sql-autocomplete-adapter.ts
│   │   │   │   │   │   ├── tests/
│   │   │   │   │   │   │   ├── get-completion-tests/
│   │   │   │   │   │   │   │   ├── expected-results.ts
│   │   │   │   │   │   │   │   ├── get-completion-Items.spec.ts
│   │   │   │   │   │   │   │   └── test-inputs/
│   │   │   │   │   │   │   │       ├── input-query-context.ts
│   │   │   │   │   │   │   │       └── input-table.ts
│   │   │   │   │   │   │   └── test-utils/
│   │   │   │   │   │   │       ├── mock-db-config.ts
│   │   │   │   │   │   │       ├── test-getCompletionItemsFromQueryContext.spec.ts
│   │   │   │   │   │   │       └── tests-utils.ts
│   │   │   │   │   │   ├── trinoToJs.spec.ts
│   │   │   │   │   │   ├── trinoToJs.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── db-info/
│   │   │   │   │   │   ├── db-info-service.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── languge/
│   │   │   │   │   │   └── reserved-words.ts
│   │   │   │   │   └── sql-context-evaluator/
│   │   │   │   │       ├── context-evaluator.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── position-evaluator.ts
│   │   │   │   │       ├── presto-context-listener.ts
│   │   │   │   │       ├── tests/
│   │   │   │   │       │   ├── queries-spec/
│   │   │   │   │       │   │   ├── basic-queries.spec.ts
│   │   │   │   │       │   │   ├── join-queries.spec.ts
│   │   │   │   │       │   │   ├── nested-queries.spec.ts
│   │   │   │   │       │   │   ├── union-queries.spec.ts
│   │   │   │   │       │   │   ├── utils.ts
│   │   │   │   │       │   │   └── with-queries.spec.ts
│   │   │   │   │       │   └── result-options/
│   │   │   │   │       │       ├── basic-results.ts
│   │   │   │   │       │       ├── nested-results.ts
│   │   │   │   │       │       ├── utils.ts
│   │   │   │   │       │       └── with-results.ts
│   │   │   │   │       ├── tree-analyzer.ts
│   │   │   │   │       ├── types.ts
│   │   │   │   │       ├── utils.ts
│   │   │   │   │       └── with-clause-analyzer.ts
│   │   │   │   ├── sql-formatter/
│   │   │   │   │   ├── LICENSE
│   │   │   │   │   ├── core/
│   │   │   │   │   │   ├── Formatter.ts
│   │   │   │   │   │   ├── Indentation.ts
│   │   │   │   │   │   ├── InlineBlock.ts
│   │   │   │   │   │   ├── Params.ts
│   │   │   │   │   │   ├── Tokenizer.ts
│   │   │   │   │   │   └── tokenTypes.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── languages/
│   │   │   │   │   │   ├── SqlWithQuixVarFormmater.ts
│   │   │   │   │   │   └── StandardSqlFormatter.ts
│   │   │   │   │   └── sqlFormatter.ts
│   │   │   │   ├── store/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── services/
│   │   │   │   │       ├── store-cache.ts
│   │   │   │   │       ├── store-logger.ts
│   │   │   │   │       └── store.ts
│   │   │   │   ├── ui/
│   │   │   │   │   ├── app.scss
│   │   │   │   │   ├── assets/
│   │   │   │   │   │   └── css/
│   │   │   │   │   │       ├── action.scss
│   │   │   │   │   │       ├── alert.scss
│   │   │   │   │   │       ├── align.scss
│   │   │   │   │   │       ├── animations.scss
│   │   │   │   │   │       ├── app/
│   │   │   │   │   │       │   ├── app-header.scss
│   │   │   │   │   │       │   └── app-menu.scss
│   │   │   │   │   │       ├── badge.scss
│   │   │   │   │   │       ├── border.scss
│   │   │   │   │   │       ├── button.scss
│   │   │   │   │   │       ├── caret.scss
│   │   │   │   │   │       ├── colors.scss
│   │   │   │   │   │       ├── def/
│   │   │   │   │   │       │   ├── action.def.scss
│   │   │   │   │   │       │   ├── alert.def.scss
│   │   │   │   │   │       │   ├── align.def.scss
│   │   │   │   │   │       │   ├── animations.def.scss
│   │   │   │   │   │       │   ├── app/
│   │   │   │   │   │       │   │   ├── app-header.def.scss
│   │   │   │   │   │       │   │   └── app-menu.def.scss
│   │   │   │   │   │       │   ├── badge.def.scss
│   │   │   │   │   │       │   ├── border.def.scss
│   │   │   │   │   │       │   ├── button.def.scss
│   │   │   │   │   │       │   ├── caret.def.scss
│   │   │   │   │   │       │   ├── colors.def.scss
│   │   │   │   │   │       │   ├── content.def.scss
│   │   │   │   │   │       │   ├── defaults.def.scss
│   │   │   │   │   │       │   ├── dropdown.def.scss
│   │   │   │   │   │       │   ├── empty-state.def.scss
│   │   │   │   │   │       │   ├── flex.def.scss
│   │   │   │   │   │       │   ├── header.def.scss
│   │   │   │   │   │       │   ├── heading.def.scss
│   │   │   │   │   │       │   ├── hint.def.scss
│   │   │   │   │   │       │   ├── icon.def.scss
│   │   │   │   │   │       │   ├── input.def.scss
│   │   │   │   │   │       │   ├── label.def.scss
│   │   │   │   │   │       │   ├── link.def.scss
│   │   │   │   │   │       │   ├── media.def.scss
│   │   │   │   │   │       │   ├── morph.def.scss
│   │   │   │   │   │       │   ├── nav-tabs.def.scss
│   │   │   │   │   │       │   ├── panel.def.scss
│   │   │   │   │   │       │   ├── section.def.scss
│   │   │   │   │   │       │   ├── space.def.scss
│   │   │   │   │   │       │   ├── spinner.def.scss
│   │   │   │   │   │       │   ├── state.def.scss
│   │   │   │   │   │       │   ├── table.def.scss
│   │   │   │   │   │       │   ├── tag.def.scss
│   │   │   │   │   │       │   ├── theme.def.scss
│   │   │   │   │   │       │   ├── toggle.def.scss
│   │   │   │   │   │       │   └── trim.def.scss
│   │   │   │   │   │       ├── dialog.scss
│   │   │   │   │   │       ├── dropdown.scss
│   │   │   │   │   │       ├── empty-state.scss
│   │   │   │   │   │       ├── flex.scss
│   │   │   │   │   │       ├── fonts.scss
│   │   │   │   │   │       ├── form.scss
│   │   │   │   │   │       ├── heading.scss
│   │   │   │   │   │       ├── hint.scss
│   │   │   │   │   │       ├── home-action.scss
│   │   │   │   │   │       ├── hover.scss
│   │   │   │   │   │       ├── icon.scss
│   │   │   │   │   │       ├── input.scss
│   │   │   │   │   │       ├── label.scss
│   │   │   │   │   │       ├── link.scss
│   │   │   │   │   │       ├── media.scss
│   │   │   │   │   │       ├── mouse.scss
│   │   │   │   │   │       ├── nav-tabs.scss
│   │   │   │   │   │       ├── no-select.scss
│   │   │   │   │   │       ├── panel.scss
│   │   │   │   │   │       ├── reset.scss
│   │   │   │   │   │       ├── scroll.scss
│   │   │   │   │   │       ├── section.scss
│   │   │   │   │   │       ├── space.scss
│   │   │   │   │   │       ├── spinner.scss
│   │   │   │   │   │       ├── state.scss
│   │   │   │   │   │       ├── table.scss
│   │   │   │   │   │       ├── tag.scss
│   │   │   │   │   │       ├── text.scss
│   │   │   │   │   │       ├── theme.scss
│   │   │   │   │   │       ├── toggle.scss
│   │   │   │   │   │       └── wrap.scss
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── Highlighter.tsx
│   │   │   │   │   │   ├── autocomplete/
│   │   │   │   │   │   │   ├── Autocomplete.tsx
│   │   │   │   │   │   │   └── autocomplete.hook.ts
│   │   │   │   │   │   ├── date-picker/
│   │   │   │   │   │   │   ├── DatePicker.tsx
│   │   │   │   │   │   │   ├── date-picker-utils.ts
│   │   │   │   │   │   │   └── date-picker.hook.ts
│   │   │   │   │   │   ├── dropdown/
│   │   │   │   │   │   │   ├── Dropdown.tsx
│   │   │   │   │   │   │   └── dropdown.scss
│   │   │   │   │   │   ├── hoc/
│   │   │   │   │   │   │   └── makePagination.tsx
│   │   │   │   │   │   ├── input/
│   │   │   │   │   │   │   ├── Input.tsx
│   │   │   │   │   │   │   └── input.scss
│   │   │   │   │   │   ├── panel/
│   │   │   │   │   │   │   └── Panel.tsx
│   │   │   │   │   │   ├── states/
│   │   │   │   │   │   │   ├── EmptyState.tsx
│   │   │   │   │   │   │   ├── ErrorState.tsx
│   │   │   │   │   │   │   ├── FilterInitialState.tsx
│   │   │   │   │   │   │   ├── InitialState.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── table/
│   │   │   │   │   │       ├── Table.scss
│   │   │   │   │   │       ├── Table.tsx
│   │   │   │   │   │       ├── TableRow.tsx
│   │   │   │   │   │       └── table-testkit.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── breadcrumbs/
│   │   │   │   │   │   │   ├── breadcrumbs.html
│   │   │   │   │   │   │   ├── breadcrumbs.scss
│   │   │   │   │   │   │   ├── breadcrumbs.story.ts
│   │   │   │   │   │   │   └── breadcrumbs.ts
│   │   │   │   │   │   ├── common/
│   │   │   │   │   │   │   └── dropdown-list.ts
│   │   │   │   │   │   ├── content-editable/
│   │   │   │   │   │   │   ├── content-editable.scss
│   │   │   │   │   │   │   └── content-editable.ts
│   │   │   │   │   │   ├── copy-to-clipboard/
│   │   │   │   │   │   │   ├── copy-to-clipboard.html
│   │   │   │   │   │   │   ├── copy-to-clipboard.scss
│   │   │   │   │   │   │   ├── copy-to-clipboard.story.ts
│   │   │   │   │   │   │   └── copy-to-clipboard.ts
│   │   │   │   │   │   ├── date-picker/
│   │   │   │   │   │   │   ├── date-picker.scss
│   │   │   │   │   │   │   ├── date-picker.story.ts
│   │   │   │   │   │   │   └── date-picker.ts
│   │   │   │   │   │   ├── draggable/
│   │   │   │   │   │   │   ├── draggable.story.ts
│   │   │   │   │   │   │   └── draggable.ts
│   │   │   │   │   │   ├── dropdown/
│   │   │   │   │   │   │   ├── dropdown.html
│   │   │   │   │   │   │   ├── dropdown.scss
│   │   │   │   │   │   │   ├── dropdown.story.ts
│   │   │   │   │   │   │   └── dropdown.ts
│   │   │   │   │   │   ├── droppable/
│   │   │   │   │   │   │   ├── droppable.story.ts
│   │   │   │   │   │   │   └── droppable.ts
│   │   │   │   │   │   ├── dual-action/
│   │   │   │   │   │   │   ├── dual-action.html
│   │   │   │   │   │   │   ├── dual-action.scss
│   │   │   │   │   │   │   └── dual-action.ts
│   │   │   │   │   │   ├── editable/
│   │   │   │   │   │   │   ├── editable.html
│   │   │   │   │   │   │   ├── editable.scss
│   │   │   │   │   │   │   ├── editable.story.ts
│   │   │   │   │   │   │   └── editable.ts
│   │   │   │   │   │   ├── filter/
│   │   │   │   │   │   │   ├── filter-items.ts
│   │   │   │   │   │   │   ├── filter-term.ts
│   │   │   │   │   │   │   ├── filter.story.ts
│   │   │   │   │   │   │   ├── filter.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── focus/
│   │   │   │   │   │   │   ├── focus-if.ts
│   │   │   │   │   │   │   ├── focus.story.ts
│   │   │   │   │   │   │   ├── focus.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── foldable/
│   │   │   │   │   │   │   ├── foldable.html
│   │   │   │   │   │   │   ├── foldable.scss
│   │   │   │   │   │   │   ├── foldable.story.ts
│   │   │   │   │   │   │   └── foldable.ts
│   │   │   │   │   │   ├── html/
│   │   │   │   │   │   │   └── html.ts
│   │   │   │   │   │   ├── icon-badge/
│   │   │   │   │   │   │   ├── icon-badge.html
│   │   │   │   │   │   │   ├── icon-badge.scss
│   │   │   │   │   │   │   └── icon-badge.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── infinite-scroll/
│   │   │   │   │   │   │   └── infinite-scroll.ts
│   │   │   │   │   │   ├── info/
│   │   │   │   │   │   │   ├── info.html
│   │   │   │   │   │   │   ├── info.scss
│   │   │   │   │   │   │   └── info.ts
│   │   │   │   │   │   ├── key-nav/
│   │   │   │   │   │   │   └── key-nav.ts
│   │   │   │   │   │   ├── maximizable/
│   │   │   │   │   │   │   ├── maximizable.scss
│   │   │   │   │   │   │   ├── maximizable.story.ts
│   │   │   │   │   │   │   └── maximizable.ts
│   │   │   │   │   │   ├── on-image-load/
│   │   │   │   │   │   │   └── on-image-load.ts
│   │   │   │   │   │   ├── progress-gauge/
│   │   │   │   │   │   │   ├── progress-gauge.html
│   │   │   │   │   │   │   ├── progress-gauge.scss
│   │   │   │   │   │   │   ├── progress-gauge.story.ts
│   │   │   │   │   │   │   └── progress-gauge.ts
│   │   │   │   │   │   ├── progress-line/
│   │   │   │   │   │   │   ├── progress-line.html
│   │   │   │   │   │   │   ├── progress-line.scss
│   │   │   │   │   │   │   └── progress-line.ts
│   │   │   │   │   │   ├── resizable/
│   │   │   │   │   │   │   └── resizable.ts
│   │   │   │   │   │   ├── scroll/
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── scroll-to.ts
│   │   │   │   │   │   ├── search/
│   │   │   │   │   │   │   ├── search.html
│   │   │   │   │   │   │   ├── search.scss
│   │   │   │   │   │   │   ├── search.story.ts
│   │   │   │   │   │   │   └── search.ts
│   │   │   │   │   │   ├── simple-select/
│   │   │   │   │   │   │   ├── simple-select.html
│   │   │   │   │   │   │   ├── simple-select.scss
│   │   │   │   │   │   │   ├── simple-select.story.ts
│   │   │   │   │   │   │   └── simple-select.ts
│   │   │   │   │   │   ├── state-loader/
│   │   │   │   │   │   │   ├── state-loader.scss
│   │   │   │   │   │   │   └── state-loader.ts
│   │   │   │   │   │   ├── table/
│   │   │   │   │   │   │   ├── header/
│   │   │   │   │   │   │   │   ├── table-header.html
│   │   │   │   │   │   │   │   ├── table-header.scss
│   │   │   │   │   │   │   │   └── table-header.ts
│   │   │   │   │   │   │   ├── row/
│   │   │   │   │   │   │   │   └── table-row.ts
│   │   │   │   │   │   │   ├── table.html
│   │   │   │   │   │   │   ├── table.scss
│   │   │   │   │   │   │   ├── table.story.ts
│   │   │   │   │   │   │   └── table.ts
│   │   │   │   │   │   ├── tabs/
│   │   │   │   │   │   │   ├── tabs-router.html
│   │   │   │   │   │   │   ├── tabs-router.ts
│   │   │   │   │   │   │   ├── tabs.html
│   │   │   │   │   │   │   ├── tabs.scss
│   │   │   │   │   │   │   ├── tabs.story.ts
│   │   │   │   │   │   │   └── tabs.ts
│   │   │   │   │   │   ├── tags/
│   │   │   │   │   │   │   ├── tags.html
│   │   │   │   │   │   │   ├── tags.scss
│   │   │   │   │   │   │   ├── tags.story.ts
│   │   │   │   │   │   │   └── tags.ts
│   │   │   │   │   │   └── tooltip/
│   │   │   │   │   │       ├── tooltip.html
│   │   │   │   │   │       ├── tooltip.scss
│   │   │   │   │   │       ├── tooltip.story.ts
│   │   │   │   │   │       └── tooltip.ts
│   │   │   │   │   ├── filters/
│   │   │   │   │   │   ├── absolute-date.ts
│   │   │   │   │   │   ├── date-utc.ts
│   │   │   │   │   │   ├── date.ts
│   │   │   │   │   │   ├── highlight.story.ts
│   │   │   │   │   │   ├── highlight.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── relative-date.ts
│   │   │   │   │   │   └── to-human-case.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── confirm.story.ts
│   │   │   │   │   │   ├── confirm.ts
│   │   │   │   │   │   ├── date.ts
│   │   │   │   │   │   ├── dialog-testkit.ts
│   │   │   │   │   │   ├── dialog.story.ts
│   │   │   │   │   │   ├── dialog.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── toast.scss
│   │   │   │   │   │   ├── toast.story.ts
│   │   │   │   │   │   └── toast.ts
│   │   │   │   │   ├── stories/
│   │   │   │   │   │   ├── action.story.ts
│   │   │   │   │   │   ├── alert.story.ts
│   │   │   │   │   │   ├── align.story.ts
│   │   │   │   │   │   ├── badge.story.ts
│   │   │   │   │   │   ├── border.story.ts
│   │   │   │   │   │   ├── button.story.ts
│   │   │   │   │   │   ├── colors.story.ts
│   │   │   │   │   │   ├── empty-state.story.ts
│   │   │   │   │   │   ├── flex.story.ts
│   │   │   │   │   │   ├── form.story.ts
│   │   │   │   │   │   ├── hint.story.ts
│   │   │   │   │   │   ├── home-action.story.ts
│   │   │   │   │   │   ├── input.story.ts
│   │   │   │   │   │   ├── label.story.ts
│   │   │   │   │   │   ├── media.story.ts
│   │   │   │   │   │   ├── scroll.story.ts
│   │   │   │   │   │   ├── space.story.ts
│   │   │   │   │   │   ├── spinner.story.ts
│   │   │   │   │   │   ├── tag.story.ts
│   │   │   │   │   │   └── text.story.ts
│   │   │   │   │   └── typings/
│   │   │   │   │       ├── globals.d.ts
│   │   │   │   │       ├── turnerjs.d.ts
│   │   │   │   │       └── types.d.ts
│   │   │   │   ├── viz/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── chart/
│   │   │   │   │   │   │   ├── chart-renderer.ts
│   │   │   │   │   │   │   ├── chart.html
│   │   │   │   │   │   │   ├── chart.scss
│   │   │   │   │   │   │   ├── chart.ts
│   │   │   │   │   │   │   └── filter/
│   │   │   │   │   │   │       ├── chart-filter.html
│   │   │   │   │   │   │       ├── chart-filter.scss
│   │   │   │   │   │   │       └── chart-filter.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── picker/
│   │   │   │   │   │   │   ├── picker.html
│   │   │   │   │   │   │   ├── picker.scss
│   │   │   │   │   │   │   └── picker.ts
│   │   │   │   │   │   ├── pie/
│   │   │   │   │   │   │   ├── filter/
│   │   │   │   │   │   │   │   ├── pie-filter.html
│   │   │   │   │   │   │   │   ├── pie-filter.scss
│   │   │   │   │   │   │   │   └── pie-filter.ts
│   │   │   │   │   │   │   ├── pie-renderer.ts
│   │   │   │   │   │   │   ├── pie.html
│   │   │   │   │   │   │   ├── pie.scss
│   │   │   │   │   │   │   └── pie.ts
│   │   │   │   │   │   ├── table/
│   │   │   │   │   │   │   ├── table-renderer.ts
│   │   │   │   │   │   │   ├── table.html
│   │   │   │   │   │   │   ├── table.scss
│   │   │   │   │   │   │   └── table.ts
│   │   │   │   │   │   ├── viz.html
│   │   │   │   │   │   ├── viz.scss
│   │   │   │   │   │   └── viz.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── chart/
│   │   │   │   │   │   │   ├── chart-conf.ts
│   │   │   │   │   │   │   ├── chart-data-service.ts
│   │   │   │   │   │   │   ├── chart-filter-service.ts
│   │   │   │   │   │   │   ├── chart-utils.ts
│   │   │   │   │   │   │   └── chart-viz-service.ts
│   │   │   │   │   │   ├── viz-conf.ts
│   │   │   │   │   │   ├── viz-data-service.ts
│   │   │   │   │   │   ├── viz-filter-service.ts
│   │   │   │   │   │   └── viz-service.ts
│   │   │   │   │   ├── transducers/
│   │   │   │   │   │   ├── chart/
│   │   │   │   │   │   │   ├── chart-input-filter-transducer.ts
│   │   │   │   │   │   │   ├── chart-meta-transducer.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── parse-dates-transducer.ts
│   │   │   │   │   │   ├── parse-floats-transducer.ts
│   │   │   │   │   │   ├── sort-transducer.ts
│   │   │   │   │   │   └── ungroup-transducer.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── utils.ts
│   │   │   │   └── web-worker-infra/
│   │   │   │       ├── types.ts
│   │   │   │       ├── web-worker/
│   │   │   │       │   └── index.ts
│   │   │   │       └── web-worker-manager/
│   │   │   │           └── index.ts
│   │   │   ├── plugins/
│   │   │   │   ├── db/
│   │   │   │   │   ├── athena-db-plugin.ts
│   │   │   │   │   ├── bigquery-db-plugin.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── jdbc-db-plugin.ts
│   │   │   │   │   └── presto-db-plugin.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── note/
│   │   │   │   │   ├── athena-note-plugin.ts
│   │   │   │   │   ├── bigquery-note-plugin.ts
│   │   │   │   │   ├── default-note-plugin.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── jdbc-note-plugin.ts
│   │   │   │   │   ├── presto-note-plugin.ts
│   │   │   │   │   └── python-note-plugin.ts
│   │   │   │   └── plugin-factory.ts
│   │   │   ├── react-components/
│   │   │   │   ├── file-explorer/
│   │   │   │   │   ├── FileExplorerComponent.scss
│   │   │   │   │   ├── FileExplorerComponent.tsx
│   │   │   │   │   ├── TreeItem.tsx
│   │   │   │   │   ├── TreeItemMenu.tsx
│   │   │   │   │   ├── file-explorer-testkit.ts
│   │   │   │   │   └── file-explorer.ts
│   │   │   │   └── index.ts
│   │   │   ├── services/
│   │   │   │   ├── db.ts
│   │   │   │   ├── dialog.ts
│   │   │   │   ├── files.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── use-view-state.ts
│   │   │   │   │   └── with-outside-click.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── notebook.ts
│   │   │   │   ├── notifications.ts
│   │   │   │   ├── permissions.ts
│   │   │   │   ├── plugins/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── plugin-manager.ts
│   │   │   │   │   └── plugin-types.ts
│   │   │   │   ├── popup.ts
│   │   │   │   ├── resources.ts
│   │   │   │   ├── runners.ts
│   │   │   │   ├── scope.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── state.ts
│   │   │   │   └── subscription.ts
│   │   │   ├── state-components/
│   │   │   │   ├── base/
│   │   │   │   │   ├── base.html
│   │   │   │   │   └── base.ts
│   │   │   │   ├── embed/
│   │   │   │   │   ├── embed.ts
│   │   │   │   │   └── note/
│   │   │   │   │       ├── embed-note-events.ts
│   │   │   │   │       ├── embed-note-reactions.ts
│   │   │   │   │       ├── embed-note-scope.ts
│   │   │   │   │       ├── embed-note-url.ts
│   │   │   │   │       ├── embed-note-vm.ts
│   │   │   │   │       ├── embed-note.html
│   │   │   │   │       ├── embed-note.scss
│   │   │   │   │       └── embed-note.ts
│   │   │   │   ├── favorites/
│   │   │   │   │   ├── FavoritesComponent.tsx
│   │   │   │   │   ├── favorites-events.ts
│   │   │   │   │   ├── favorites-table-fields.tsx
│   │   │   │   │   ├── favorites-testkit.ts
│   │   │   │   │   ├── favorites.scss
│   │   │   │   │   └── favorites.ts
│   │   │   │   ├── files/
│   │   │   │   │   ├── files-events.ts
│   │   │   │   │   ├── files-reactions.ts
│   │   │   │   │   ├── files-scope.ts
│   │   │   │   │   ├── files-table-fields.ts
│   │   │   │   │   ├── files-testkit.ts
│   │   │   │   │   ├── files-types.ts
│   │   │   │   │   ├── files-url.ts
│   │   │   │   │   ├── files-vm.ts
│   │   │   │   │   ├── files.html
│   │   │   │   │   ├── files.scss
│   │   │   │   │   └── files.ts
│   │   │   │   ├── history/
│   │   │   │   │   ├── HistoryComponent.scss
│   │   │   │   │   ├── HistoryComponent.tsx
│   │   │   │   │   ├── history-events.ts
│   │   │   │   │   ├── history-table-fields.tsx
│   │   │   │   │   ├── history-testkit.ts
│   │   │   │   │   └── history.ts
│   │   │   │   ├── home/
│   │   │   │   │   ├── HomeComponent.tsx
│   │   │   │   │   ├── home-testkit.ts
│   │   │   │   │   ├── home.scss
│   │   │   │   │   └── home.ts
│   │   │   │   ├── import/
│   │   │   │   │   ├── import.html
│   │   │   │   │   └── import.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── notebook/
│   │   │   │   │   ├── notebook-events.ts
│   │   │   │   │   ├── notebook-reactions.ts
│   │   │   │   │   ├── notebook-scope.ts
│   │   │   │   │   ├── notebook-testkit.ts
│   │   │   │   │   ├── notebook-types.ts
│   │   │   │   │   ├── notebook-url.ts
│   │   │   │   │   ├── notebook-vm.ts
│   │   │   │   │   ├── notebook.html
│   │   │   │   │   ├── notebook.scss
│   │   │   │   │   └── notebook.ts
│   │   │   │   ├── trash-bin/
│   │   │   │   │   ├── TrashBinComponent.tsx
│   │   │   │   │   ├── trash-bin-events.ts
│   │   │   │   │   ├── trash-bin-table-fields.tsx
│   │   │   │   │   └── trash-bin.ts
│   │   │   │   └── users/
│   │   │   │       ├── UsersComponent.tsx
│   │   │   │       ├── users-events.ts
│   │   │   │       ├── users-table-fields.tsx
│   │   │   │       ├── users-testkit.ts
│   │   │   │       ├── users.scss
│   │   │   │       └── users.ts
│   │   │   ├── store/
│   │   │   │   ├── app/
│   │   │   │   │   ├── app-actions.ts
│   │   │   │   │   └── app-branch.ts
│   │   │   │   ├── db/
│   │   │   │   │   ├── db-actions.ts
│   │   │   │   │   ├── db-branch.ts
│   │   │   │   │   └── db-cache.ts
│   │   │   │   ├── deleted-notebook/
│   │   │   │   │   ├── deleted-notebook-actions.ts
│   │   │   │   │   ├── deleted-notebook-branch.ts
│   │   │   │   │   └── deleted-notebook-cache.ts
│   │   │   │   ├── favorites/
│   │   │   │   │   ├── favorites-actions.ts
│   │   │   │   │   ├── favorites-branch.ts
│   │   │   │   │   └── favorites-cache.ts
│   │   │   │   ├── files/
│   │   │   │   │   ├── files-actions.ts
│   │   │   │   │   ├── files-branch.ts
│   │   │   │   │   └── files-cache.ts
│   │   │   │   ├── folder/
│   │   │   │   │   ├── folder-actions.ts
│   │   │   │   │   ├── folder-branch.ts
│   │   │   │   │   └── folder-cache.ts
│   │   │   │   ├── history/
│   │   │   │   │   ├── history-actions.ts
│   │   │   │   │   ├── history-branch.ts
│   │   │   │   │   └── history-cache.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── notebook/
│   │   │   │   │   ├── notebook-actions.ts
│   │   │   │   │   ├── notebook-branch.ts
│   │   │   │   │   └── notebook-cache.ts
│   │   │   │   └── users/
│   │   │   │       ├── users-actions.ts
│   │   │   │       ├── users-branch.ts
│   │   │   │       └── users-cache.ts
│   │   │   ├── types.ts
│   │   │   └── utils.ts
│   │   ├── test/
│   │   │   ├── dev/
│   │   │   │   ├── localhost.crt
│   │   │   │   ├── localhost.key
│   │   │   │   ├── server.ts
│   │   │   │   ├── vm.ts
│   │   │   │   └── websocket-mock.ts
│   │   │   ├── e2e/
│   │   │   │   ├── dbExplorer.e2e.ts
│   │   │   │   ├── driver.ts
│   │   │   │   ├── e2e-common.ts
│   │   │   │   ├── favorites.e2e.ts
│   │   │   │   ├── files.e2e.ts
│   │   │   │   ├── history.e2e.ts
│   │   │   │   ├── home.e2e.ts
│   │   │   │   ├── notebook.e2e.ts
│   │   │   │   └── users.e2e.ts
│   │   │   ├── mocha-setup.ts
│   │   │   ├── mocks.ts
│   │   │   └── test-common.ts
│   │   ├── tsconfig.json
│   │   ├── tslint.json
│   │   ├── velocity.data.json
│   │   ├── velocity.private.data.json
│   │   └── wallaby.js
│   ├── lerna.json
│   ├── npm-deploy.sh
│   ├── package.json
│   ├── service/
│   │   ├── .gitignore
│   │   ├── .npmrc
│   │   ├── .nvmrc
│   │   ├── .prettierrc
│   │   ├── .quixroot
│   │   ├── .testenv
│   │   ├── .travis.yml
│   │   ├── README.md
│   │   ├── ecosystem.config.js
│   │   ├── index.js
│   │   ├── nest-cli.json
│   │   ├── nodemon-debug.json
│   │   ├── nodemon.json
│   │   ├── ormconfig.json
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   ├── create_migrations.sh
│   │   │   ├── helpers/
│   │   │   │   └── copy-statics.ts
│   │   │   ├── ormconfig.json.template
│   │   │   ├── run_migrations.sh
│   │   │   ├── start.ts
│   │   │   └── update-statics.ts
│   │   ├── src/
│   │   │   ├── app.controller.spec.ts
│   │   │   ├── app.controller.ts
│   │   │   ├── app.module.ts
│   │   │   ├── base.module.ts
│   │   │   ├── common/
│   │   │   │   ├── demo-mode-interceptor.ts
│   │   │   │   ├── entity-type.enum.ts
│   │   │   │   └── user-sanitizer.ts
│   │   │   ├── config/
│   │   │   │   ├── config.module.ts
│   │   │   │   ├── config.service.ts
│   │   │   │   ├── db-conf.ts
│   │   │   │   ├── db-connection.ts
│   │   │   │   ├── env/
│   │   │   │   │   ├── computed-settings.ts
│   │   │   │   │   ├── engine-settings.ts
│   │   │   │   │   ├── env.spec.ts
│   │   │   │   │   ├── env.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── static-settings.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── utils.ts
│   │   │   ├── consts.ts
│   │   │   ├── entities/
│   │   │   │   ├── deleted-notebook/
│   │   │   │   │   ├── dbdeleted-notebook.entity.ts
│   │   │   │   │   └── deleted-notebook.repository.ts
│   │   │   │   ├── favorites/
│   │   │   │   │   └── favorites.entity.ts
│   │   │   │   ├── filenode/
│   │   │   │   │   ├── filenode.entity.ts
│   │   │   │   │   └── filenode.repository.ts
│   │   │   │   ├── folder/
│   │   │   │   │   └── folder.entity.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── note/
│   │   │   │   │   ├── dbnote.entity.ts
│   │   │   │   │   └── note.repository.ts
│   │   │   │   ├── notebook/
│   │   │   │   │   ├── dbnotebook.entity.ts
│   │   │   │   │   └── notebook.repository.ts
│   │   │   │   ├── user/
│   │   │   │   │   └── user.entity.ts
│   │   │   │   ├── utils.ts
│   │   │   │   └── version-metadata.entity.ts
│   │   │   ├── errors/
│   │   │   │   ├── exceptions.ts
│   │   │   │   └── index.ts
│   │   │   ├── main.ts
│   │   │   ├── migrations/
│   │   │   │   ├── 1558528771647-v1.ts
│   │   │   │   ├── 1558528771648-v1-metadata.ts
│   │   │   │   ├── 1562174176877-v2.ts
│   │   │   │   ├── 1614173960671-v3.ts
│   │   │   │   ├── 1614712161318-v4.ts
│   │   │   │   └── 1634023683491-v5.ts
│   │   │   ├── modules/
│   │   │   │   ├── auth/
│   │   │   │   │   ├── auth.controller.ts
│   │   │   │   │   ├── auth.module.ts
│   │   │   │   │   ├── common-auth.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── login.service.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── user-decorator.ts
│   │   │   │   │   └── users.service.ts
│   │   │   │   ├── event-sourcing/
│   │   │   │   │   ├── base-action-validation.ts
│   │   │   │   │   ├── event-sourcing.module.ts
│   │   │   │   │   ├── events.service.ts
│   │   │   │   │   ├── infrastructure/
│   │   │   │   │   │   ├── action-store/
│   │   │   │   │   │   │   ├── action-store.spec.ts
│   │   │   │   │   │   │   ├── action-store.ts
│   │   │   │   │   │   │   ├── entities/
│   │   │   │   │   │   │   │   └── db-action.entity.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   ├── event-bus/
│   │   │   │   │   │   │   ├── api.ts
│   │   │   │   │   │   │   ├── context.ts
│   │   │   │   │   │   │   ├── event-bus-builder.ts
│   │   │   │   │   │   │   ├── event-bus.drawio
│   │   │   │   │   │   │   ├── event-bus.spec.ts
│   │   │   │   │   │   │   ├── event-bus.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── plugins/
│   │   │   │   │   │   ├── deleted-notebook-plugin.ts
│   │   │   │   │   │   ├── events-plugin.ts
│   │   │   │   │   │   ├── favorites-plugin.ts
│   │   │   │   │   │   ├── file-tree-plugin.ts
│   │   │   │   │   │   ├── note-plugin.ts
│   │   │   │   │   │   ├── notebook-plugin.ts
│   │   │   │   │   │   ├── trash-bin-plugin.ts
│   │   │   │   │   │   ├── user-plugin.ts
│   │   │   │   │   │   └── utils.ts
│   │   │   │   │   ├── quix-event-bus.driver.ts
│   │   │   │   │   ├── quix-event-bus.spec.ts
│   │   │   │   │   ├── quix-event-bus.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── logger/
│   │   │   │   │   ├── logger.module.ts
│   │   │   │   │   └── logger.service.ts
│   │   │   │   ├── proxy-backend/
│   │   │   │   │   └── proxy-backend.module.ts
│   │   │   │   ├── search/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── parser.spec.ts
│   │   │   │   │   ├── parser.ts
│   │   │   │   │   ├── search.module.ts
│   │   │   │   │   ├── search.spec.ts
│   │   │   │   │   ├── search.ts
│   │   │   │   │   └── types.ts
│   │   │   │   └── web-api/
│   │   │   │       ├── autocomplete/
│   │   │   │       │   ├── autocomplete.controller.ts
│   │   │   │       │   └── autocomplete.service.ts
│   │   │   │       ├── deleted-notebooks/
│   │   │   │       │   ├── deleted-notebook.controller.ts
│   │   │   │       │   └── deleted-notebook.service.ts
│   │   │   │       ├── events.controller.ts
│   │   │   │       ├── events.gateway.ts
│   │   │   │       ├── favorites/
│   │   │   │       │   ├── favorites.controller.ts
│   │   │   │       │   └── favorites.service.ts
│   │   │   │       ├── folders/
│   │   │   │       │   ├── folders.controller.ts
│   │   │   │       │   ├── folders.service.ts
│   │   │   │       │   └── utils.ts
│   │   │   │       ├── notebooks/
│   │   │   │       │   ├── notebooks.controller.ts
│   │   │   │       │   └── notebooks.service.ts
│   │   │   │       ├── search.controller.ts
│   │   │   │       ├── user-list.controller.ts
│   │   │   │       ├── web-api.driver.ts
│   │   │   │       ├── web-api.module.ts
│   │   │   │       └── web-api.spec.ts
│   │   │   ├── template-engine/
│   │   │   │   └── velocity.ts
│   │   │   ├── types/
│   │   │   │   ├── 3rd-party/
│   │   │   │   │   ├── uuid.d.ts
│   │   │   │   │   └── velocity.d.ts
│   │   │   │   └── index.ts
│   │   │   └── utils/
│   │   │       ├── create-schema-helpers.ts
│   │   │       ├── deferred-promise.ts
│   │   │       └── retry-promise.ts
│   │   ├── test/
│   │   │   ├── app.e2e-spec.ts
│   │   │   ├── builder.ts
│   │   │   ├── custom-matchers.ts
│   │   │   ├── driver.ts
│   │   │   └── jest-e2e.js
│   │   ├── tsconfig.build.json
│   │   ├── tsconfig.json
│   │   └── tslint.json
│   └── shared/
│       ├── .gitignore
│       ├── config-helper/
│       │   ├── config-helper.ts
│       │   └── consts.ts
│       ├── entities/
│       │   ├── common/
│       │   │   ├── actions.ts
│       │   │   ├── common-types.ts
│       │   │   ├── create-reducer.spec.ts
│       │   │   └── create-reducer.ts
│       │   ├── deleted-notebook/
│       │   │   ├── actions.ts
│       │   │   ├── deleted-notebook.ts
│       │   │   ├── index.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── file/
│       │   │   ├── actions.ts
│       │   │   ├── file.ts
│       │   │   ├── index.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── folder/
│       │   │   ├── folder.ts
│       │   │   ├── index.ts
│       │   │   └── types.ts
│       │   ├── history/
│       │   │   ├── actions.ts
│       │   │   ├── history.ts
│       │   │   ├── index.ts
│       │   │   └── types.ts
│       │   ├── note/
│       │   │   ├── actions.ts
│       │   │   ├── index.ts
│       │   │   ├── note.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── notebook/
│       │   │   ├── actions.ts
│       │   │   ├── index.ts
│       │   │   ├── notebook.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── trash-bin/
│       │   │   ├── actions.ts
│       │   │   ├── index.ts
│       │   │   └── types.ts
│       │   └── user/
│       │       ├── actions.ts
│       │       ├── index.ts
│       │       ├── types.ts
│       │       └── user.ts
│       ├── index.ts
│       ├── package.json
│       ├── tsconfig.json
│       ├── types/
│       │   └── search-types.ts
│       └── utils/
│           └── utils.ts
└── terraform/
    ├── README.md
    ├── acme_certificate.tf
    ├── aws-tf-backend.tf
    ├── ecs.tf
    ├── iam.tf
    ├── initialize.tf
    ├── lb.tf
    ├── outputs.tf
    ├── parameter_store.tf
    ├── provider.tf
    ├── rds.tf
    ├── route_53.tf
    ├── security_groups.tf
    ├── variables.tf
    ├── versions.tf
    └── vpc.tf

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
*/node_modules
*.log


================================================
FILE: .github/workflows/quix-backend-build.yml
================================================
name: Quix Backend Build
on:
  pull_request:
    paths:
    - 'quix-backend/**'  
  push:
    paths:
    - 'quix-backend/**'
  workflow_dispatch:
jobs:
  scala_tests:
    runs-on: ubuntu-20.04
    strategy:
      matrix:
        scala_version: ['2.12.17', '2.13.9']
    steps:
    - name: Checkout
      uses: actions/checkout@v1
    - name: Setup Scala
      uses: olafurpg/setup-scala@v12
      with:
        java-version: "adopt@1.8"
    - name: Coursier cache
      uses: coursier/cache-action@v5
    - name: Build and Test
      working-directory: ./quix-backend
      run: |
        sbt ++${{matrix.scala_version}} -v -Dfile.encoding=UTF-8 test publishM2
        if [[ ${{matrix.scala_version}} = '2.12.17' ]]
        then
          mvn --quiet -f quix-webapps/quix-web-spring/pom.xml test
        fi
        rm -rf "$HOME/.ivy2/local" || true
        find $HOME/Library/Caches/Coursier/v1        -name "ivydata-*.properties" -delete || true
        find $HOME/.ivy2/cache                       -name "ivydata-*.properties" -delete || true
        find $HOME/.cache/coursier/v1                -name "ivydata-*.properties" -delete || true
        find $HOME/.sbt                              -name "*.lock"               -delete || true


================================================
FILE: .github/workflows/quix-documentation-publish.yml
================================================
# This Workflow will publish Documentation on any push to master branch into 
# the documentation folder.
name: Quix Documentation Publish
on:
  workflow_dispatch:
    inputs:
      comment:
        description: 'Comment'     
        required: true
        default: 'Publish'
  push:
    branches: ['master']
    paths:
    - 'documentation/**/*.*'

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v2
      with:
        node-version: '14.19.1'
    - run: npm install
      working-directory: 'documentation/website'
    - run: npm run build
      working-directory: 'documentation/website'
    - name: Deploy
      if: success()
      uses: crazy-max/ghaction-github-pages@v2
      with:
        target_branch: gh-pages
        build_dir: documentation/website/build/quix
      env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

================================================
FILE: .github/workflows/quix-frontend-publish.yml
================================================
# Build on each branch and Publish to NPM on master if version bumped
name: Quix Frontend Build & Publish
on:
  workflow_dispatch:
    inputs:
      comment:
        description: 'Comment'     
        required: true
        default: 'Publish'
  push:
    paths:
    - 'quix-frontend/**'
defaults:
  run:
    working-directory: quix-frontend
jobs:
  build_and_test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-node@v2
        with:
          node-version: '14.19.1'
      - uses: samin/mysql-action@v1.3
        with:
          mysql database: 'quixtest'
          mysql version: '5.7'
      
      - run: npm ci
      - run: npm run build:ci
      - run: npm test

      - name: Prepare Publish To NPM
        if: github.ref == 'refs/heads/master'
        run: |
          echo "registry=http://registry.npmjs.org/" >> .npmrc
          echo "//registry.npmjs.org/:_authToken=$NPM_TOKEN" >> .npmrc
        env: 
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
      
      - name: Publish
        if: github.ref == 'refs/heads/master'
        run: npm run publish
        env: 
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}


================================================
FILE: .github/workflows/quix-frontend-release.yml
================================================
name: Quix Frontend Release DockerHub

on:
  workflow_dispatch:
    inputs:
      comment:
        description: 'Comment'     
        required: true
        default: 'Release'
      tags:
        description: 'Tags'
      labels:
        description: 'Labels'
        
  release:
    types: [published]

defaults:
  run:
    working-directory: quix-frontend

jobs:
  push_to_registry:
    name: Push Docker image to Docker Hub
    runs-on: ubuntu-latest
    steps:
      - name: Check out the repo
        uses: actions/checkout@v2
      
      - name: Log in to Docker Hub
        uses: docker/login-action@f054a8b539a109f9f41c372932f1ae047eff08c9
        with:
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}
      
      - name: Extract metadata (tags, labels) for Docker
        id: meta
        uses: docker/metadata-action@98669ae865ea3cffbcbaa878cf57c20bbf1c6c38
        with:
          images: wixquix/quix-frontend
          
      - name: Log
        run: |
          echo "${{ steps.meta.outputs.tags }} ${{ steps.meta.outputs.labels }}" \
          && echo "${{github.event.inputs.tags}}" \
          && echo "${{github.event.inputs.labels}}" 
      
      - name: Build and push Docker image
        uses: docker/build-push-action@ad44023a93711e3deb337508980b4b5e9bcdc5dc
        with:
          context: ./quix-frontend/
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}


================================================
FILE: .gitignore
================================================
# Created by https://www.gitignore.io/api/maven,scala,jetbrains

### Maven ###
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties


### Scala ###
*.class
*.log

# sbt specific
.cache
.history
.lib/
dist/*
target/
lib_managed/
src_managed/
project/boot/
project/plugins/project/

# Scala-IDE specific
.scala_dependencies
.worksheet


### JetBrains ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio

*.iml

## Directory-based project format:
.idea/
# if you remove the above rule, at least ignore the following:

# User-specific stuff:
# .idea/workspace.xml
# .idea/tasks.xml
# .idea/dictionaries

# Sensitive or high-churn files:
# .idea/dataSources.ids
# .idea/dataSources.xml
# .idea/sqlDataSources.xml
# .idea/dynamic.xml
# .idea/uiDesigner.xml

# Gradle:
# .idea/gradle.xml
# .idea/libraries

# Mongo Explorer plugin:
# .idea/mongoSettings.xml

## File-based project format:
*.ipr
*.iws

## Plugin-specific files:

# IntelliJ
/out/

# mpeltonen/sbt-idea plugin
.idea_modules/

# JIRA plugin
atlassian-ide-plugin.xml

# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties

.DS_Store
.vscode
node_modules

.env


## Terraform
*.tfstate
*.tfstate.backup
.terraform
vpc.plan
terraform.tfvars

quix-frontend/.npmrc
documentation/website/build/

================================================
FILE: .travis.yml
================================================
jobs:
  include:
    - stage: test
      name: "Frontend"
      language: node_js
      dist: bionic
      node_js: 14
      cache: npm
      env: PROJECT=frontend
      services:
        - mysql
      before_install:
        - mysql -e 'CREATE DATABASE IF NOT EXISTS quixtest;'
      install:
        - $TRAVIS_BUILD_DIR/build-selector.sh $TRAVIS_COMMIT_RANGE $PROJECT || exit 0
        - cd ./quix-frontend
        - npm install
      script:
        - $TRAVIS_BUILD_DIR/build-selector.sh $TRAVIS_COMMIT_RANGE $PROJECT || exit 0
        - npm run build:ci
        - npm run test
      deploy:
        provider: script
        script: bash npm-deploy.sh
        edge: true
        on:
          branch: master


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2019 Wix Incubator

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# Quix
![Support](https://img.shields.io/npm/l/@wix/quix-client) [![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.wix/quix-api_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.wix/quix-api_2.13)

[![Quix Backend Build](https://github.com/wix-incubator/quix/actions/workflows/quix-backend-build.yml/badge.svg?branch=master)](https://github.com/wix-incubator/quix/actions/workflows/quix-backend-build.yml)
[![Quix Frontend Build & Publish](https://github.com/wix-incubator/quix/actions/workflows/quix-frontend-publish.yml/badge.svg)](https://github.com/wix-incubator/quix/actions/workflows/quix-frontend-publish.yml) [![Quix Documentation Publish](https://github.com/wix-incubator/quix/actions/workflows/quix-documentation-publish.yml/badge.svg)](https://github.com/wix-incubator/quix/actions/workflows/quix-documentation-publish.yml)

Quix is an easy-to-use notebook manager with support for [Presto](https://wix-incubator.github.io/quix/docs/presto), [Athena](https://wix-incubator.github.io/quix/docs/athena), [BigQuery](https://wix-incubator.github.io/quix/docs/bigquery), [MySQL](https://wix-incubator.github.io/quix/docs/mysql), [PostgreSQL](https://wix-incubator.github.io/quix/docs/postgresql), [ClickHouse](https://wix-incubator.github.io/quix/docs/clickhouse) and more.

* [Installation](https://wix-incubator.github.io/quix/docs/installation)

## Intro
Check out these blog posts introducing Quix on Wix Engineering Blog : 
* [Introducing Quix: Presto-based Notebook Manager for Fast and Easy Data Exploration ](https://www.wix.engineering/post/introducing-quix-presto-based-notebook-manager-for-fast-and-easy-data-exploration)
* [Quix Version 1: Now also Supporting Amazon Athena, Google BigQuery and Generic JDBC](https://www.wix.engineering/post/quix-version-1-now-also-supporting-amazon-athena-google-bigquery-and-generic-jdbc)

## Quick start
Using `docker-compose`, this will run Quix with a MySQL container and an example Presto installation. Quix will run in a single-user mode without authentication. 

```bash
mkdir quix && cd quix
curl https://raw.githubusercontent.com/wix/quix/master/docker-compose.prebuilt.yml -o docker-compose.yml
curl https://raw.githubusercontent.com/wix/quix/master/env-example -o .env
docker-compose up
```

Be sure to check the [full installation notes](https://wix-incubator.github.io/quix/docs/installation) on how to edit the `.env` file to add more data sources, turn on multi-user mode and customize your deployment.

For support please contact us via [oss@wix.com](mailto:oss@wix.com).

## Main features
- [Query management](#Management) - organize your notebooks in folders for easy access and sharing
- [Visualizations](#Visualizations) - quickly plot time and bar series (more visualizations to follow)
- [DB Explorer](#Explorer) - explore your data sources
- Search - search notes of all users

#### Management
![](documentation/docs/assets/management.gif)

#### Visualizations
![](documentation/docs/assets/chart.gif)

#### Explorer
![](documentation/docs/assets/db.gif)

## License
MIT


================================================
FILE: build-selector.sh
================================================
#!/usr/bin/env bash

if [ -z $2 ]; then
  GIT_RANGE="HEAD^1"
  BUILD_TYPE=$1
else
  GIT_RANGE="$1"
  BUILD_TYPE="$2"
fi

echo GIT RANGE=$GIT_RANGE
echo BUILD_TYPE=$BUILD_TYPE

declare -A PATTERN_MAP

PATTERN_MAP[frontend]='^((quix-frontend/)|\.travis\.yml)'
PATTERN_MAP[backend]='^(quix-backend/|\.travis\.yml)'


git diff --name-only $GIT_RANGE | grep -qE ${PATTERN_MAP[$BUILD_TYPE]}

================================================
FILE: docker-compose.prebuilt.yml
================================================
version: '3'
services:
  backend:
    image: wixquix/quix-backend:latest
    ports:
      - "8081:8081"
    depends_on:
      - presto
    env_file:
      - .env
    environment:
      - MODULES
      - AUTH_COOKIE
      - AUTH_SECRET
      - AUTH_TYPE
  frontend:
    image: wixquix/quix-frontend:latest
    ports:
      - "3000:3000"
    depends_on:
      - backend
      - db
    env_file:
      - .env
    environment:
      - DB_NAME
      - DB_USER
      - DB_PASS
      - DB_HOST
      - DB_PORT
      - BACKEND_INTERNAL_URL
      - BACKEND_PUBLIC_URL
      - GOOGLE_SSO_CLIENT_ID
      - GOOGLE_SSO_SECRET
      - AUTH_COOKIE
      - AUTH_SECRET
      - AUTH_TYPE
      - APPMETRICS_PORT
      - ENABLE_APPMETRICS
      - MODULES
  db:
    image: "mysql:5.7"
    restart: always
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      MYSQL_DATABASE: "quix"
    volumes:
      - "db_volume:/var/lib/mysql"
  presto:
    image: "starburstdata/presto:340-e"
    ports:
      - "8181:8080"

volumes:
  db_volume:


================================================
FILE: docker-compose.yml
================================================
version: "3"
services:
  backend:
    build: ./quix-backend/
    ports:
      - "8081:8081"
    depends_on:
      - presto
      - postgres
    env_file:
      - .env
    environment:
      - MODULES
      - AUTH_COOKIE
      - AUTH_SECRET
      - AUTH_TYPE
  frontend:
    build: ./quix-frontend/
    ports:
      - "3000:3000"
    depends_on:
      - backend
      - db
    env_file:
      - .env
    environment:
      - DB_NAME
      - DB_USER
      - DB_PASS
      - DB_HOST
      - DB_PORT
      - BACKEND_INTERNAL_URL
      - BACKEND_PUBLIC_URL
      - GOOGLE_SSO_CLIENT_ID
      - GOOGLE_SSO_SECRET
      - AUTH_COOKIE
      - AUTH_SECRET
      - AUTH_TYPE
      - APPMETRICS_PORT
      - ENABLE_APPMETRICS
      - MODULES
  db:
    image: "mysql:5.7"
    restart: always
    environment:
      MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
      MYSQL_DATABASE: "quix"
    volumes:
      - "db_volume:/var/lib/mysql"
  presto:
    image: "starburstdata/presto:340-e"
    ports:
      - "8181:8080"
  postgres:
    image: "aa8y/postgres-dataset:dellstore"
    ports:
      - "5432:5432"

volumes:
  db_volume:


================================================
FILE: documentation/docs/about.md
================================================
---
id: about
title: About
sidebar_label: About
---

Quix is an easy-to-use notebook manager with support for [Presto](/quix/docs/presto), [Athena](/quix/docs/athena), [BigQuery](/quix/docs/bigquery), [MySQL](/quix/docs/mysql), [PostgreSQL](/quix/docs/postgresql), [ClickHouse](/quix/docs/clickhouse), [Amazon Redshift](/quix/docs/redshift) and more.

* [Demo](https://quix-demo.io/)
* [Installation](/quix/docs/installation)

## Quick start
Using docker-compose, this will run Quix with a MySQL container and an example Presto installation. Quix will run in a single-user mode without authentication. 

```bash
mkdir quix && cd quix
curl https://raw.githubusercontent.com/wix/quix/master/docker-compose.prebuilt.yml -o docker-compose.yml
curl https://raw.githubusercontent.com/wix/quix/master/env-example -o .env
docker-compose up
```

Be sure to check the [full installation notes](/quix/docs/installation) on how to edit the `.env` file to add more data sources, turn on multi-user mode and customize your deployment.

For support please conatct us via [oss@wix.com](mailto:oss@wix.com).

## Main features
- [Query management](#management) - organize your notebooks in folders for easy access and sharing
- [Visualizations](#visualizations) - quickly plot time and bar series (more visualizations to follow)
- [DB Explorer](#explorer) - explore your data sources
- Search - search notes of all users

#### Management
![](assets/management.gif)

#### Visualizations
![](assets/chart.gif)

#### Explorer
![](assets/db.gif)



================================================
FILE: documentation/docs/architecture.md
================================================
---
id: architecture
title: Architecture
sidebar_label: Architecture
---

![](assets/architecture.png)

Quix consists of three main elements:

* Frontend to serve UI and manage notebooks
* Backend to communicate with Presto
* DB for storing notebooks

Each component is run in a separate Docker container, and all of them are managed by a single Docker Compose configuration.

There's also a fourth Docker container provided with this repository running Presto inside Docker Compose, but it's for demonstration purposes only.

================================================
FILE: documentation/docs/athena.md
================================================
---
id: athena
title: Amazon Athena
sidebar_label: Athena
---
## Features
Work with Amazon Athena tables straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.

## Setup

### 1. Create a new IAM Policy

Create a new IAM policy to allow access to your bucket
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name/*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetBucketLocation",
                "s3:ListBucket"
            ],
            "Resource": [
                "arn:aws:s3:::your-bucket-name"
            ]
        }
    ]
}
```

### 2. Create a new IAM user
Create a new user with `Programmatic Access`. Attach security policy `AmazonAthenaFullAccess` along with policy created in step 1. 


### 3. Pick a new name for your athena note and update .env

Add/update following properties to .env file to configure your new note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo` |
| `MODULES_FOO_ENGINE`      | note type | `athena` |
| `MODULES_FOO_OUTPUT` | s3 bucket for results      |   `s3://some-bucket-id/` |
| `MODULES_FOO_REGION` | aws region      |   `us-east-1` |
| `MODULES_FOO_DATABASE` | default database      |   `default` |
| `MODULES_FOO_AWS_ACCESS_KEY_ID` | aws access key      |    |
| `MODULES_FOO_AWS_SECRET_KEY` | awe secret key      |   |

Example of possible configuration that will create note type named foo : 
```properties
MODULES_FOO_ENGINE=athena
MODULES_FOO_OUTPUT=s3://some-bucket-id/
MODULES_FOO_REGION=us-east-1
MODULES_FOO_DATABASE=default
MODULES_FOO_AWS_ACCESS_KEY_ID=123
MODULES_FOO_AWS_SECRET_KEY=abc
```

## Troubleshooting

================================================
FILE: documentation/docs/bigquery.md
================================================
---
id: bigquery
title: Google BigQuery
sidebar_label: BigQuery
---
## Features
Work with Google bigquery tables straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.

## Setup

### 1. Create a new service account
Go to `Api & Services` -> `Credentials` and click `Create credentials` with `Service Account key`.
Choose new service account in the dropdown, enter quix-bigquery-user as username, 
`BigQuery Admin` as role, and `Json` as key type.

Store resulting json in a secure location and use `base64` command line tool to calculate the base64 string of the file contents.
Alternatively use some online tool like https://www.base64encode.org/ to process the contents of json with credentials.     

### 2. Pick a new name for your bigquery note and update .env

Add/update following properties in .env file to configure your new note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo` |
| `MODULES_FOO_ENGINE`      | note type | `bigquery` |
| `MODULES_FOO_CREDENTIALS_BASE64` | base64 value of your credentials.json      |  `AABB111222` |


Example of possible configuration that will create new bigquery note named foo : 
```properties
MODULES_BQ_ENGINE=bigquery
MODULES_BQ_SYNTAX=ansi_sql
MODULES_BQ_CREDENTIALS_BASE64=AAABBBCCCDDDEEEFFFF
```

## Troubleshooting

================================================
FILE: documentation/docs/clickhouse.md
================================================
---
id: clickhouse
title: ClickHouse
sidebar_label: ClickHouse
---

## Features
Using jdbc note you can use quix to query ClickHouse. You will be able to execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.


## Setup
To setup [ClickHouse](https://clickhouse.tech/) note you have to perform the following :


### 1. Pick new name and update .env

Add/update following properties to .env file to configure your new note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `ru.yandex.clickhouse.ClickHouseDriver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:clickhouse://localhost:8123/test` |
| `MODULES_FOO_USER` | db username      |   `user` |
| `MODULES_FOO_PASS` | db password      |   `pass` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `ansi_sql` |


example of clickhouse jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=ru.yandex.clickhouse.ClickHouseDriver
MODULES_FOO_URL=jdbc:clickhouse://localhost:8123/test
MODULES_FOO_USER=your-user
MODULES_FOO_PASS=your-password
MODULES_FOO_SYNTAX=ansi_sql
```

## Troubleshooting

================================================
FILE: documentation/docs/installation.md
================================================
---
id: installation
title: Installation
sidebar_label: Installation
---

## Requirements
* [Docker](https://www.docker.com/products)
* [Docker Compose](https://docs.docker.com/compose/install/)

## Running
Run Docker Compose:

```
docker-compose up
```

The initial run of the `docker-compose up` command will take care of all the dependencies, like MySQL, Presto, Maven, etc, will install all necessary Quix components and create a web-accessible Quix instance.
You will need an `.env` file to run it. We will configure it in the next step.

To access Quix, navigate to:  
`http://localhost:3000`

## Clone repository
```
git clone https://github.com/wix-incubator/quix.git
```
## Configuration
Most of the configuration you'll need is done through environment variables. docker-compose can load environment-variables easily through a `.env` file.
You should rename our [env-example](https://github.com/wix-incubator/quix/blob/master/env-example) file to `.env`, and modify it's values as needed. 

#### Presto
By default, Quix works with demo Presto instance that runs inside Docker Compose.  
To work with your real Presto DB, change `PRESTO_API` environment variable.

Note that you need to specify full URL, including protocol, port and API version:
* MODULES_PRESTO_API - `http://presto.my.domain:8181/v1`  

  If you're running Presto locally, use the following instead of `localhost`:
  * Your internal IP
  * Or `host.docker.internal` (macOS only)

#### DB
Quix also uses MySQL to store notebooks and other application data. The default docker-compose uses a mysql container, so no further setup is needed. 
As an alternative, you can also use an external MySQL database, by specifying some of the following variables:
* DB_NAME - defaults to `quix`, must exist
* DB_USER - defaults to `root`
* DB_PASS - defaults to empty password
* DB_HOST - defaults to `db`
* DB_PORT - defaults to `3306`

* DB_AUTO_MIGRATE - this sets the [TypeORM](https://typeorm.io/#/connection-options) `synchronize` flag. Defaults to `false`. You probably only want to set this when running locally for development or if you don't care at all about your data.

#### User authentication
Quix can work in two modes: multi-user mode, authenticated with [Google OAuth](https://console.developers.google.com/apis/credentials), or in a single-user mode. This is controlled by the following variables:
* AUTH_TYPE - can be `fake` or `google`. Defaults to `fake` (single-user mode).

If you use Google OAuth, you must supply the clientId and the secret:
* GOOGLE_SSO_CLIENT_ID
* GOOGLE_SSO_SECRET

Other variables related to authentication:
* AUTH_COOKIE - defaults to `__quix`. When using `google` auth, must be provided.
* AUTH_SECRET - the encryption key for the cookie. Must be provided.
* COOKIE_MAX_AGE - should be in seconds, default is 30 days.

#### Configuration for custom deployment
Running quix with `docker-compose` should "just work", but when deploying quix, there are a couple more variables you might want to change:

* BACKEND_INTERNAL_URL - An address + port number (no protocol) where you have the backend service deployed and accessible to the frontend service.
* BACKEND_PUBLIC_URL - An address + port number (no protocol) to the backend service, made accessible to user's browser. In most scenarios, it's value is the same as `BACKEND_INTERNAL_URL`.
* ENABLE_APPMETRICS - Set this variable if you want to enable [appmetrics-dash](https://github.com/RuntimeTools/appmetrics-dash).
* APPMETRICS_PORT - The port where appmetrics dashboard will be exposed.

## Upgrading Quix
This takes into account a `docker-compose` setup. Extrapolate as needed if you have some other custom deployment. 

1. Backup your data, if possible.
2. Download an updated `docker-compose.yml` or `docker-compose.prebuilt.yml`. If you are not using the prebuilt images, you need to run `docker-compose build`.
3. Stop the frontend and backend services - `docker-compose stop backend frontend`.
4. Make sure all your environment variables are exported correctly in your current shell, specifically all the `DB_*` variables.
5. Run DB migrations: `docker-compose run --no-deps --rm frontend scripts/run_migrations.sh`.
6. Start services again `docker-compose up -d`.


================================================
FILE: documentation/docs/jdbc.md
================================================
---
id: jdbc
title: Jdbc
sidebar_label: Jdbc
---

## Features
Using jdbc note you can use quix to query 
[MySQL](mysql.md), 
[ClickHouse](clickhouse.md), 
[PostgreSQL](postgresql.md), 
Microsoft SQL Server, 
[MariaDB](mariadb.md), 
[Oracle](oracle.md), 
SQLite, 
[Redshift](redshift.md), 
Firebird, 
H2, 
HSQLDB, 
Apache Derby, 
IBM DB2, 
Teradata and more. 

You will be able to execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.

## Setup
To setup jdbc note you have to perform the following two steps :

### 1. Add new jdbc dependency to [Dockerfile](https://github.com/wix-incubator/quix/blob/master/quix-backend/Dockerfile)
Right now quix is pre-bundled with several populat jdbc drivers. If your driver is missing from the list, 
you should edit the [Dockerfile](https://github.com/wix-incubator/quix/blob/master/quix-backend/Dockerfile) and 
add a line that will download the driver and another line to push it into `quix.jar` file 


Examples of pre-bundled jdbc drivers : 
```
RUN wget -q -P BOOT-INF/lib/ \
    https://repo1.maven.org/maven2/ru/yandex/clickhouse/clickhouse-jdbc/0.2.4/clickhouse-jdbc-0.2.4.jar \
    https://repo1.maven.org/maven2/org/postgresql/postgresql/42.2.10/postgresql-42.2.10.jar \
    https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.19/mysql-connector-java-8.0.19.jar \
    https://repo1.maven.org/maven2/org/xerial/sqlite-jdbc/3.30.1/sqlite-jdbc-3.30.1.jar \
    https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/2.5.4/mariadb-java-client-2.5.4.jar \
    https://repo1.maven.org/maven2/org/hsqldb/hsqldb/2.5.0/hsqldb-2.5.0.jar \
    https://maven.ceon.pl/artifactory/repo/com/oracle/ojdbc/ojdbc10/19.3.0.0/ojdbc10-19.3.0.0.jar \
    https://repo1.maven.org/maven2/com/microsoft/sqlserver/mssql-jdbc/8.2.1.jre11/mssql-jdbc-8.2.1.jre11.jar

RUN jar uf0 quix.jar \
    BOOT-INF/lib/clickhouse-jdbc-0.2.4.jar \
    BOOT-INF/lib/postgresql-42.2.10.jar \
    BOOT-INF/lib/mysql-connector-java-8.0.19.jar \
    BOOT-INF/lib/sqlite-jdbc-3.30.1.jar \
    BOOT-INF/lib/mariadb-java-client-2.5.4.jar \
    BOOT-INF/lib/hsqldb-2.5.0.jar \
    BOOT-INF/lib/ojdbc10-19.3.0.0.jar \
    BOOT-INF/lib/mssql-jdbc-8.2.1.jre11.jar
``` 

### 2. Pick new name and update .env

Add/update following properties to .env file to configure your new note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `org.postgresql.Driver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:postgresql:postgres` |
| `MODULES_FOO_USER` | db username      |   `user` |
| `MODULES_FOO_PASS` | db password      |   `pass` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `mysql` or `ansi_sql` |


example of postgres jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=org.postgresql.Driver
MODULES_FOO_URL=jdbc:postgresql:postgres
MODULES_FOO_USER=your-user
MODULES_FOO_PASS=your-password
MODULES_FOO_SYNTAX=ansi_sql
```

## Troubleshooting

================================================
FILE: documentation/docs/mariadb.md
================================================
---
id: mariadb
title: MariaDB
sidebar_label: MariaDB
---

## Features
Work with MariaDB tables straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.

## Setup
To setup MariaDB note you have to perform the following two steps :

### 1. Pick new name and update .env

Add/update following properties to .env file to configure your new note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `org.mariadb.jdbc.Driver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:mariadb://localhost:3306/DB` |
| `MODULES_FOO_USER` | db username      |   `user` |
| `MODULES_FOO_PASS` | db password      |   `pass` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `mysql`|


example of mariadb jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=org.mariadb.jdbc.Driver
MODULES_FOO_URL=jdbc:mariadb://localhost:3306/DB
MODULES_FOO_USER=your-username
MODULES_FOO_PASS=your-password
MODULES_FOO_SYNTAX=mysql
```

## Troubleshooting

================================================
FILE: documentation/docs/mysql.md
================================================
---
id: mysql
title: MySQL
sidebar_label: MySQL
---

## Features
Work with MySQL tables straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.


## Setup
To setup MySQL note you have to perform the following two steps :

### 1. Pick new name and update .env

Add/update following properties to .env file to configure your new note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `com.mysql.jdbc.Driver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:mysql://localhost/test` |
| `MODULES_FOO_USER` | db username      |   `user` |
| `MODULES_FOO_PASS` | db password      |   `pass` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `mysql`|


example of mysql jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=com.mysql.jdbc.Driver
MODULES_FOO_URL=jdbc:mysql://localhost/test
MODULES_FOO_USER=your-username
MODULES_FOO_PASS=your-password
MODULES_FOO_SYNTAX=mysql
```

## Troubleshooting

================================================
FILE: documentation/docs/oracle.md
================================================
---
id: oracle
title: Oracle
sidebar_label: Oracle
---

## Features
Work with Oracle straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.

## Setup
To setup Oracle note you have to perform the following two steps :

### 1. Pick new name and update .env

Add/update following properties to .env file to configure your new oracle note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `oracle.jdbc.driver.OracleDriver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:oracle:thin:@localhost:1521:db` |
| `MODULES_FOO_USER` | db username      |   `user` |
| `MODULES_FOO_PASS` | db password      |   `pass` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `ansi_sql` |


example of oracle jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=oracle.jdbc.driver.OracleDriver
MODULES_FOO_URL=jdbc:oracle:thin:@localhost:1521:db
MODULES_FOO_USER=your-user
MODULES_FOO_PASS=your-password
MODULES_FOO_SYNTAX=ansi_sql
```

## Troubleshooting

================================================
FILE: documentation/docs/postgresql.md
================================================
---
id: postgresql
title: PostgreSQL
sidebar_label: PostgreSQL
---

## Features
Work with PostgreSQL straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.


## Setup
To setup PostgreSQL note you have to perform the following two steps :

### 1. Pick new name and update .env

Add/update following properties to .env file to configure your new postgresql note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `org.postgresql.Driver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:postgresql:postgres` |
| `MODULES_FOO_USER` | db username      |   `user` |
| `MODULES_FOO_PASS` | db password      |   `pass` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `ansi_sql` |


example of postgresql jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=org.postgresql.Driver
MODULES_FOO_URL=jdbc:postgresql:postgres
MODULES_FOO_USER=your-user
MODULES_FOO_PASS=your-password
MODULES_FOO_SYNTAX=ansi_sql
```

## Troubleshooting

================================================
FILE: documentation/docs/presto.md
================================================
---
id: presto
title: Presto
sidebar_label: Presto
---
## Features
Quix is a great tool for querying Presto. You can execute multiple queries in parallel, 
stream results straight to your browser, download them as csv, build visualizations, 
share your notes with other people in your organization and more.

## Setup

### 1. Pick a new name for your presto note and update .env

Add the following properties to the .env file to configure your new presto note

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo` |
| `MODULES_FOO_ENGINE`      | note type | `presto` |
| `MODULES_FOO_API` | presto url      |   `http://presto.your-domain.com:8080/v1` |
| `MODULES_FOO_CATALOG` | default catalog      |   `system` |
| `MODULES_FOO_SCHEMA` | default schema      |   `runtime` |
| `MODULES_FOO_SOURCE` | default source      |   `quix` |

Example of possible configuration that will create Presto note named foo : 
```properties
MODULES_FOO_ENGINE=presto
MODULES_FOO_API=http://presto:8080/v1
MODULES_FOO_CATALOG=system
MODULES_FOO_SCHEMA=runtime
MODULES_FOO_SOURCE=quix
```

## Troubleshooting


================================================
FILE: documentation/docs/python.md
================================================
---
id: python
title: Python
sidebar_label: Python
---
## Features
* Execute lightweight Python scripts straight from Quix
* Manage pip packages on user-level
* Render and visualize results in Quix

## Ideas for using python in Quix
1) Python notes can be used to orchestrate more complex processes that are hard to
achieve in simple sql note, so it's a perfect tool for simple prototyping and ETLS.  

2) You can query much more data sources in addition to out-of-the-box Quix notes.
 For example, PyMongo can be used to query MongoDB, hbase-python for HBase, boto3 for s3, python-firebase for firebase and many more. 

## Setup

### 1. Pick a new name for your python note and update .env

Add the following properties to the .env file to configure your new python note

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo` |
| `MODULES_FOO_ENGINE`      | note type | `python` |
| `MODULES_FOO_SYNTAX`      | note syntax | `python` |
| `MODULES_FOO_PIP_INDEX`      | custom pip index url | `https://your-own-pypi-mirror.org/simple` |
| `MODULES_FOO_PIP_EXTRA_INDEX`      | extra pip index url | `https://pypi.python.org/simple` |
| `MODULES_FOO_PIP_PACKAGES`      | list of mandatory pip packages | `ujson,pyhive` |
| `MODULES_FOO_SCRIPTS_DIR`      | dir that will be used to store each user temp files | `/tmp/quix-python` |
| `MODULES_FOO_ADDITIONAL_CODE_FILE`      | additional code that would be prepended to each python note | `/tmp/quix-python/init.py` |

Example : 
```properties
MODULES=foo
MODULES_FOO_ENGINE=python
MODULES_FOO_SYNTAX=python
MODULES_FOO_PIP_INDEX=https://pypi.your-domain.com/simple
MODULES_FOO_PIP_EXTRA_INDEX=https://pypi.python.org/simple
MODULES_FOO_PIP_PACKAGES=ujson,requests
MODULES_FOO_SCRIPTS_DIR=/tmp/quix-python
MODULES_FOO_ADDITIONAL_CODE_FILE=/tmp/quix-python/init.py
```

## Troubleshooting


================================================
FILE: documentation/docs/redshift.md
================================================
---
id: redshift
title: Amazon Redshift
sidebar_label: Redshift
---

## Features
Query Amazon Redshift data warehouse straight from Quix, execute multiple queries in parallel, explore the db tree, visualize and download the results into csv.


## Setup
To setup Amazon Redshift note you have to perform the following steps :

### 1. Obtain link to redshift jdbc driver 
Go to https://docs.aws.amazon.com/redshift/latest/mgmt/configure-jdbc-connection.html#download-jdbc-driver and choose the jar file that you need.
For example, 
```
https://s3.amazonaws.com/redshift-downloads/drivers/jdbc/1.2.41.1065/RedshiftJDBC42-no-awssdk-1.2.41.1065.jar
``` 

### 2. Update [Dockerfile](https://github.com/wix-incubator/quix/blob/master/quix-backend/Dockerfile) 
You need to update the Dockerfile that prepares image of quix-backend to include the missing jar. 
Edit it and add a line that will download the driver and another line to push it into `quix.jar` file 

```
RUN wget -q -P BOOT-INF/lib/ \
    https://s3.amazonaws.com/redshift-downloads/drivers/jdbc/1.2.41.1065/https://s3.amazonaws.com/redshift-downloads/drivers/jdbc/1.2.41.1065/RedshiftJDBC42-no-awssdk-1.2.41.1065.jar

RUN jar uf0 quix.jar \
    BOOT-INF/lib/RedshiftJDBC42-no-awssdk-1.2.41.1065.jar
```
### 3. Build the quix-backend image

Execute the following command to prepare a new docker image of quix-backend 
```
docker-compose build backend
``` 


### 4. Pick new name and update .env

Add/update following properties to .env file to configure your new Amazon Redshift note    

| Variables        | Meaning           | Example  |
| ------------- |:-------------:| -----:|
| `MODULES`      | list of registered notes | `foo,boo,prod,qa` |
| `MODULES_FOO_ENGINE`      | note type | `jdbc` |
| `MODULES_FOO_DRIVER` | jdbc driver class      |   `com.amazon.redshift.jdbc.Driver` |
| `MODULES_FOO_URL` | jdbc url      |   `jdbc:redshift://examplecluster.abc123xyz789.us-west-2.redshift.amazonaws.com:5439/dev` |
| `MODULES_FOO_SYNTAX` | syntax marker      |   `ansi_sql` |


example of redshift jdbc note that will be named `foo` in the UI

```properties
MODULES=<comma separated list of your modules>,foo

MODULES_FOO_ENGINE=jdbc
MODULES_FOO_DRIVER=com.amazon.redshift.jdbc.Driver
MODULES_FOO_URL=jdbc:redshift://examplecluster.abc123xyz789.us-west-2.redshift.amazonaws.com:5439/dev
MODULES_FOO_SYNTAX=ansi_sql
```

## Troubleshooting

================================================
FILE: documentation/website/README.md
================================================
This website was created with [Docusaurus](https://docusaurus.io/).

# What's In This Document

* [Get Started in 5 Minutes](#get-started-in-5-minutes)
* [Directory Structure](#directory-structure)
* [Editing Content](#editing-content)
* [Adding Content](#adding-content)
* [Full Documentation](#full-documentation)

# Get Started in 5 Minutes

1. Make sure all the dependencies for the website are installed:

```sh
# Install dependencies
$ yarn
```
2. Run your dev server:

```sh
# Start the site
$ yarn start
```

## Directory Structure

Your project file structure should look something like this

```
my-docusaurus/
  docs/
    doc-1.md
    doc-2.md
    doc-3.md
  website/
    blog/
      2016-3-11-oldest-post.md
      2017-10-24-newest-post.md
    core/
    node_modules/
    pages/
    static/
      css/
      img/
    package.json
    sidebar.json
    siteConfig.js
```

# Editing Content

## Editing an existing docs page

Edit docs by navigating to `docs/` and editing the corresponding document:

`docs/doc-to-be-edited.md`

```markdown
---
id: page-needs-edit
title: This Doc Needs To Be Edited
---

Edit me...
```

For more information about docs, click [here](https://docusaurus.io/docs/en/navigation)

## Editing an existing blog post

Edit blog posts by navigating to `website/blog` and editing the corresponding post:

`website/blog/post-to-be-edited.md`
```markdown
---
id: post-needs-edit
title: This Blog Post Needs To Be Edited
---

Edit me...
```

For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog)

# Adding Content

## Adding a new docs page to an existing sidebar

1. Create the doc as a new markdown file in `/docs`, example `docs/newly-created-doc.md`:

```md
---
id: newly-created-doc
title: This Doc Needs To Be Edited
---

My new content here..
```

1. Refer to that doc's ID in an existing sidebar in `website/sidebar.json`:

```javascript
// Add newly-created-doc to the Getting Started category of docs
{
  "docs": {
    "Getting Started": [
      "quick-start",
      "newly-created-doc" // new doc here
    ],
    ...
  },
  ...
}
```

For more information about adding new docs, click [here](https://docusaurus.io/docs/en/navigation)

## Adding a new blog post

1. Make sure there is a header link to your blog in `website/siteConfig.js`:

`website/siteConfig.js`
```javascript
headerLinks: [
    ...
    { blog: true, label: 'Blog' },
    ...
]
```

2. Create the blog post with the format `YYYY-MM-DD-My-Blog-Post-Title.md` in `website/blog`:

`website/blog/2018-05-21-New-Blog-Post.md`

```markdown
---
author: Frank Li
authorURL: https://twitter.com/foobarbaz
authorFBID: 503283835
title: New Blog Post
---

Lorem Ipsum...
```

For more information about blog posts, click [here](https://docusaurus.io/docs/en/adding-blog)

## Adding items to your site's top navigation bar

1. Add links to docs, custom pages or external links by editing the headerLinks field of `website/siteConfig.js`:

`website/siteConfig.js`
```javascript
{
  headerLinks: [
    ...
    /* you can add docs */
    { doc: 'my-examples', label: 'Examples' },
    /* you can add custom pages */
    { page: 'help', label: 'Help' },
    /* you can add external links */
    { href: 'https://github.com/facebook/Docusaurus', label: 'GitHub' },
    ...
  ],
  ...
}
```

For more information about the navigation bar, click [here](https://docusaurus.io/docs/en/navigation)

## Adding custom pages

1. Docusaurus uses React components to build pages. The components are saved as .js files in `website/pages/en`:
1. If you want your page to show up in your navigation header, you will need to update `website/siteConfig.js` to add to the `headerLinks` element:

`website/siteConfig.js`
```javascript
{
  headerLinks: [
    ...
    { page: 'my-new-custom-page', label: 'My New Custom Page' },
    ...
  ],
  ...
}
```

For more information about custom pages, click [here](https://docusaurus.io/docs/en/custom-pages).

# Full Documentation

Full documentation can be found on the [website](https://docusaurus.io/).



================================================
FILE: documentation/website/blog/2019-11-25-first-release.md
================================================
---
title: First release
author: Quix Team
---
Quix is a notebook manager that focuses on ease of use and shareability.  
It aims to be a shared space for your company's BI insights and know-how.

Since the official announcement this summer and following the requests from our first users we added support for more data sources (Athena, BigQuery, JDBC), tweaked the visualizations, fixed bugs and improved the documentation.

If you're in the market for an intuitive and fast tool to query and share your data, give Quix a try:
* [Online demo](https://quix-demo.io/)
* Quick start
```bash
mkdir quix && cd quix
curl https://raw.githubusercontent.com/wix/quix/master/docker-compose.prebuilt.yml -o docker-compose.yml
curl https://raw.githubusercontent.com/wix/quix/master/env-example -o .env
docker-compose up
```
* [Full installation](https://wix.github.io/quix/docs/installation)

### Here's what's available in our first release:

#### Notebook/note management with multi-user support
* Shareable folders/notebooks/notes
* Favorite notebooks
* Full-text note search across all users
* Readonly access to the notebooks of all users

#### Query editor
* Multiple statements
* Syntax highlighting
* Live syntax validation and autocompletion (currently for Presto only)
* Keyboard shortcuts
* Typed parameters (String, Boolean, Number, Date, Option, List)
* Export results as CSV

#### One-click visualizations
* Timeline chart
* Bar chart
* Pie chart

#### DB types you can query
* Presto (supports live syntax validation and basic autocompletion)
* Amazon Athena
* Google BigQuery
* Generic JDBC (MySQL, PostgreSQL, SQL Server, ClickHouse, etc...)

#### DB Explorer
* Navigate, search and preview your catalogs and tables

#### What's in the pipeline?
* Python note
* More SSO options (OpenID)
* More visualizations
* Note embedding
* Scheduled queries
* Public queries
* SDK for extending the base functionality of Quix

#### Contributors
@frolovv, @sthuck, @antonpod, @ittaym, @yaarams, @stas-slu, @shl3vi, @amitmarx, @kgshv, @erezr


================================================
FILE: documentation/website/core/Footer.js
================================================
/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const React = require('react');

class Footer extends React.Component {
  docUrl(doc, language) {
    const baseUrl = this.props.config.baseUrl;
    const docsUrl = this.props.config.docsUrl;
    const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
    const langPart = `${language ? `${language}/` : ''}`;
    return `${baseUrl}${docsPart}${langPart}${doc}`;
  }

  pageUrl(doc, language) {
    const baseUrl = this.props.config.baseUrl;
    return baseUrl + (language ? `${language}/` : '') + doc;
  }

  render() {
    return (
      <footer className="nav-footer" id="footer">
        <section className="sitemap">
          <a href={this.props.config.baseUrl} className="nav-home">
            {this.props.config.footerIcon && (
              <img
                src={this.props.config.baseUrl + this.props.config.footerIcon}
                alt={this.props.config.title}
              />
            )}
          </a>
          <div>
            <h5>Docs</h5>
            <a href={this.docUrl('about.html#quick-start')}>
              Quick Start
            </a>
            <a href={this.docUrl('installation.html')}>
              Installation
            </a>
          </div>

          <div>
            <h5>Social</h5>
            <a href={`${this.props.config.baseUrl}blog`}>Blog</a>
            <a
              className="github-button"
              href={this.props.config.repoUrl}
              data-icon="octicon-star"
              data-count-href="/wix/quix/stargazers"
              data-show-count="true"
              data-count-aria-label="# stargazers on GitHub"
              aria-label="Star this project on GitHub">
              Quix
            </a>
          </div>

          <div>
            <h5>Contact Us</h5>
            <a href="mailto:oss@wix.com">By Email</a>
          </div>
        </section>
        <section className="copyright">{this.props.config.copyright}</section>
      </footer>
    );
  }
}

module.exports = Footer;


================================================
FILE: documentation/website/i18n/en.json
================================================
{
  "_comment": "This file is auto-generated by write-translations.js",
  "localized-strings": {
    "next": "Next",
    "previous": "Previous",
    "tagline": "An easy-to-use notebook manager",
    "docs": {
      "about": {
        "title": "About",
        "sidebar_label": "About"
      },
      "architecture": {
        "title": "Architecture",
        "sidebar_label": "Architecture"
      },
      "athena": {
        "title": "Amazon Athena",
        "sidebar_label": "Athena"
      },
      "bigquery": {
        "title": "Google BigQuery",
        "sidebar_label": "BigQuery"
      },
      "clickhouse": {
        "title": "ClickHouse",
        "sidebar_label": "ClickHouse"
      },
      "installation": {
        "title": "Installation",
        "sidebar_label": "Installation"
      },
      "jdbc": {
        "title": "Jdbc",
        "sidebar_label": "Jdbc"
      },
      "mariadb": {
        "title": "MariaDB",
        "sidebar_label": "MariaDB"
      },
      "mysql": {
        "title": "MySQL",
        "sidebar_label": "MySQL"
      },
      "oracle": {
        "title": "Oracle",
        "sidebar_label": "Oracle"
      },
      "postgresql": {
        "title": "PostgreSQL",
        "sidebar_label": "PostgreSQL"
      },
      "presto": {
        "title": "Presto",
        "sidebar_label": "Presto"
      },
      "python": {
        "title": "Python",
        "sidebar_label": "Python"
      },
      "redshift": {
        "title": "Amazon Redshift",
        "sidebar_label": "Redshift"
      }
    },
    "links": {
      "Docs": "Docs",
      "Blog": "Blog",
      "GitHub": "GitHub"
    },
    "categories": {
      "Introduction": "Introduction",
      "Getting Started": "Getting Started",
      "Supported datasources": "Supported datasources"
    }
  },
  "pages-strings": {
    "Help Translate|recruit community translators for your project": "Help Translate",
    "Edit this Doc|recruitment message asking to edit the doc source": "Edit",
    "Translate this Doc|recruitment message asking to translate the docs": "Translate"
  }
}


================================================
FILE: documentation/website/package.json
================================================
{
  "scripts": {
    "examples": "docusaurus-examples",
    "start": "docusaurus-start",
    "build": "docusaurus-build",
    "publish-gh-pages": "docusaurus-publish",
    "write-translations": "docusaurus-write-translations",
    "version": "docusaurus-version",
    "rename-version": "docusaurus-rename-version"
  },
  "devDependencies": {
    "docusaurus": "^1.14.6"
  }
}


================================================
FILE: documentation/website/pages/en/help.js
================================================
/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const React = require('react');

const CompLibrary = require('../../core/CompLibrary.js');

const Container = CompLibrary.Container;
const GridBlock = CompLibrary.GridBlock;

function Help(props) {
  const {config: siteConfig, language = ''} = props;
  const {baseUrl, docsUrl} = siteConfig;
  const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
  const langPart = `${language ? `${language}/` : ''}`;
  const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`;

  const supportLinks = [
    {
      content: `Learn more using the [documentation on this site.](${docUrl(
        'doc1.html',
      )})`,
      title: 'Browse Docs',
    },
    {
      content: 'Ask questions about the documentation and project',
      title: 'Join the community',
    },
    {
      content: "Find out what's new with this project",
      title: 'Stay up to date',
    },
  ];

  return (
    <div className="docMainWrapper wrapper">
      <Container className="mainContainer documentContainer postContainer">
        <div className="post">
          <header className="postHeader">
            <h1>Need help?</h1>
          </header>
          <p>This project is maintained by a dedicated group of people.</p>
          <GridBlock contents={supportLinks} layout="threeColumn" />
        </div>
      </Container>
    </div>
  );
}

module.exports = Help;


================================================
FILE: documentation/website/pages/en/index.js
================================================
/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const React = require('react');

const CompLibrary = require('../../core/CompLibrary.js');

const Container = CompLibrary.Container;
const GridBlock = CompLibrary.GridBlock;

class HomeSplash extends React.Component {
  render() {
    const {siteConfig, language = ''} = this.props;
    const {baseUrl, docsUrl} = siteConfig;
    const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
    const langPart = `${language ? `${language}/` : ''}`;
    const docUrl = doc => `${baseUrl}${docsPart}${langPart}${doc}`;

    const SplashContainer = props => (
      <div className="homeContainer">
        <div className="homeSplashFade">
          <div className="wrapper homeWrapper">{props.children}</div>
        </div>
      </div>
    );

    const Logo = props => (
      <div className="projectLogo">
        <img src={props.img_src} alt="Project Logo" />
      </div>
    );

    const ProjectTitle = () => (
      <h2 className="projectTitle">
        {siteConfig.title}
        <small>{siteConfig.tagline}</small>
      </h2>
    );

    const PromoSection = props => (
      <div className="section promoSection">
        <div className="promoRow">
          <div className="pluginRowBlock">{props.children}</div>
        </div>
      </div>
    );

    const Button = props => (
      <div className="pluginWrapper buttonWrapper">
        <a className="button" href={props.href} target={props.target}>
          {props.children}
        </a>
      </div>
    );

    return (
      <SplashContainer>
        <Logo img_src={`${baseUrl}img/chart.gif`} />
        <div className="inner">
          <ProjectTitle siteConfig={siteConfig} />
          <PromoSection>
            <Button href={docUrl('about')}>Quick start</Button>
            <Button href={docUrl('installation')}>Installation</Button>
            <Button href="mailto:oss@wix.com">Contact us</Button>
          </PromoSection>
        </div>
      </SplashContainer>
    );
  }
}

class Index extends React.Component {
  render() {
    const {config: siteConfig, language = ''} = this.props;
    const {baseUrl, docsUrl} = siteConfig;
    const docsPart = `${docsUrl ? `${docsUrl}/` : ''}`;
    const langPart = `${language ? `${language}/` : ''}`;
    const docUrl = (doc, hash) => `${baseUrl}${docsPart}${langPart}${doc}${hash ? `#${hash}` : ''}`;

    const Block = props => (
      <Container
        padding={['bottom', 'top']}
        id={props.id}
        background={props.background}>
        <GridBlock
          align="center"
          contents={props.children}
          layout={props.layout}
        />
      </Container>
    );

    const MainFeatures = () => (
      <Block layout="threeColumn" background="light">
        {[
          {
            content: 'You can run Quix in single-user or <br> multi-user mode via Google OAuth',
            title: 'Multi-user web-app',
          },
          {
            content: 'Quix uses notes to edit and run queries. <br> Notes live inside notebooks, which  <br>  can be organized in folders.',
            title: 'Notebook manager',
          },
          {
            content: 'The DB explorer lets you navigate, <br> search and preview your tables',
            title: 'DB explorer',
          },
        ]}
      </Block>
    );

    const MoreFeatures = () => (
      <React.Fragment>
        <Block layout="threeColumn">
          {[
            {
              content: 'Quix features smart charts which help <br> you quickly visualize your data',
              title: 'One-click visualizations',
            },
            {
              content: 'Search queries across all users',
              title: 'Search',
            },
            {
              content: 'Easily share your folders, notebooks and notes',
              title: 'Shareability',
            },
          ]}
        </Block>
        <Block layout="threeColumn" background="light">
          {[
            {
              content: 'View the history of queries executed by you <br> or other users',
              title: 'History',
            },
            {},
            {},
          ]}
        </Block>
      </React.Fragment>
    );

    const Showcase = () => {
      if ((siteConfig.users || []).length === 0) {
        return null;
      }

      const showcase = siteConfig.users
        .filter(user => user.pinned)
        .map(user => (
          <a href={user.infoLink} key={user.infoLink}>
            <img src={user.image} alt={user.caption} title={user.caption} />
          </a>
        ));

      const pageUrl = page => baseUrl + (language ? `${language}/` : '') + page;

      return (
        <div className="productShowcaseSection paddingBottom">
          <h2>Who is Using This?</h2>
          <p>This project is used by all these people</p>
          <div className="logos">{showcase}</div>
          <div className="more-users">
            <a className="button" href={pageUrl('users.html')}>
              More {siteConfig.title} Users
            </a>
          </div>
        </div>
      );
    };

    return (
      <div>
        <HomeSplash siteConfig={siteConfig} language={language} />
        <div className="mainContainer">
          <MainFeatures />
          <MoreFeatures />
        </div>
      </div>
    );
  }
}

module.exports = Index;


================================================
FILE: documentation/website/pages/en/users.js
================================================
/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

const React = require('react');

const CompLibrary = require('../../core/CompLibrary.js');

const Container = CompLibrary.Container;

class Users extends React.Component {
  render() {
    const {config: siteConfig} = this.props;
    if ((siteConfig.users || []).length === 0) {
      return null;
    }

    const editUrl = `${siteConfig.repoUrl}/edit/master/website/siteConfig.js`;
    const showcase = siteConfig.users.map(user => (
      <a href={user.infoLink} key={user.infoLink}>
        <img src={user.image} alt={user.caption} title={user.caption} />
      </a>
    ));

    return (
      <div className="mainContainer">
        <Container padding={['bottom', 'top']}>
          <div className="showcaseSection">
            <div className="prose">
              <h1>Who is Using This?</h1>
              <p>This project is used by many folks</p>
            </div>
            <div className="logos">{showcase}</div>
            <p>Are you using this project?</p>
            <a href={editUrl} className="button">
              Add your company
            </a>
          </div>
        </Container>
      </div>
    );
  }
}

module.exports = Users;


================================================
FILE: documentation/website/sidebars.json
================================================
{
  "docs": {
    "Introduction": ["about", "architecture"],
    "Getting Started": ["installation"],
    "Supported datasources": ["athena", "bigquery", "clickhouse", "jdbc", "mariadb", "mysql", "oracle", "postgresql", "presto", "python", "redshift"]
  }
}


================================================
FILE: documentation/website/siteConfig.js
================================================
/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

// See https://docusaurus.io/docs/site-config for all the possible
// site configuration options.

// List of projects/orgs using your project for the users page.
const users = [
  {
    caption: 'User1',
    // You will need to prepend the image path with your baseUrl
    // if it is not '/', like: '/test-site/img/image.jpg'.
    image: '/img/undraw_open_source.svg',
    infoLink: 'https://www.facebook.com',
    pinned: true,
  },
];

const siteConfig = {
  algolia: {
    apiKey: '706ea6606dcf22ab4091945383d0cff9',
    indexName: 'quix',
  },
  title: 'Quix', // Title for your website.
  tagline: 'An easy-to-use notebook manager',
  // url: 'https://your-docusaurus-test-site.com', // Your website URL
  baseUrl: '/quix/', // Base URL for your project */
  // For github.io type URLs, you would set the url and baseUrl like:
  url: 'https://wix.github.io',
  baseUrl: '/quix/',

  // Used for publishing and more
  projectName: 'quix',
  organizationName: 'wix',
  // For top-level user or org sites, the organization is still the same.
  // e.g., for the https://JoelMarcey.github.io site, it would be set like...
  //   organizationName: 'JoelMarcey'

  // For no header links in the top nav bar -> headerLinks: [],
  headerLinks: [
    {doc: 'installation', label: 'Docs'},
    {blog: true, label: 'Blog'},
    {href: 'https://github.com/wix-incubator/quix', label: 'GitHub'},
  ],

  // If you have users set above, you add it here:
  users,

  /* path to images for header/footer */
  headerIcon: 'img/favicon.ico',
  footerIcon: 'img/favicon.ico',
  favicon: 'img/favicon.ico',

  /* Colors for website */
  colors: {
    primaryColor: '#fc4a6a',
    secondaryColor: '#00a9f4',
  },

  /* Custom fonts for website */
  /*
  fonts: {
    myFont: [
      "Times New Roman",
      "Serif"
    ],
    myOtherFont: [
      "-apple-system",
      "system-ui"
    ]
  },
  */

  // This copyright info is used in /core/Footer.js and blog RSS/Atom feeds.
  copyright: `© ${new Date().getFullYear()} Wix.com, Inc`,

  highlight: {
    // Highlight.js theme to use for syntax highlighting in code blocks.
    theme: 'default',
  },

  // Add custom scripts here that would be placed in <script> tags.
  scripts: ['https://buttons.github.io/buttons.js'],

  // On page navigation for the current documentation page.
  onPageNav: 'separate',
  // No .html extensions for paths.
  cleanUrl: true,

  // Open Graph and Twitter card images.
  ogImage: 'img/undraw_online.svg',
  twitterImage: 'img/undraw_tweetstorm.svg',

  // Show documentation's last contributor's name.
  // enableUpdateBy: true,

  // Show documentation's last update time.
  // enableUpdateTime: true,

  // You may provide arbitrary config keys to be used as needed by your
  // template. For example, if you need your repo's URL...
  repoUrl: 'https://github.com/wix-incubator/quix',
};

module.exports = siteConfig;


================================================
FILE: documentation/website/static/css/custom.css
================================================
/* your custom css */

@media only screen and (min-device-width: 360px) and (max-device-width: 736px) {
}

@media only screen and (min-width: 1024px) {
}

@media only screen and (max-width: 1023px) {
}

@media only screen and (min-width: 1400px) {
}

@media only screen and (min-width: 1500px) {
}

.homeContainer {
  text-align: unset;
}

.homeContainer .homeWrapper {
  padding: 2em 100px;
}

.homeContainer .homeWrapper .projectLogo {
  padding: 20px 100px 0;
}

.promoSection .promoRow .pluginRowBlock {
  justify-content: unset;
}

.imageAlignTop .blockImage {
  position: relative;
  display: block;
  max-width: 60%;
}

.imageAlignTop .blockImage:after {
  content: '';
  display: block;
  padding-bottom: 100%;
}

.imageAlignTop .blockImage img {
  transform: translate(0, -50%);
  position: absolute;
  top: 50%;
  left: 0;
}

.fixedHeaderContainer header .logo {
  height: 20px;
  padding: 4px;
  background-color: #ffffff;
  border-radius: 100px;
}

================================================
FILE: env-example
================================================
#MODULES=presto,athena,prod,bq
MODULES=presto


MODULES_PRESTO_ENGINE=presto
MODULES_PRESTO_API=http://presto:8080/v1
MODULES_PRESTO_CATALOG=system
MODULES_PRESTO_SCHEMA=runtime
MODULES_PRESTO_SOURCE=quix
MODULES_PRESTO_DB_EMPTY_TIMEOUT=60000
MODULES_PRESTO_DB_REQUEST_TIMEOUT=10000
MODULES_PRESTO_HTTP_HEADERS_PREFIX=X-PRESTO-

#MODULES_ATHENA_ENGINE=athena
#MODULES_ATHENA_OUTPUT=s3://some-bucket-id/
#MODULES_ATHENA_REGION=us-east-1
#MODULES_ATHENA_DATABASE=default
#MODULES_ATHENA_DB_EMPTY_TIMEOUT=60000
#MODULES_ATHENA_DB_REQUEST_TIMEOUT=10000

#MODULES_PROD_ENGINE=jdbc
#MODULES_PROD_DRIVER=com.mysql.jdbc.Driver
#MODULES_PROD_URL=jdbc:mysql://localhost:2222/aschema
#MODULES_PROD_USER=prod-user
#MODULES_PROD_PASS=prod-pass
#MODULES_PROD_SYNTAX=mysql

#MODULES_BQ_ENGINE=bigquery
#MODULES_BQ_SYNTAX=ansi_sql
#MODULES_BQ_CREDENTIALS_BASE64= BASE64 of credentials.json

#fake or google
AUTH_TYPE=fake
AUTH_USER=dummy-user
AUTH_COOKIE=
AUTH_SECRET=
#COOKIE_MAX_AGE=30
DB_NAME=quix
DB_USER=
DB_PASS=
DB_HOST=
DB_PORT=
#BACKEND_INTERNAL_URL=
#BACKEND_PUBLIC_URL=
GOOGLE_SSO_CLIENT_ID=
GOOGLE_SSO_SECRET=


================================================
FILE: quix-backend/Dockerfile
================================================
FROM maven:alpine as maven

# Install sbt
RUN \
    curl -L --silent "https://raw.githubusercontent.com/sbt/sbt/v1.5.1/sbt" > $HOME/sbt && \
    chmod +x $HOME/sbt && \
    mv $HOME/sbt /usr/local/bin/sbt

COPY build.sbt .
COPY version.sbt .
RUN sbt update -Dsbt.rootdir=true;
COPY /quix-webapps/quix-web-spring/pom.xml ./quix-webapps/quix-web-spring/pom.xml
RUN mvn -B -f /quix-webapps/quix-web-spring/pom.xml dependency:resolve --fail-never

COPY quix-api/src ./quix-api/src
COPY quix-core/src ./quix-core/src
COPY /quix-modules/quix-presto-module/src ./quix-modules/quix-presto-module/src
COPY /quix-modules/quix-athena-module/src ./quix-modules/quix-athena-module/src
COPY /quix-modules/quix-bigquery-module/src ./quix-modules/quix-bigquery-module/src
COPY /quix-modules/quix-jdbc-module/src ./quix-modules/quix-jdbc-module/src
COPY /quix-modules/quix-python-module/src ./quix-modules/quix-python-module/src
COPY /quix-modules/quix-dummy-module/src ./quix-modules/quix-dummy-module/src
COPY /quix-webapps/quix-web-spring/src ./quix-webapps/quix-web-spring/src

RUN sbt +publishM2 -Dsbt.rootdir=true;
RUN mvn -f /quix-webapps/quix-web-spring/pom.xml install -DskipTests

FROM ubuntu:20.04

# Setup python and java and base system
ENV PYTHONUNBUFFERED=1
ENV DEBIAN_FRONTEND noninteractive
ENV LANG=en_US.UTF-8

RUN apt-get update && \
  apt-get install -q -y --no-install-recommends \
  default-jdk \
  python3 \
  python-dev \
  python3-dev \
  python3-pip \
  libsnappy-dev \
  language-pack-en \
  build-essential \
  wget \
  && rm -rf /var/lib/apt/lists/*

RUN pip3 install --no-cache --upgrade pip setuptools wheel py4j

EXPOSE 8081

WORKDIR /quix-webapps/quix-web-spring

COPY --from=maven /quix-webapps/quix-web-spring/target/quix-web-spring-*.jar ./quix.jar

RUN wget -q -P BOOT-INF/lib/ \
    https://repo1.maven.org/maven2/ru/yandex/clickhouse/clickhouse-jdbc/0.2.4/clickhouse-jdbc-0.2.4.jar \
    https://repo1.maven.org/maven2/org/postgresql/postgresql/42.2.10/postgresql-42.2.10.jar \
    https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.19/mysql-connector-java-8.0.19.jar \
    https://repo1.maven.org/maven2/org/xerial/sqlite-jdbc/3.30.1/sqlite-jdbc-3.30.1.jar \
    https://repo1.maven.org/maven2/org/mariadb/jdbc/mariadb-java-client/2.5.4/mariadb-java-client-2.5.4.jar \
    https://repo1.maven.org/maven2/org/hsqldb/hsqldb/2.5.0/hsqldb-2.5.0.jar \
    https://maven.ceon.pl/artifactory/repo/com/oracle/ojdbc/ojdbc10/19.3.0.0/ojdbc10-19.3.0.0.jar \
    https://repo1.maven.org/maven2/com/microsoft/sqlserver/mssql-jdbc/8.2.1.jre11/mssql-jdbc-8.2.1.jre11.jar

RUN jar uf0 quix.jar \
    BOOT-INF/lib/clickhouse-jdbc-0.2.4.jar \
    BOOT-INF/lib/postgresql-42.2.10.jar \
    BOOT-INF/lib/mysql-connector-java-8.0.19.jar \
    BOOT-INF/lib/sqlite-jdbc-3.30.1.jar \
    BOOT-INF/lib/mariadb-java-client-2.5.4.jar \
    BOOT-INF/lib/hsqldb-2.5.0.jar \
    BOOT-INF/lib/ojdbc10-19.3.0.0.jar \
    BOOT-INF/lib/mssql-jdbc-8.2.1.jre11.jar

CMD ["java", "-jar", "quix.jar"]


================================================
FILE: quix-backend/README.md
================================================
# Quix Backend
Quix backend is based on SpringBoot and Scala, and is built with sbt and Maven.
 
## Installation

### Requirements
* Presto
* Docker
* Maven 3.6
* sbt 1.3.8

### Building
The default build will download all dependencies inside the Docker container. This build is safer and doesn't require sbt/Maven to be installed locally, but takes longer.
``` 
docker build -t quix-backend .
```

### Running
Provide a mandatory config values to docker
```
docker run -p 8081:8081 --name quix-backend -t quix-backend 
```

In case you have local `application.properties` file, we can map it into Docker container and execute it
```docker run -v /path-to-local/application.properties:/application.properties -p 8081:8081 -t quix-backend``` 

## Sample application.properties 
```
server.port=8081

# logging levels of different classes
logging.level.org.springframework.web=DEBUG
logging.level.org.hibernate=ERROR

# mandatory presto api url
presto.api=<your-presto-master-hostname>:8181/v1

# refresh policy of db tree, every 15 minutes with initial 1 minute delay
db.refresh.initialDelayInMinutes=1
db.refresh.delayInMinutes=15

```

### Stopping
``` 
docker stop quix-backend && docker rm quix-backend 
```

## License
MIT

## Contributing


================================================
FILE: quix-backend/build.sbt
================================================
lazy val publishSettings = Seq(
  publishTo := {
    val nexus = "https://oss.sonatype.org/"
    if (version.value.trim.endsWith("SNAPSHOT"))
      Some("snapshots" at nexus + "content/repositories/snapshots")
    else
      Some("releases" at nexus + "service/local/staging/deploy/maven2")
  },
  publishMavenStyle := true,
  ThisBuild / pomExtra :=
    <scm>
      <url>https://github.com/wix-incubator/quix.git</url>
      <connection>scm:git:https://github.com/wix-incubator/quix.git</connection>
    </scm>
      <developers>
        <developer>
          <id>frolovv</id>
          <name>Valery Frolov</name>
          <email>valeryf@wix.com</email>
          <organization>Wix</organization>
        </developer>
      </developers>
)

lazy val compileOptions = Seq(
  crossScalaVersions := Seq("2.12.17", "2.13.9"),
)

lazy val noPublish = Seq(publish := {}, publishLocal := {}, publishArtifact := false)

lazy val baseSettings =
  publishSettings ++
    compileOptions ++
    Seq(
      organization := "com.wix",
      homepage := Some(url("https://github.com/wix-incubator/quix")),
      licenses := Seq("MIT" -> url("https://opensource.org/licenses/MIT"))
    )

val loggingDeps = Seq(
  "com.typesafe.scala-logging" %% "scala-logging" % "3.9.3",
  "ch.qos.logback" % "logback-classic" % "1.2.3"
)

val specs2Deps = Seq(
  "org.specs2" %% "specs2-core" % "4.10.6" % "test",
  "org.specs2" %% "specs2-junit" % "4.10.6" % "test",
  "org.specs2" %% "specs2-mock" % "4.10.6" % "test",
)

lazy val quixApi = (project in file("quix-api"))
  .settings(Seq(
    name := "Quix Api",
    libraryDependencies += "io.monix" %% "monix" % "3.3.0"
  ) ++ baseSettings)

lazy val quixCore = (project in file("quix-core"))
  .dependsOn(quixApi)
  .settings(Seq(
    name := "Quix Core",

    libraryDependencies += "com.github.blemale" %% "scaffeine" % "3.1.0",

    // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core
    libraryDependencies += "com.fasterxml.jackson.core" % "jackson-core" % "2.10.4",

    // https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-scala
    libraryDependencies += "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.10.4",

    // https://mvnrepository.com/artifact/com.fasterxml.jackson.datatype/jackson-datatype-jdk8
    libraryDependencies += "com.fasterxml.jackson.datatype" % "jackson-datatype-jdk8" % "2.10.4",

    // https://mvnrepository.com/artifact/io.prestosql/presto-parser
    libraryDependencies += "io.prestosql" % "presto-parser" % "329",

    // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-s3
    libraryDependencies += "com.amazonaws" % "aws-java-sdk-s3" % "1.11.728",

    // https://mvnrepository.com/artifact/com.opencsv/opencsv
    libraryDependencies += "com.opencsv" % "opencsv" % "5.5.2",

    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,

    // https://mvnrepository.com/artifact/com.wix/wix-embedded-mysql
    libraryDependencies += "com.wix" % "wix-embedded-mysql" % "4.6.1" % Test,

    // https://mvnrepository.com/artifact/mysql/mysql-connector-java
    libraryDependencies += "mysql" % "mysql-connector-java" % "8.0.19" % Test,
  ) ++ baseSettings)

lazy val quixAthenaModule = (project in file("quix-modules/quix-athena-module"))
  .dependsOn(quixCore)
  .settings(Seq(
    name := "Quix Athena Module",

    // https://mvnrepository.com/artifact/com.amazonaws/aws-java-sdk-athena
    libraryDependencies += "com.amazonaws" % "aws-java-sdk-athena" % "1.11.715",
    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,
  ) ++ baseSettings)

lazy val quixBigqueryModule = (project in file("quix-modules/quix-bigquery-module"))
  .dependsOn(quixCore)
  .settings(Seq(
    name := "Quix Bigquery Module",

    // https://mvnrepository.com/artifact/com.google.cloud/google-cloud-bigquery
    libraryDependencies += "com.google.cloud" % "google-cloud-bigquery" % "1.106.0",
    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,
  ) ++ baseSettings)

lazy val quixDummyModule = (project in file("quix-modules/quix-dummy-module"))
  .dependsOn(quixCore)
  .settings(Seq(
    name := "Quix Dummy Module",

    libraryDependencies += "io.monix" %% "monix" % "3.3.0",
    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,
  ) ++ baseSettings ++ noPublish)

lazy val quixJdbcModule = (project in file("quix-modules/quix-jdbc-module"))
  .dependsOn(quixCore)
  .settings(Seq(
    name := "Quix Jdbc Module",

    libraryDependencies += "io.monix" %% "monix" % "3.3.0",
    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,
    // https://mvnrepository.com/artifact/com.wix/wix-embedded-mysql
    libraryDependencies += "com.wix" % "wix-embedded-mysql" % "4.6.1" % Test,

    // https://mvnrepository.com/artifact/mysql/mysql-connector-java
    libraryDependencies += "mysql" % "mysql-connector-java" % "8.0.19" % Test,
  ) ++ baseSettings)

lazy val quixPrestoModule = (project in file("quix-modules/quix-presto-module"))
  .dependsOn(quixCore)
  .settings(Seq(
    name := "Quix Presto Module",

    libraryDependencies += "io.monix" %% "monix" % "3.3.0",
    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,
    // https://mvnrepository.com/artifact/io.prestosql/presto-parser
    libraryDependencies += "io.prestosql" % "presto-parser" % "329",
    // https://mvnrepository.com/artifact/io.prestosql/presto-client
    libraryDependencies += "io.prestosql" % "presto-client" % "329",
    // https://mvnrepository.com/artifact/org.scalaj/scalaj-http
    libraryDependencies += "org.scalaj" %% "scalaj-http" % "2.4.2",
  ) ++ baseSettings)

lazy val quixPythonModule = (project in file("quix-modules/quix-python-module"))
  .dependsOn(quixCore)
  .settings(Seq(
    name := "Quix Python Module",

    libraryDependencies ++= loggingDeps,
    libraryDependencies ++= specs2Deps,
    // https://mvnrepository.com/artifact/com.zaxxer/nuprocess
    libraryDependencies += "com.zaxxer" % "nuprocess" % "2.0.1",
    // https://mvnrepository.com/artifact/net.sf.py4j/py4j
    libraryDependencies += "net.sf.py4j" % "py4j" % "0.10.9.2",
  ) ++ baseSettings)

lazy val root = (project in file("."))
  .aggregate(quixApi, quixCore, quixAthenaModule, quixBigqueryModule, quixJdbcModule, quixPrestoModule, quixPythonModule)
  .settings(
    crossScalaVersions := Nil,
    publish / skip := true,
  )


================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/db/Db.scala
================================================
package quix.api.v1.db

import monix.eval.Task

sealed case class Catalog(name: String,
                          children: List[Schema],
                          `type`: String = "catalog")

sealed case class Schema(name: String,
                         children: List[Table],
                         `type`: String = "schema")

sealed case class Table(name: String,
                        children: List[Kolumn],
                        `type`: String = "table")

sealed case class Kolumn(name: String,
                         dataType: String,
                         `type`: String = "column")

/** Db exposes database tree, supports autocomplete in quix editor and powers the DB search. */
trait Db {

  /** Supports up-to 4 levels of hierarchy : catalogs, schemas, tables and columns */
  def getCatalogs: Task[List[Catalog]]

  /** Returns list of all possible autocomplete items within different categories.
   * For example, in case of presto-module : catalogs, schemas, tables and columns.
   * */
  def getAutocomplete: Task[Map[String, List[String]]]

  /** Returns columns and types for a table identified by catalog, schema and table name */
  def getTable(catalog: String, schema: String, table: String): Task[Table]

  /** Returns list of catalogs filtered using a given substring */
  def search(query: String): Task[List[Catalog]]
}

/** Catalogs expose list of catalogs present within a module */
trait Catalogs {

  /** This method should return within under X milliseconds (configurable via .env) and will be called directly
   * from quix-frontend if db tree is empty */
  def fast: Task[List[Catalog]]

  /** This method isn't exposed to quix-frontend and will be called in background to cache the full db tree */
  def full: Task[List[Catalog]]
}

/** Autocomplete exposes list of categories and autocomplete items that belong to these categories.
 * For example, 'catalogs' might be a category and list of 'foo' and 'boo' might be catalogs
 * */
trait Autocomplete {
  def fast: Task[Map[String, List[String]]]

  def full: Task[Map[String, List[String]]]
}

/** Tables expose a way to get metadata of table */
trait Tables {

  /** This method will be called when user tries to expand a table in quix-frontend db tree */
  def get(catalog: String, schema: String, table: String): Task[Table]
}

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/execute/Api.scala
================================================
package quix.api.v1.execute

import java.io.IOException

import monix.eval.Task
import quix.api.v1.users.User

/** End consumer of quix backend messages.
 * In case of quix frontend, it is a websocket channel.
 *
 */
trait Consumer[Message] {
  def id: String

  def user: User

  @throws[IOException]
  def write(payload: Message): Task[Unit]

  @throws[IOException]
  def close(): Task[Unit]
}

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/execute/Batch.scala
================================================
package quix.api.v1.execute

case class BatchColumn(name: String)

case class BatchError(message: String)

/** Used in [[quix.api.v1.execute.Builder]] to send batched payloads from [[quix.api.v1.module.ExecutionModule]] to
 * [[quix.api.v1.execute.Consumer]]
 *
 * @param data list of rows
 * @param columns optional list of column names
 * @param error optional error
 * @param stats optional stats object for custom properties
 */
case class Batch(data: Seq[Seq[Any]] = Seq.empty,
                 columns: Option[Seq[BatchColumn]] = None,
                 error: Option[BatchError] = None,
                 stats: Map[String, Any] = Map.empty)


object Batch {
  val PERCENTAGE = "percentage"
  val STATUS = "status"
  val TYPE = "type"

  implicit class BatchStatsOps(val batch: Batch) extends AnyVal {
    def percentage = {
      batch.stats.get(PERCENTAGE) match {
        case Some(value: Int) => Some(value)
        case _ => None
      }
    }

    def queryType: Option[String] = {
      batch.stats.get(TYPE) match {
        case Some(value: String) => Some(value)
        case _ => None
      }
    }

    def withPercentage(percentage: Int): Batch = {
      batch.copy(stats = batch.stats.updated(PERCENTAGE, percentage))
    }

    def withStatus(status: String) = {
      batch.copy(stats = batch.stats.updated(STATUS, status))
    }

    def withType(queryType: String) = {
      batch.copy(stats = batch.stats.updated(TYPE, queryType))
    }
  }

}


================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/execute/ExecutionEngine.scala
================================================
package quix.api.v1.execute

import monix.eval.Task
import quix.api.v1.users.User


case class ActiveQuery[Code](id: String,
                             statements: Seq[Code],
                             user: User,
                             var current: Int = 0,
                             var isCancelled: Boolean = false,
                             var session: Map[String, Any] = Map.empty,
                             var catalog: Option[String] = None,
                             var schema: Option[String] = None) {
  def text = statements(current)
}


/**
 * Builder is used to propagate messages between AsyncQueryExecutor and quix frontend
 *
 * @tparam Code    designates type of incoming code, usually String
 * @tparam Results designates type of outgoing messages, usually [[quix.api.v1.execute.Batch]]
 */

trait Builder[Code, Results] {

  /** Sent when query is started */
  def start(query: ActiveQuery[Code]): Task[Unit]

  /** Sent when query is ended */
  def end(query: ActiveQuery[Code]): Task[Unit]

  /** Sent when query fails with exception */
  def error(queryId: String, e: Throwable): Task[Unit]

  /** Total counter of all rows */
  def rowCount: Long

  def lastError: Option[Throwable]

  /** Sent of every sub query start, each subquery will be shown in different tab in quix */
  def startSubQuery(subQueryId: String, code: Code, results: Results): Task[Unit]

  /** Used to stream results back to quix frontend */
  def addSubQuery(subQueryId: String, results: Results): Task[Unit]

  /** Sent of every sub query end, quix frontend will use it to stop populating currect tab */
  def endSubQuery(subQueryId: String, statistics: Map[String, Any] = Map.empty): Task[Unit]

  def errorSubQuery(subQueryId: String, e: Throwable): Task[Unit]

  /** Used to send different log messages.
   *
   * @param line  message to log
   * @param level supported levels are INFO and ERROR
   * */
  def log(queryId: String, line: String, level: String = "INFO"): Task[Unit]
}

/** Used to execute single query and stream the results back to Builder */
trait AsyncQueryExecutor[Code, Results] {
  def runTask(query: ActiveQuery[Code], builder: Builder[Code, Results]): Task[Unit]
}

/** Used to show exceptions in the quix frontend
 *
 * @param message the message will be shown to client as is
 **/
case class ExceptionPropagatedToClient(message: String) extends Exception

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/execute/ExecutionProtocol.scala
================================================
package quix.api.v1.execute

sealed trait EventData

/**
 * Event used to communicate changes
 *
 * @param event event name, shared between quix backend and quix frontend
 * @param data  data that arrives with every event
 */
sealed case class ExecutionEvent(event: String, data: EventData)

sealed case class Start(id: String, numOfQueries: Int) extends EventData

sealed case class Error(id: String, message: String) extends EventData

sealed case class End(id: String) extends EventData

sealed case class SubQueryStart(id: String) extends EventData

sealed case class SubQueryFields(id: String, fields: Seq[String]) extends EventData

sealed case class SubQueryDetails[Code](id: String, code: Code) extends EventData

sealed case class SubQueryEnd(id: String, statistics: Map[String, Any]) extends EventData

sealed case class SubQueryError(id: String, message: String) extends EventData

sealed case class Progress(id: String, percentage: Int) extends EventData

sealed case class Row(id: String, values: Seq[Any]) extends EventData

sealed case class Download(id: String, url: String) extends EventData

sealed case class StartCommand[Code](code: Code, session: Map[String, String]) extends EventData

sealed case class Log(id: String, line: String, level: String) extends EventData

object Empty extends EventData

object Start {
  def apply(id: String, numOfQueries: Int): ExecutionEvent = ExecutionEvent("start", new Start(id, numOfQueries))
}

object End {
  def apply(id: String): ExecutionEvent = ExecutionEvent("end", new End(id))
}


object SubQueryStart {
  def apply(id: String): ExecutionEvent = ExecutionEvent("query-start", new SubQueryStart(id))
}

object SubQueryDetails {
  def apply[Code](id: String, code: Code): ExecutionEvent = ExecutionEvent("query-details", new SubQueryDetails(id, code))
}

object SubQueryEnd {
  def apply(id: String, statistics: Map[String, Any] = Map.empty): ExecutionEvent = ExecutionEvent("query-end", new SubQueryEnd(id, statistics))
}

object SubQueryError {
  def apply(id: String, message: String): ExecutionEvent = ExecutionEvent("error", new SubQueryError(id, message))
}

object SubQueryFields {
  def apply(id: String, fields: Seq[String]): ExecutionEvent = ExecutionEvent("fields", new SubQueryFields(id, fields))
}

object Progress {
  def apply(id: String, percentage: Int): ExecutionEvent = ExecutionEvent("percentage", new Progress(id, percentage))
}

object Error {
  def apply(id: String, message: String): ExecutionEvent = ExecutionEvent("error", new Error(id, message))
}

object Row {
  def apply(id: String, values: Seq[Any]): ExecutionEvent = ExecutionEvent("row", new Row(id, values))
}

object Pong {
  def apply(id: String): ExecutionEvent = ExecutionEvent("pong", Empty)
}

object Download {
  def apply(id: String, url: String): ExecutionEvent = ExecutionEvent("query-download", new Download(id, url))
}

object Log {
  def apply(id: String, line: String, level: String): ExecutionEvent = ExecutionEvent("log", new Log(id, line, level))
}

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/module/ExecutionModule.scala
================================================
package quix.api.v1.module

import monix.eval.Task
import quix.api.v1.db.Db
import quix.api.v1.execute.{Builder, StartCommand}
import quix.api.v1.users.User

/** Every quix note type must implement ExecutionModule to support query execution and db tree exploration
 *
 * @tparam Code
 * @tparam Results
 */
trait ExecutionModule[Code, Results] {

  /** Describes execution of code passed via [[quix.api.v1.execute.StartCommand]] and invocations
   * of [[quix.api.v1.execute.Builder]] methods.
   *
   * @param command includes the code that must be executed. Might contains multiple statements
   * @param id      query id
   * @param user    user that asked to execute command
   * @param builder instance of [[quix.api.v1.execute.Builder]] that serves as communication channel to quix frontend
   * @return description of execution by means of [[monix.eval.Task]]
   */
  def start(command: StartCommand[Code], id: String, user: User, builder: Builder[Code, Results]): Task[Unit]

  /** Execution module might expose db tree that can be visualized and explored in quix frontend
   *
   * @return optional instance of db
   */
  def db: Option[Db]
}

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v1/users/Users.scala
================================================
package quix.api.v1.users

sealed case class User(email: String, id: String = "")

trait Users {
  @throws[RequestNotAuthenticated]
  def auth[T](headers: Map[String, String])(code: User => T): T
}

class DummyUsers(val user: String) extends Users {
  override def auth[T](headers: Map[String, String])(code: User => T): T = code(User(user))
}

case class RequestNotAuthenticated(msg: String) extends RuntimeException(msg)

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v2/execute/Builder.scala
================================================
package quix.api.v2.execute

import monix.eval.Task
import quix.api.v1.execute.Batch

/**
 * Builder is used to propagate messages between AsyncQueryExecutor and quix frontend
 *
 */
trait Builder {

  /** Sent when query is started */
  def start(query: Query): Task[Unit]

  /** Sent when query is ended */
  def end(query: Query): Task[Unit]

  /** Sent when query fails with exception */
  def error(queryId: String, e: Throwable): Task[Unit]

  /** Total counter of all rows */
  def rowCount: Long

  def lastError: Option[Throwable]

  /** Sent of every sub query start, each subquery will be shown in different tab in quix */
  def startSubQuery(subQueryId: String, code: String): Task[Unit]

  /** Used to stream results back to quix frontend */
  def addSubQuery(subQueryId: String, results: Batch): Task[Unit]

  /** Sent of every sub query end, quix frontend will use it to stop populating currect tab */
  def endSubQuery(subQueryId: String, stats: Map[String, Any] = Map.empty): Task[Unit]

  def errorSubQuery(subQueryId: String, e: Throwable): Task[Unit]

  /** Used to send different log messages.
   *
   * @param line  message to log
   * @param level supported levels are INFO and ERROR
   **/
  def log(subQueryId: String, line: String, level: String = "INFO"): Task[Unit]
}


================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v2/execute/ExecutionModule.scala
================================================
package quix.api.v2.execute

import monix.eval.Task
import quix.api.v1.db.Db
import quix.api.v1.execute.StartCommand
import quix.api.v1.users.User

/** Every quix note type must implement ExecutionModule to support query execution and db tree exploration
 */
trait ExecutionModule {

  /** Describes execution of code passed via [[quix.api.v1.execute.StartCommand]] and invocations
   * of [[quix.api.v1.execute.Builder]] methods.
   *
   * @param command includes the code that must be executed. Might contains multiple statements
   * @param id      query id
   * @param user    user that asked to execute command
   * @param builder instance of [[quix.api.v1.execute.Builder]] that serves as communication channel to quix frontend
   * @return description of execution by means of [[monix.eval.Task]]
   */
  def start(command: StartCommand[String], id: String, user: User, builder: Builder): Task[Unit]

  /** Execution module might expose db tree that can be visualized and explored in quix frontend
   *
   * @return optional instance of db
   */
  def db: Option[Db]
}

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v2/execute/Executor.scala
================================================
package quix.api.v2.execute

import monix.eval.Task

/** Used to execute single query and stream the results back to Builder */
trait Executor {
  def execute(query: SubQuery, builder: Builder): Task[Unit]
}


================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v2/execute/Session.scala
================================================
package quix.api.v2.execute

trait Session {
  def put(key: String, value: String)

  def remove(key: String)

  def get: Map[String, String]
}

class MutableSession(val session: () => Map[String, String] = () => Map.empty,
                     private var state: Map[String, String] = Map.empty) extends Session {
  override def put(key: String, value: String): Unit = state = state.updated(key, value)

  override def remove(key: String): Unit = state = state - key

  override def get: Map[String, String] = state
}

object MutableSession {
  def apply(kv: (String, String)*): MutableSession = new MutableSession(state = kv.toMap)

  def apply(session: () => Map[String, String]): MutableSession = new MutableSession(session = session)
}

================================================
FILE: quix-backend/quix-api/src/main/scala/quix/api/v2/execute/SubQuery.scala
================================================
package quix.api.v2.execute

import java.util.UUID

import monix.execution.atomic.Atomic
import quix.api.v1.users.User

trait SubQuery {
  def id: String

  def text: String

  def session: Session

  def user: User

  def canceled: Atomic[Boolean]
}

case class ImmutableSubQuery(text: String, user: User,
                             canceled: Atomic[Boolean] = Atomic(false),
                             id: String = UUID.randomUUID().toString,
                             session: Session = new MutableSession) extends SubQuery

case class Query(subQueries: Seq[SubQuery],
                 id: String = UUID.randomUUID().toString,
                 canceled: Atomic[Boolean] = Atomic(false),
                 rawCode: String = "")

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/db/DbOps.scala
================================================
package quix.core.db

import com.typesafe.scalalogging.LazyLogging
import quix.api.v1.db.Catalog

object DbOps extends LazyLogging {
  def mergeNewAndOldCatalogs(newCatalogs: List[Catalog], oldCatalogs: List[Catalog]): List[Catalog] = {
    newCatalogs.map { newCatalog =>
      val maybeOldCatalog = oldCatalogs.find(_.name == newCatalog.name)

      (newCatalog, maybeOldCatalog) match {
        case (_, None) =>
          newCatalog

        case (_, Some(oldCatalog)) if newCatalog.children.isEmpty =>
          logger.warn("Catalog " + newCatalog + "is empty")
          oldCatalog

        case _ =>
          newCatalog
      }
    }
  }

  def search(catalogs: List[Catalog], query: String): List[Catalog] = search(catalogs, DbQuery(query))

  def search(catalogs: List[Catalog], query: DbQuery): List[Catalog] = {
    val filtered = catalogs.map {

      case catalog if query.matches(catalog.name) =>
        catalog

      case catalog =>
        val schemas = catalog.children

        val filtered = schemas.map {
          case schema if query.matches(schema.name) =>
            schema

          case schema =>
            val tables = schema.children
            val filtered = tables.filter(table => query.matches(table.name))

            schema.copy(children = filtered)
        }.filter(schema => schema.children.nonEmpty || query.matches(schema.name))

        catalog.copy(children = filtered)
    }.filter(catalog => catalog.children.nonEmpty || query.matches(catalog.name))

    filtered
  }
}

trait DbQuery {
  def matches(name: String): Boolean
}

object DbQuery {
  def apply(query: String): DbQuery = {
    query match {

      case null =>
        DbQueryFalse

      case query if isExactMatch(query) =>
        new DbQueryExactMatch(query.substring(1, query.length - 1))

      case _ =>
        new DbQueryContains(query)
    }
  }

  private def isExactMatch(query: String) = {
    query.startsWith("\"") & query.endsWith("\"") || query.startsWith("'") & query.endsWith("'")
  }
}

class DbQueryContains(query: String) extends DbQuery {
  override def matches(name: String): Boolean = name.contains(query)
}

class DbQueryExactMatch(query: String) extends DbQuery {
  override def matches(name: String): Boolean = query == name
}

object DbQueryFalse extends DbQuery {
  override def matches(name: String): Boolean = false
}

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/db/RefreshableAutocomplete.scala
================================================
package quix.core.db

import monix.eval.Task
import quix.api.v1.db.Autocomplete

import scala.concurrent.duration._

class RefreshableAutocomplete(autocomplete: Autocomplete,
                              timeoutInMillis: Long,
                              staleThreshold: Long,
                              var state: State[Map[String, List[String]]] = State(Map.empty, 0L)) {
  def get: Task[Map[String, List[String]]] = {
    state match {
      case State(data, _) if data.isEmpty =>
        for {
          _ <- startUpdate()

          newCatalogs <-
          autocomplete.fast
            .flatMap(update)
            .timeout(timeoutInMillis.millis)
            .onErrorFallbackTo(Task.now(state.data))

          _ <- autocomplete.full
            .flatMap(update)
            .attempt.start
        } yield newCatalogs

      case State(_, expirationDate) if expirationDate < System.currentTimeMillis() =>
        for {
          _ <- startUpdate()
          _ <- autocomplete.full
            .flatMap(update)
            .attempt.start
        } yield state.data

      case _ => Task.now(state.data)
    }
  }

  def startUpdate() = {
    Task(this.state = this.state.copy(expirationDate = System.currentTimeMillis() + staleThreshold))
  }

  def update(newData: Map[String, List[String]]) = {
    Task {
      this.state = this.state.copy(data = newData)
      newData
    }
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/db/RefreshableCatalogs.scala
================================================
package quix.core.db

import monix.eval.Task
import quix.api.v1.db.{Catalog, Catalogs}

import scala.concurrent.duration._

class RefreshableCatalogs(catalogs: Catalogs,
                          timeoutInMillis: Long,
                          staleThreshold: Long,
                          var state: State[List[Catalog]] = State(Nil, 0L)) {

  def get: Task[List[Catalog]] = {
    state match {
      case State(data, _) if data.isEmpty =>
        for {
          _ <- startUpdate()

          newCatalogs <-
          catalogs.fast
            .flatMap(update)
            .timeout(timeoutInMillis.millis)
            .onErrorFallbackTo(Task.now(state.data))

          _ <- catalogs.full
            .flatMap(update)
            .attempt.start
        } yield newCatalogs

      case State(_, expirationDate) if expirationDate < System.currentTimeMillis() =>
        for {
          _ <- startUpdate()
          _ <- catalogs.full
            .flatMap(update)
            .attempt.start
        } yield state.data

      case _ => Task.now(state.data)
    }
  }

  def startUpdate() = {
    Task(this.state = this.state.copy(expirationDate = System.currentTimeMillis() + staleThreshold))
  }

  def update(newCatalogs: List[Catalog]) = {
    Task {
      this.state = this.state.copy(data = newCatalogs)
      newCatalogs
    }
  }

}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/db/RefreshableDb.scala
================================================
package quix.core.db

import monix.eval.Task
import quix.api.v1.db.{Catalog, Db, Table, Tables}

class RefreshableDb(catalogs: RefreshableCatalogs, autocomplete: RefreshableAutocomplete, tables: Tables) extends Db {

  override def getCatalogs: Task[List[Catalog]] =
    catalogs.get

  override def getAutocomplete: Task[Map[String, List[String]]] =
    autocomplete.get

  override def getTable(catalog: String, schema: String, table: String): Task[Table] =
    tables.get(catalog, schema, table)

  override def search(query: String): Task[List[Catalog]] =
    catalogs.get.map(c => DbOps.search(c, query))
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/db/State.scala
================================================
package quix.core.db

case class State[T](data: T, expirationDate: Long)

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/download/DownloadConfig.scala
================================================
package quix.core.download

import java.io.InputStream
import java.nio.file.{Files, Path, Paths}
import java.util.zip.GZIPInputStream

import com.amazonaws.auth.{AWSStaticCredentialsProvider, BasicAWSCredentials}
import com.amazonaws.services.s3.{AmazonS3, AmazonS3ClientBuilder}
import com.typesafe.scalalogging.LazyLogging
import monix.eval.Task

case class DownloadConfig(downloadDir: String, cloudConfig: Map[String, String] = Map.empty)

trait QueryResultsStorage {
  def upload(queryId: String, file: Path): Task[Unit]

  def exists(queryId: String): Task[Boolean]

  def delete(queryId: String): Task[Unit]

  def getInputStream(queryId: String): Task[InputStream]
}

object QueryResultsStorage {
  def apply(config: DownloadConfig): QueryResultsStorage = {
    config.cloudConfig match {
      case _ if hasS3Keys(config.cloudConfig) =>
        initS3(config.cloudConfig)
      case _ =>
        initLocalFS(config)
    }
  }

  def hasS3Keys(config: Map[String, String]) = {
    config.keySet.contains("accessKey") &&
      config.keySet.contains("secretKey") &&
      config.keySet.contains("region") &&
      config.keySet.contains("bucket")
  }

  def initS3(config: Map[String, String]): QueryResultsStorage = {
    val accessKey = config("accessKey")
    val secretKey = config("secretKey")
    val region = config("region")
    val bucket = config("bucket")

    val credentials = new AWSStaticCredentialsProvider(new BasicAWSCredentials(accessKey, secretKey))

    val amazonS3Client: AmazonS3 = AmazonS3ClientBuilder
      .standard()
      .withCredentials(credentials)
      .withRegion(region)
      .build()

    new QueryResultsStorage with LazyLogging {
      override def upload(queryId: String, file: Path): Task[Unit] = Task {
        logger.info(s"event=s3-upload-start query-id=$queryId file=$file size=${Files.size(file)}")
        amazonS3Client.putObject(bucket, queryId, file.toFile)
        logger.info(s"event=s3-upload-done query-id=$queryId file=$file size=${Files.size(file)}")
      }

      override def getInputStream(queryId: String): Task[InputStream] = Task {
        logger.info(s"event=s3-get-inputstream-start query-id=$queryId")
        val is = new GZIPInputStream(amazonS3Client.getObject(bucket, queryId).getObjectContent)
        logger.info(s"event=s3-get-inputstream-done query-id=$queryId")
        is
      }

      override def exists(queryId: String): Task[Boolean] = Task {
        logger.info(s"event=s3-exists-start query-id=$queryId")
        val response = amazonS3Client.doesObjectExist(bucket, queryId)
        logger.info(s"event=s3-exists-done query-id=$queryId response=$response")
        response
      }

      override def delete(queryId: String): Task[Unit] = Task {
        logger.info(s"event=s3-delete-start query-id=$queryId")
        amazonS3Client.deleteObject(bucket, queryId)
        logger.info(s"event=s3-delete-done query-id=$queryId")
      }
    }
  }

  def initLocalFS(config: DownloadConfig): QueryResultsStorage = {
    new QueryResultsStorage {
      override def upload(queryId: String, file: Path): Task[Unit] = Task.unit

      override def getInputStream(queryId: String): Task[InputStream] = Task {
        val path = Paths.get(config.downloadDir, queryId)
        new GZIPInputStream(Files.newInputStream(path))
      }

      override def exists(queryId: String): Task[Boolean] = Task(Files.exists(Paths.get(config.downloadDir, queryId)))

      override def delete(queryId: String): Task[Unit] = Task(Files.deleteIfExists(Paths.get(config.downloadDir, queryId)))
    }
  }
}

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/download/DownloadableBuilder.scala
================================================
package quix.core.download

import com.opencsv.CSVWriter
import monix.eval.Task
import quix.api.v1.execute.{Builder => _, _}
import quix.api.v2.execute._
import quix.core.executions.DelegatingBuilder

import java.io.{BufferedWriter, OutputStream, OutputStreamWriter}
import java.nio.file.{Files, Paths}
import java.util.concurrent.ConcurrentHashMap
import java.util.zip.GZIPOutputStream

class DownloadableBuilder[Code](delegate: Builder,
                                downloadConfig: DownloadConfig,
                                queryResultsStorage: QueryResultsStorage,
                                consumer: Consumer[ExecutionEvent])
  extends DelegatingBuilder(delegate) {
  val sentColumnsPerQuery = collection.mutable.Set.empty[String]
  val openStreams = new ConcurrentHashMap[String, OutputStream]

  override def startSubQuery(subQueryId: String, code: String): Task[Unit] = {
    for {
      _ <- delegate.startSubQuery(subQueryId, code)
      _ <- createNewFile(subQueryId)
    } yield ()
  }

  override def addSubQuery(subQueryId: String, results: Batch): Task[Unit] = {
    sendColumns(subQueryId, results.columns) >>
      use(subQueryId, results.data)
  }

  override def endSubQuery(subQueryId: String, stats: Map[String, Any]): Task[Unit] = {
    for {
      _ <- delegate.endSubQuery(subQueryId, stats).attempt
      _ <- close(subQueryId)
      _ <- consumer.write(Download(subQueryId, "/api/download/" + subQueryId))
      _ <- Task(sentColumnsPerQuery.remove(subQueryId))
    } yield ()
  }

  override def errorSubQuery(subQueryId: String, e: Throwable): Task[Unit] = {
    for {
      _ <- delegate.errorSubQuery(subQueryId, e).attempt
      _ <- cancel(subQueryId)
      _ <- Task(sentColumnsPerQuery.remove(subQueryId))
    } yield ()
  }

  def sendColumns(subQueryId: String, columnsOpt: Option[Seq[BatchColumn]]) = {
    columnsOpt match {
      case Some(columns) if !sentColumnsPerQuery.contains(subQueryId) =>
        use(subQueryId, Seq(columns.map(_.name))) >>
          Task(sentColumnsPerQuery.add(subQueryId))

      case _ => Task.unit

    }
  }

  def createNewFile(subQueryId: String): Task[Unit] = {
    val path = Paths.get(downloadConfig.downloadDir, subQueryId)

    val writerTask = Task(Files.createDirectories(Paths.get(downloadConfig.downloadDir))) >>
      Task(Files.deleteIfExists(path)) >>
      Task(Files.createFile(path)) >>
      Task(new GZIPOutputStream(Files.newOutputStream(path)))

    for {
      writer <- writerTask
      _ <- Task(openStreams.put(subQueryId, writer))
    } yield writer
  }

  def use(subQueryId: String, rows: Seq[Seq[Any]]): Task[Unit] = Task {
    val stream = openStreams.get(subQueryId)
    val writer = new CSVWriter(new BufferedWriter(new OutputStreamWriter(stream, "UTF-8")))

    if (rows.nonEmpty && stream != null) {
      rows.foreach(row => writer.writeNext(row.toArray.map(nullToEmpty), true))
      writer.flush()
    }
  }

  def nullToEmpty(any: Any): String = if (any == null) "" else any.toString

  def close(subQueryId: String): Task[Unit] = {
    val path = Paths.get(downloadConfig.downloadDir, subQueryId)

    openStreams.get(subQueryId) match {
      case null => Task.unit
      case stream =>
        Task(stream.flush()).attempt >>
          Task(stream.close()).attempt >>
          Task(openStreams.remove(subQueryId)) >>
          queryResultsStorage.upload(subQueryId, path)
    }
  }

  def cancel(subQueryId: String): Task[Unit] = {
    val path = Paths.get(downloadConfig.downloadDir, subQueryId)

    close(subQueryId) >> Task(Files.deleteIfExists(path))
  }

}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/executions/DelegatingBuilder.scala
================================================
package quix.core.executions

import quix.api.v1.execute.Batch
import quix.api.v2.execute._

abstract class DelegatingBuilder(val delegate: Builder) extends Builder {

  override def start(query: Query) =
    delegate.start(query)

  override def end(query: Query) =
    delegate.end(query)

  override def error(queryId: String, e: Throwable) =
    delegate.error(queryId, e)

  override def rowCount: Long =
    delegate.rowCount

  override def lastError: Option[Throwable] =
    delegate.lastError

  override def startSubQuery(subQueryId: String, code: String) =
    delegate.startSubQuery(subQueryId, code)

  override def addSubQuery(subQueryId: String, results: Batch) =
    delegate.addSubQuery(subQueryId, results)

  override def endSubQuery(subQueryId: String, stats: Map[String, Any]) =
    delegate.endSubQuery(subQueryId, stats)

  override def errorSubQuery(subQueryId: String, e: Throwable) =
    delegate.errorSubQuery(subQueryId, e)

  override def log(subQueryId: String, line: String, level: String) =
    delegate.log(subQueryId, line, level)
}

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/executions/SingleQueryExecutor.scala
================================================
package quix.core.executions

import monix.eval.Task
import quix.api.v1.users.User
import quix.api.v2.execute.{Executor, ImmutableSubQuery}
import quix.core.results.SingleBuilder

/** SingleQueryExecutor exposes useful methods for executing single queries with small amount of rows */
trait SingleQueryExecutor {
  val queryExecutor: Executor

  val user = User("quix-db-tree")

  /** @param sql  sql that when executed will return small amount of results
   * @param delim delimiter that will be used to concatenate each row produced by sql
   * @return list of rows, if row is made of more than one column, they will be concatenated with delim
   **/
  def executeForSingleColumn(sql: String, delim: String = ""): Task[List[String]] = {
    executeFor[String](sql, x => x.mkString(delim))
  }

  /** @param sql         Sql that when executed will return small amount of results
   * @param resultMapper Function that will be applied to each row
   * @return Returns list of T produced by applying resultMapper on each row
   */
  def executeFor[T](sql: String, resultMapper: List[String] => T): Task[List[T]] = {
    val subQuery = ImmutableSubQuery(sql, user)
    val resultBuilder = new SingleBuilder
    for {
      _ <- queryExecutor.execute(subQuery, resultBuilder)
      results <- Task(
        resultBuilder.build()
          .map(row => resultMapper(row.map(_.toString).toList))
      )
      _ <- if (resultBuilder.isFailure) {
        Task.raiseError(new Exception("query failed"))
      } else {
        Task.unit
      }

    } yield results
  }
}

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/executions/SqlModule.scala
================================================
package quix.core.executions

import monix.eval.Task
import quix.api.v1.db.Db
import quix.api.v1.execute.StartCommand
import quix.api.v1.users.User
import quix.api.v2.execute._
import quix.core.sql.{PrestoLikeSplitter, SqlSplitter}

class SqlModule(val executor: Executor,
                val db: Option[Db],
                val splitter: SqlSplitter = PrestoLikeSplitter) extends ExecutionModule {

  override def start(command: StartCommand[String], id: String, user: User, builder: Builder): Task[Unit] = {
    val query = splitter.split(command, id, user)

    for {
      _ <- builder.start(query)
      _ <- Task.traverse(query.subQueries) { q =>
        Task(builder.lastError).flatMap {
          case None =>
            executor.execute(q, builder)
          case Some(e) =>
            Task.raiseError(e)
        }
      }.attempt
      _ <- builder.end(query)
    } yield ()
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/history/Execution.scala
================================================
package quix.core.history

import java.time.Instant

import quix.api.v1.users.User

case class Execution(id: String,
                     queryType: String,
                     statements: Seq[String],
                     code: String,
                     user: User,
                     startedAt: Instant,
                     status: ExecutionStatus)

sealed trait ExecutionStatus

object ExecutionStatus {
  case object Running extends ExecutionStatus
  case object Finished extends ExecutionStatus
  case object Failed extends ExecutionStatus
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/history/HistoryBuilder.scala
================================================
package quix.core.history

import monix.eval.Task
import quix.api.v1.execute.Batch
import quix.api.v2.execute.{Builder, Query}
import quix.core.history.dao.HistoryWriteDao

class HistoryBuilder[Results](delegate: Builder,
                              historyWriteDao: HistoryWriteDao,
                              queryType: String)
  extends Builder {

  override def start(query: Query): Task[Unit] =
    delegate.start(query).flatMap(_ => historyWriteDao.executionStarted(query, queryType))

  override def end(query: Query): Task[Unit] =
    delegate.end(query).flatMap(_ => historyWriteDao.executionSucceeded(query.id))

  override def error(queryId: String, e: Throwable): Task[Unit] =
    delegate.error(queryId, e).flatMap(_ => historyWriteDao.executionFailed(queryId, e))

  override def rowCount: Long =
    delegate.rowCount

  override def lastError: Option[Throwable] =
    delegate.lastError

  override def startSubQuery(subQueryId: String, code: String): Task[Unit] =
    delegate.startSubQuery(subQueryId, code)

  override def addSubQuery(subQueryId: String, results: Batch): Task[Unit] =
    delegate.addSubQuery(subQueryId, results)

  override def endSubQuery(subQueryId: String, stats: Map[String, Any]): Task[Unit] =
    delegate.endSubQuery(subQueryId, stats)

  override def errorSubQuery(subQueryId: String, e: Throwable): Task[Unit] =
    delegate.errorSubQuery(subQueryId, e)

  override def log(subQueryId: String, line: String, level: String): Task[Unit] =
    delegate.log(subQueryId, line, level)

}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/history/dao/HistoryReadDao.scala
================================================
package quix.core.history.dao

import monix.eval.Task
import quix.core.history.{Execution, ExecutionStatus}

import scala.collection.mutable.ListBuffer

trait HistoryReadDao {
  def executions(filter: Filter = Filter.None,
                 sort: Sort = Sort.Default,
                 page: Page = Page.First): Task[List[Execution]]
}

sealed trait Filter

object Filter {

  case object None extends Filter

  case class Status(status: ExecutionStatus) extends Filter

  case class User(email: String) extends Filter

  case class Query(query: String) extends Filter

  case class QueryType(queryType: String) extends Filter

  case class CompoundFilter(filters: List[Filter]) extends Filter

  def apply(userEmail: String, query: String): Filter = apply(userEmail, query, "")

  def apply(userEmail: String, query: String, queryType: String): Filter = {
    var filters = ListBuffer.empty[Filter]

    if (userEmail.nonEmpty) filters += User(userEmail)
    if (query.nonEmpty) filters += Query(query)
    if (queryType.nonEmpty) filters += QueryType(queryType)

    filters.toList match {
      case Nil => None
      case List(single) => single
      case many => CompoundFilter(many)
    }
  }

}

case class Sort(by: SortField, order: SortOrder)

object Sort {
  val Default = Sort(SortField.StartTime, SortOrder.Descending)
}

sealed trait SortField

object SortField {

  case object StartTime extends SortField

}

sealed trait SortOrder

object SortOrder {

  case object Ascending extends SortOrder

  case object Descending extends SortOrder

}

trait Page {
  def offset: Int

  def limit: Int

  def endOffset: Int = offset + limit
}

object Page {
  val DefaultLimit = 20
  val MaxLimit = 1000
  val First = Page(0, DefaultLimit)

  def apply(offset: Int, limit: Int): Page = {
    val offset1 = offset max 0
    val limit1 = limit min MaxLimit
    new Page {
      override val offset: Int = offset1
      override val limit: Int = limit1
    }
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/history/dao/HistoryWriteDao.scala
================================================
package quix.core.history.dao

import monix.eval.Task
import quix.api.v2.execute.Query

trait HistoryWriteDao {
  def executionStarted(query: Query, queryType: String): Task[Unit]

  def executionSucceeded(queryId: String): Task[Unit]

  def executionFailed(queryId: String, error: Throwable): Task[Unit]
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/history/dao/InMemoryHistoryDao.scala
================================================
package quix.core.history.dao

import java.time.Clock

import cats.effect.concurrent.Ref
import monix.eval.Task
import quix.api.v2.execute.Query
import quix.core.history.dao.InMemoryHistoryDao.{comparator, predicate}
import quix.core.history.{Execution, ExecutionStatus}

case class InMemoryHistoryDao(state: Ref[Task, Map[String, Execution]], clock: Clock)
  extends HistoryWriteDao with HistoryReadDao {

  private val instant = Task(clock.instant)

  override def executionStarted(query: Query, queryType: String): Task[Unit] =
    instant.flatMap { now =>
      val execution = Execution(
        id = query.id,
        queryType = queryType,
        statements = query.subQueries.map(_.text),
        code = query.rawCode,
        user = query.subQueries.map(_.user).head,
        startedAt = now,
        status = ExecutionStatus.Running)

      state.update(_ + (query.id -> execution))
    }

  override def executionSucceeded(queryId: String): Task[Unit] =
    update(queryId, _.copy(status = ExecutionStatus.Finished))

  override def executionFailed(queryId: String, error: Throwable): Task[Unit] =
    update(queryId, _.copy(status = ExecutionStatus.Failed))

  override def executions(filter: Filter, sort: Sort, page: Page): Task[List[Execution]] =
    state.get.map { map =>
      map.values.toList
        .filter(predicate(filter))
        .sortWith(comparator(sort))
        .slice(page.offset, page.endOffset)
    }

  private def update(queryId: String, f: Execution => Execution): Task[Unit] =
    state.update { map =>
      map.get(queryId).fold(map) { execution =>
        map + (queryId -> f(execution))
      }
    }

}

object InMemoryHistoryDao {
  def make(clock: Clock): Task[InMemoryHistoryDao] =
    Ref.of[Task, Map[String, Execution]](Map.empty).map(InMemoryHistoryDao(_, clock))

  def predicate(filter: Filter)(execution: Execution): Boolean = filter match {
    case Filter.None => true

    case Filter.Status(status) =>
      execution.status == status

    case Filter.User(email) =>
      execution.user.email == email

    case Filter.QueryType(queryType) =>
      execution.queryType == queryType

    case Filter.Query(text) =>
      execution.code.toLowerCase.contains(text.toLowerCase())

    case Filter.CompoundFilter(filters) =>
      filters.forall(filter => predicate(filter)(execution))
  }

  def comparator(sort: Sort)(e1: Execution, e2: Execution): Boolean = sort match {
    case Sort(SortField.StartTime, SortOrder.Ascending) =>
      e1.startedAt isBefore e2.startedAt

    case Sort(SortField.StartTime, SortOrder.Descending) =>
      e1.startedAt isAfter e2.startedAt
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/history/dao/MySqlHistoryDao.scala
================================================
package quix.core.history.dao

import java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}
import java.time.{Clock, Instant}

import cats.effect.Resource
import monix.eval.Task
import quix.api.v1.users.User
import quix.api.v2.execute.{Query => ActiveQuery}
import quix.core.history.dao.MySqlHistoryDao._
import quix.core.history.{Execution, ExecutionStatus}

class MySqlHistoryReadDao(connection: Connection) extends HistoryReadDao {

  override def executions(filter: Filter, sort: Sort, page: Page): Task[List[Execution]] = {
    val insertStatement = prepare(connection) {
      s"""
        SELECT id, query_type, statements, code, user_id, user_email, created_at, status
        FROM executions_history
        WHERE ${where(filter)}
        ${orderBy(sort)}
        LIMIT ?, ?
      """
    }

    insertStatement.use { statement =>
      for {
        _ <- Task(statement.setInt(1, page.offset))
        _ <- Task(statement.setInt(2, page.limit))
        rows <- Task(statement.executeQuery()).bracket(getRows(getExecution))(rs => Task(rs.close()))
      } yield rows.reverse
    }
  }

  private def where(filter: Filter): String = filter match {
    case Filter.Status(status) => s"status = '${status.toString.toUpperCase}'"
    case Filter.User(userEmail) => s"user_email = '$userEmail'"
    case Filter.Query(query) => s"code like '%$query%'"
    case Filter.QueryType(queryType) => s"query_type = '$queryType'"
    case Filter.CompoundFilter(filters) => filters.map(where).mkString(" and ")
    case Filter.None => "1 = 1"
  }

  private def orderBy(sort: Sort): String =
    s"ORDER BY ${field(sort.by)} ${order(sort.order)}"

  private def field(sortField: SortField): String = sortField match {
    case SortField.StartTime => "created_at"
  }

  private def order(sortOrder: SortOrder): String = sortOrder match {
    case SortOrder.Descending => "DESC"
    case SortOrder.Ascending => "ASC"
  }

  private def getRows[A](getRow: ResultSet => Task[A])(resultSet: ResultSet): Task[List[A]] = {
    Task(resultSet.next()).flatMapLoop(List.empty[A]) { (hasRow, rows, continue) =>
      if (hasRow) getRow(resultSet).flatMap(row => continue(row :: rows))
      else Task.now(rows)
    }
  }

  private def getExecution(resultSet: ResultSet): Task[Execution] = for {
    id <- Task(resultSet.getString("id"))
    queryType <- Task(resultSet.getString("query_type"))
    statements <- Task(resultSet.getString("statements"))
    code <- Task(resultSet.getString("code"))
    userEmail <- Task(resultSet.getString("user_email"))
    userId <- Task(resultSet.getString("user_id"))
    createdAt <- Task(resultSet.getLong("created_at"))
    status <- Task(resultSet.getString("status"))
  } yield Execution(
    id = id,
    queryType = queryType,
    statements = statements.split(separator),
    code = code,
    user = User(userEmail, userId),
    startedAt = Instant.ofEpochMilli(createdAt),
    status = statusFrom(status))

  private def statusFrom(status: String): ExecutionStatus = status match {
    case "RUNNING" => ExecutionStatus.Running
    case "FINISHED" => ExecutionStatus.Finished
    case _ => ExecutionStatus.Failed
  }

}

class MySqlHistoryWriteDao(connection: Connection, clock: Clock) extends HistoryWriteDao {

  private val instant = Task(clock.instant())

  private val startStatement = prepare(connection) {
    """
      INSERT INTO executions_history (id, query_type, statements, code, user_id, user_email, created_at)
      VALUES (?, ?, ?, ?, ?, ?, ?)
    """
  }

  private val succeedStatement = prepare(connection) {
    "UPDATE executions_history SET status = 'FINISHED' WHERE id = ? LIMIT 1"
  }

  private val failStatement = prepare(connection) {
    "UPDATE executions_history SET status = 'FAILED' WHERE id = ? LIMIT 1"
  }

  override def executionStarted(query: ActiveQuery, queryType: String): Task[Unit] =
    startStatement.use { statement =>
      for {
        now <- instant
        _ <- Task(statement.setString(1, query.id))
        _ <- Task(statement.setString(2, queryType))
        _ <- Task(statement.setString(3, query.subQueries.map(_.text).mkString(separator)))
        _ <- Task(statement.setString(4, query.rawCode))
        _ <- Task(statement.setString(5, query.subQueries.map(_.user).head.id))
        _ <- Task(statement.setString(6, query.subQueries.map(_.user).head.email))
        _ <- Task(statement.setLong(7, now.toEpochMilli))
        _ <- Task(statement.executeUpdate())
      } yield ()
    }

  override def executionSucceeded(queryId: String): Task[Unit] =
    succeedStatement.use { statement =>
      Task(statement.setString(1, queryId)) *>
        Task(statement.executeUpdate())
    }

  override def executionFailed(queryId: String, error: Throwable): Task[Unit] =
    failStatement.use { statement =>
      Task(statement.setString(1, queryId)) *>
        Task(statement.executeUpdate())
    }

}

case class JdbcConfig(url: String, user: String, pass: String)

object MySqlHistoryDao {
  val separator = ";"

  def connect(config: JdbcConfig): Resource[Task, Connection] = {
    val acquire = Task(DriverManager.getConnection(config.url, config.user, config.pass))
    Resource.make(acquire)(connection => Task(connection.close()))
  }

  def prepare(connection: Connection)(sql: String): Resource[Task, PreparedStatement] =
    Resource.make(Task(connection.prepareStatement(sql)))(statement => Task(statement.close()))
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/results/MultiBuilder.scala
================================================
package quix.core.results

import com.typesafe.scalalogging.LazyLogging
import monix.eval.Task
import quix.api.v1.execute.Batch._
import quix.api.v1.execute.{Batch, BatchColumn, BatchError, Consumer, End, Error, ExceptionPropagatedToClient, ExecutionEvent, Log, Progress, Row, Start, SubQueryDetails, SubQueryEnd, SubQueryError, SubQueryFields, SubQueryStart}
import quix.api.v2.execute._

/** MultiBuilder accepts Consumer[ExecutionEvent] and propagates to it different events from lifecycle of Builder.
 * For example, {{{start(query: Execution)}}} will produce {{{Start(query.id, query.statements.size)}}}
 * */
class MultiBuilder(val consumer: Consumer[ExecutionEvent])
  extends Builder with LazyLogging {

  var rows = 0L
  val sentColumnsPerQuery = collection.mutable.Set.empty[String]
  var lastError: Option[Throwable] = None

  override def start(query: Query) = {
    consumer.write(Start(query.id, query.subQueries.size))
  }

  override def end(query: Query) = {
    consumer.write(End(query.id))
  }

  override def startSubQuery(subQueryId: String, code : String) = {
    val resetCount = Task(this.rows = 0L)
    val startTask = consumer.write(SubQueryStart(subQueryId))
    val detailsTask = consumer.write(SubQueryDetails(subQueryId, code))

    Task.sequence(List(resetCount, startTask, detailsTask)).map(_ => ())
  }

  override def endSubQuery(subQueryId : String, stats : Map[String, Any]) = {
    consumer.write(SubQueryEnd(subQueryId, stats))
  }

  override def addSubQuery(subQueryId : String, results: Batch) = {
    val columnTask: Task[Unit] = results.columns.map(columns => sendColumns(subQueryId, columns)).getOrElse(Task.unit)
    val progressTask: Task[Unit] = results.percentage.map(percentage => sendProgress(subQueryId, percentage)).getOrElse(Task.unit)
    val errorTask: Task[Unit] = results.error.map(error => sendErrors(subQueryId, error)).getOrElse(Task.unit)

    rows += results.data.size

    val rowTask = Task.traverse(results.data) { row =>
      consumer.write(Row(subQueryId, row))
    }

    Task.sequence(Seq(columnTask, progressTask, errorTask, rowTask)).map(_ => ())
  }

  def sendErrors(queryId: String, prestoError: BatchError) = {
    lastError = Some(new RuntimeException(prestoError.message))
    consumer.write(Error(queryId, prestoError.message))
  }

  def sendProgress(queryId: String, percentage: Int) = {
    consumer.write(Progress(queryId, percentage))
  }

  override def errorSubQuery(subQueryId: String, e: Throwable) = {
    lastError = Some(e)
    val errorMessage = makeErrorMessage(e)
    consumer.write(SubQueryError(subQueryId, errorMessage))
  }

  private def makeErrorMessage(e: Throwable) = {
    e match {
      case ExceptionPropagatedToClient(message) => message
      case _ => s"${e.getClass.getSimpleName}(${e.getMessage})"
    }
  }

  /** Sends to consumer SubQueryFields on every unique queryId.
   * Every query can have only single list of columns, so no duplications are allowed.
   *  */
  def sendColumns(queryId: String, names: Seq[BatchColumn]) = {
    val sentColumns = sentColumnsPerQuery.contains(queryId)
    if (!sentColumns && names.nonEmpty) {
      sentColumnsPerQuery += queryId
      consumer.write(SubQueryFields(queryId, names.map(_.name)))
    } else Task.unit
  }

  override def rowCount: Long = rows

  override def error(queryId: String, e: Throwable) = {
    lastError = Some(e)
    val errorMessage = makeErrorMessage(e)
    consumer.write(Error(queryId, errorMessage))
  }

  override def log(subQueryId: String, line: String, level: String): Task[Unit] = {
    consumer.write(Log(subQueryId, line, level))
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/results/SingleBuilder.scala
================================================
package quix.core.results

import com.typesafe.scalalogging.LazyLogging
import monix.eval.Task
import quix.api.v1.execute.{Batch, BatchColumn}
import quix.api.v2.execute.{Builder, Query}

import scala.collection.mutable.ListBuffer

/** SingleBuilder accepts rows and stores them in memory in order of their arrival.
 * SingleBuilder is used by internal quix-backend processes such as db-tree traversal
 * or E2E tests. To receive the rows collected so far, one must call builder.build() */
class SingleBuilder extends Builder with LazyLogging {

  private val rows = ListBuffer.empty[Seq[Any]]
  private val headers = ListBuffer.empty[BatchColumn]
  private var failureCause: Option[Throwable] = None
  private var logMessages = ListBuffer.empty[String]
  private var statistics = Map.empty[String, Any]
  private val queriesStatuses = ListBuffer.empty[QueryStatus]

  /**
   * @returns the rows collected so far */
  def build(): List[Seq[Any]] = rows.toList

  override def errorSubQuery(subQueryId: String, e: Throwable) = Task {
    queriesStatuses += QueryFailed(subQueryId, e.getMessage)
    failureCause = Option(e)
  }

  override def startSubQuery(subQueryId: String, code: String) = Task {
    queriesStatuses += QueryStarted(subQueryId, code)
  }

  override def addSubQuery(subQueryId: String, results: Batch) = handleBatch(results)

  def handleBatch(batch: Batch): Task[Unit] = Task {
    batch.error foreach { error =>
      failureCause = Option(new RuntimeException(error.message))
    }

    for {
      newHeaders <- batch.columns if headers.isEmpty
    } headers ++= newHeaders

    rows ++= batch.data
  }

  override def endSubQuery(subQueryId: String, stats: Map[String, Any]) = Task {
    queriesStatuses += QueryFinished(subQueryId)
    this.statistics = stats
  }

  override def start(query: Query) = Task.unit

  override def end(query: Query) = Task.unit

  def isFailure = failureCause.isDefined

  override def rowCount: Long = rows.size

  override def lastError: Option[Throwable] = failureCause

  override def error(queryId: String, e: Throwable) = Task {
    failureCause = Option(e)
  }

  def columns = headers.toList

  override def log(subQueryId: String, line: String, level: String): Task[Unit] = Task {
    logMessages += line
  }

  def logs = logMessages.toList

  def queries = queriesStatuses.toList
}

sealed trait QueryStatus

sealed case class QueryStarted(queryId: String, code: String) extends QueryStatus

sealed case class QueryFinished(queryId: String) extends QueryStatus

sealed case class QueryFailed(queryId: String, error: String) extends QueryStatus

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/sql/PrestoSqlOps.scala
================================================
package quix.core.sql

import io.prestosql.sql.parser.StatementSplitter

import scala.collection.JavaConverters._

object PrestoSqlOps {

  def splitToStatements(multipleStatements: String): List[String] = {
    val splitter = new StatementSplitter(multipleStatements, Set(";").asJava)

    val completeStatements = splitter.getCompleteStatements.asScala.map(_.statement()).toList
    val partialStatements = splitter.getPartialStatement

    val restIsEmptyOrMadeofComments = partialStatements.trim.isEmpty || partialStatements.split("\n").filterNot(_.isEmpty).forall(_.trim.startsWith("--"))

    (completeStatements.isEmpty, restIsEmptyOrMadeofComments) match {
      case (true, true) =>
        List.empty

      case (true, _) =>
        List(multipleStatements)

      case (false, true) =>
        recoverLeadingSpaces(multipleStatements, completeStatements.head) +: completeStatements.tail

      case (false, false) =>
        recoverLeadingSpaces(multipleStatements, completeStatements.head) +: completeStatements.tail :+ partialStatements
    }
  }

  /*
    StatementSplitter trims all leading whitespaces, which makes it hard
    to mark correct line in case of presto error

    see https://github.com/wix-incubator/quix/issues/58 for more details
   */
  def recoverLeadingSpaces(original: String, trimmed: String): String = {
    val index = original.indexOf(trimmed)
    original.substring(0, index) ++ trimmed
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/sql/SqlSplitter.scala
================================================
package quix.core.sql

import monix.execution.atomic.Atomic
import quix.api.v1.execute.StartCommand
import quix.api.v1.users.User
import quix.api.v2.execute.{ImmutableSubQuery, MutableSession, Query, Session}

trait SqlSplitter {
  def split(sql: String): List[String]

  def newSession(command: StartCommand[String], user: User): Session = new MutableSession

  def split(command: StartCommand[String], id: String, user: User): Query = {
    val canceled = Atomic(false)
    val session = newSession(command, user)

    val subQueries = split(command.code).map { sql =>
      ImmutableSubQuery(sql, user, canceled = canceled, session = session)
    }

    Query(subQueries, id, canceled, rawCode = command.code)
  }
}

object PrestoLikeSplitter extends SqlSplitter {
  def split(sql: String): List[String] = {
    PrestoSqlOps.splitToStatements(sql)
  }
}

class StopWordSqlSplitter(val stopWords: String*) extends SqlSplitter {
  def split(sql: String): List[String] = {
    val statements = PrestoSqlOps.splitToStatements(sql)

    val noStopWords = statements.dropWhile(containsStopWords)

    val maybeSplitByStopWords = noStopWords.headOption.map { statement =>
      val newHead = sql.substring(0, sql.indexOf(statement) + statement.length)
      newHead :: noStopWords.tail
    }

    maybeSplitByStopWords.getOrElse(statements)
  }

  def containsStopWords(sql: String): Boolean = {
    stopWords.exists(sql.contains)
  }
}

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/utils/Chores.scala
================================================
package quix.core.utils

import java.util.concurrent.{Executors, ScheduledExecutorService, ThreadFactory}

import com.typesafe.scalalogging.LazyLogging

import scala.concurrent.duration.TimeUnit
import scala.util.control.NonFatal

trait Chores extends LazyLogging {
  private val className = this.getClass.toString
  private val poolName = "chore-" + className
  private val executor = scheduledSingleThreadPoolNamed(poolName)

  def chore(): Unit

  def scheduleChore(initialDelay: Long, delay: Long, unit: TimeUnit) = {
    val runnable = new Runnable {
      override def run(): Unit = try {
        logger.info("event=chore-start class-name=" + className)
        chore()
        logger.info("event=chore-finish class-name=" + className)
      } catch {
        case NonFatal(t) =>
          logger.warn("event=chore-failure class-name=" + className, t)
      }
    }

    logger.warn(s"schedule $className.chore() at fixed rate every ${unit.toMinutes(delay)} minutes")
    executor.scheduleAtFixedRate(runnable, initialDelay, delay, unit)
  }

  // helpers
  private def daemonThreadsNamed(format: String): ThreadFactory = {
    r: Runnable => {
      val t = Executors.defaultThreadFactory.newThread(r)
      t.setDaemon(true)
      t.setName(format)
      t
    }
  }

  private def scheduledSingleThreadPoolNamed(format: String): ScheduledExecutorService = {
    Executors.newSingleThreadScheduledExecutor(daemonThreadsNamed(format))
  }
}


================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/utils/JsonOps.scala
================================================
package quix.core.utils

import java.lang.reflect.{ParameterizedType, Type}
import java.util.TimeZone

import com.fasterxml.jackson.core.`type`.TypeReference
import com.fasterxml.jackson.databind.SerializationFeature._
import com.fasterxml.jackson.databind.{DeserializationFeature, JsonNode, ObjectMapper}
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module
import com.fasterxml.jackson.module.scala.DefaultScalaModule
import quix.core.utils.JacksonSupport._

import scala.util.control.NonFatal

trait StringJsonHelpersSupport {

  implicit class String2jsonNode(s: String) {
    def asJson(implicit mapper: ObjectMapper): JsonNode = mapper.readTree(s)

    def as[T](implicit mn: Manifest[T], mapper: ObjectMapper): T = deserialize[T](s)

    def get(key: String, default: String = "")(implicit mapper: ObjectMapper) = {
      try {
        s.asJson.get(key) match {
          case null => default
          case node if node.isTextual => node.asText(default)
          case node if node.isObject && node.toString.nonEmpty => node.toString
          case _ => default
        }
      } catch {
        case NonFatal(_) => default
      }
    }
  }

  implicit class AnyObject2JsonNode(o: Any) {
    def asJsonStr(implicit mapper: ObjectMapper): String = mapper.writeValueAsString(o)
  }

}

object JacksonSupport {
  def deserialize[T](value: String)(implicit mn: Manifest[T], mapper: ObjectMapper): T =
    mapper.readValue(value, typeReference[T])

  private def typeReference[T: Manifest] = new TypeReference[T] {
    override def getType = typeFromManifest(manifest[T])
  }

  private def typeFromManifest(m: Manifest[_]): Type = {
    if (m.typeArguments.isEmpty) {
      m.runtimeClass
    }
    else new ParameterizedType {
      def getRawType = m.runtimeClass

      def getActualTypeArguments = m.typeArguments.map(typeFromManifest).toArray

      def getOwnerType = null
    }
  }
}

object JsonOps {

  private val defaultModules = Seq(new DefaultScalaModule, new Jdk8Module)

  def global: ObjectMapper = Implicits.global

  def objectMapperFromTemplate: ObjectMapper =
    new ObjectMapper().registerModules(defaultModules: _*)
      .disable(WRITE_DATES_AS_TIMESTAMPS)
      .setTimeZone(TimeZone.getTimeZone("UTC"))

  object Implicits {
    implicit lazy val global: ObjectMapper = objectMapperFromTemplate
      .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
  }

}

================================================
FILE: quix-backend/quix-core/src/main/scala/quix/core/utils/TaskOps.scala
================================================
package quix.core.utils

import com.typesafe.scalalogging.LazyLogging
import monix.eval.Task

import scala.concurrent.duration.FiniteDuration

object TaskOps extends LazyLogging {

  implicit class Ops[A](val task: Task[A]) extends AnyVal {
    def retry(maxRetries: Int, firstDelay: FiniteDuration): Task[A] = {
      task.onErrorHandleWith {
        case ex: Exception =>
          if (maxRetries > 0) {
            logger.warn(s"method=retry error=${ex.getClass.getSimpleName} retries=$maxRetries delay=${firstDelay.toMillis / 1000.0}")
            retry(maxRetries - 1, firstDelay * 2).delayExecution(firstDelay)
          }
          else
            Task.raiseError(ex)
      }
    }

    def logOnError(msg: String = ""): Task[A] = {
      task.onErrorHandleWith {
        case e: Exception =>
          logger.error(msg, e)
          Task.raiseError(e)
      }
    }
  }
}


================================================
FILE: quix-backend/quix-core/src/test/resources/db/001_init.sql
================================================
CREATE TABLE executions_history (
    id CHAR(36) NOT NULL PRIMARY KEY,
    query_type VARCHAR(64) NOT NULL,
    statements MEDIUMTEXT NOT NULL,
    code MEDIUMTEXT NOT NULL,
    user_id VARCHAR(64) NOT NULL,
    user_email VARCHAR(64) NOT NULL,
    status ENUM('RUNNING', 'FINISHED', 'FAILED') NOT NULL DEFAULT 'RUNNING',
    created_at BIGINT UNSIGNED NOT NULL,
    updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP() ON UPDATE CURRENT_TIMESTAMP(),
    INDEX published_forms (created_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/db/DbOpsTest.scala
================================================
package quix.core.db

import org.specs2.matcher.MustMatchers
import org.specs2.mutable.SpecWithJUnit
import quix.api.v1.db.{Catalog, Kolumn, Schema, Table}

class DbOpsTest extends SpecWithJUnit with MustMatchers  {

  "DbOps.mergeNewAndOldCatalogs" should {

    "pass sanity if no change was detected" in {
      val columns: List[Kolumn] = List(Kolumn("uuid", "guid"))
      val tables: List[Table] = List(Table("users", columns))
      val schemas: List[Schema] = List(Schema("dbo", tables))
      val newCatalogs = List(Catalog("bi", schemas))
      val oldCatalogs = List(Catalog("bi", schemas))

      val mergedResult = DbOps.mergeNewAndOldCatalogs(newCatalogs, oldCatalogs)

      mergedResult must_=== newCatalogs
    }

    "swap old catalogs with new catalogs if tables were added" in {
      val columns: List[Kolumn] = List(Kolumn("uuid", "guid"))
      val nonEmptyTables: List[Table] = List(Table("users", columns))
      val emptyTables: List[Table] = List.empty[Table]
      val newCatalogs = List(Catalog("bi", List(Schema("dbo", nonEmptyTables))))
      val oldCatalogs = List(Catalog("bi", List(Schema("dbo", emptyTables))))

      val mergedResult = DbOps.mergeNewAndOldCatalogs(newCatalogs, oldCatalogs)

      mergedResult must_=== newCatalogs
    }

    "swap old catalogs with new catalogs if tables were removed" in {
      val columns: List[Kolumn] = List(Kolumn("uuid", "guid"))
      val nonEmptyTables: List[Table] = List(Table("users", columns))
      val emptyTables: List[Table] = List.empty[Table]
      val newCatalogs = List(Catalog("bi", List(Schema("dbo", emptyTables))))
      val oldCatalogs = List(Catalog("bi", List(Schema("dbo", nonEmptyTables))))

      val mergedResult = DbOps.mergeNewAndOldCatalogs(newCatalogs, oldCatalogs)

      mergedResult must_=== newCatalogs
    }

    "not swap old catalogs with new catalogs if schemas were removed" in {
      val columns: List[Kolumn] = List(Kolumn("uuid", "guid"))
      val nonEmptyTables: List[Table] = List(Table("users", columns))
      val newCatalogs = List(Catalog("bi", List.empty[Schema]))
      val oldCatalogs = List(Catalog("bi", List(Schema("dbo", nonEmptyTables))))

      val mergedResult = DbOps.mergeNewAndOldCatalogs(newCatalogs, oldCatalogs)

      mergedResult must_=== oldCatalogs
    }

  }

  "DbOps.search" should {
    "pass sanity" in {
      DbOps.search(List.empty, "foo") must beEmpty
    }

    "search by catalog name" in {
      val first = Catalog("this-is-foo-catalog", Nil)
      val second = Catalog("this-is-boo-catalog", Nil)

      val expected = List(first)

      DbOps.search(List(first, second), "foo") must_=== expected
    }

    "search by schema name" in {
      val first = Schema("this-is-foo-schema", Nil)
      val second = Schema("this-is-boo-schema", Nil)

      val catalog = Catalog("catalog", List(first, second))
      val expected = Catalog("catalog", List(first))

      DbOps.search(List(catalog), "foo") must contain(expected)
    }

    "search by table name" in {
      val first = Table("this-is-foo-table", Nil)
      val second = Table("this-is-boo-table", Nil)

      val catalog = Catalog("catalog", List(Schema("schema", List(first, second))))
      val expected = Catalog("catalog", List(Schema("schema", List(first))))

      DbOps.search(List(catalog), "foo") must contain(expected)
    }

    "return complete catalog tree on top-level match" in {
      val catalog = Catalog("c1", List(Schema("s1", List(Table("t1", Nil), Table("t2", Nil)))))

      DbOps.search(List(catalog), "c1") must contain(catalog)
    }
  }

}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/db/DbQueryTest.scala
================================================
package quix.core.db

import org.specs2.mutable.SpecWithJUnit

class DbQueryTest extends SpecWithJUnit {

  "DbQuery.apply" should {
    "return exact match query for quoted strings" in {
      DbQuery(""""foo"""").matches("foo") must beTrue
      DbQuery("""'foo'""").matches("foo") must beTrue
    }

    "return contains query regular strings" in {
      DbQuery("foo").matches("foo") must beTrue
      DbQuery("").matches("foo") must beTrue
    }

    "handle nulls" in {
      DbQuery(null).matches("foo") must beFalse
    }
  }

}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/executions/SqlModuleTest.scala
================================================
package quix.core.executions

import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import org.specs2.matcher.MustMatchers
import org.specs2.mutable.SpecWithJUnit
import org.specs2.specification.Scope
import quix.api.v1.execute.{End, ExecutionEvent, Start, StartCommand}
import quix.api.v1.users.User
import quix.api.v2.execute.{Builder, Executor, SubQuery}
import quix.core.results.{MultiBuilder, TestConsumer}

class SqlModuleTest extends SpecWithJUnit with MustMatchers {

  class ctx extends Scope {
    val consumer = new TestConsumer[ExecutionEvent]
    val builder = new MultiBuilder(consumer)
    val user = User("user@quix", "user-id")
    val module = new SqlModule(TestExecutor, None)

    val emptyCommand = StartCommand[String]("", Map.empty)
  }

  "SqlModule.start" should {
    "invoke builder.start & builder.end methods on every command" in new ctx {
      module.start(emptyCommand, "id", user, builder).runSyncUnsafe()

      eventually {
        consumer.payloads must contain(Start("id", 0))
        consumer.payloads must contain(End("id"))
      }
    }
  }

  object TestExecutor extends Executor {
    override def execute(query: SubQuery, builder: Builder): Task[Unit] = Task.unit
  }

}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/ExecutionMatchers.scala
================================================
package quix.core.history

import org.specs2.matcher.Matcher
import org.specs2.matcher.Matchers._

object ExecutionMatchers {
  def executionWithId(id: String): Matcher[Execution] =
    equalTo(id) ^^ ((_: Execution).id)

  def executionWithStatus(status: ExecutionStatus): Matcher[Execution] =
    equalTo(status) ^^ ((_: Execution).status)
}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/FakeBuilder.scala
================================================
package quix.core.history

import cats.effect.concurrent.Ref
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import quix.api.v1.execute.Batch
import quix.api.v2.execute.{Builder, Query}

case class FakeBuilder(state: Ref[Task, State]) extends Builder {

  override def start(query: Query): Task[Unit] =
    state.update(_.start(query))

  override def end(query: Query): Task[Unit] =
    state.update(_.end(query))

  override def error(subQueryId: String, e: Throwable): Task[Unit] =
    state.update(_.error(subQueryId, e))

  override def rowCount: Long = get(_.rows)

  override def lastError: Option[Throwable] = get(_.lastError)

  override def startSubQuery(queryId: String, code: String): Task[Unit] =
    state.update(_.startSubQuery(queryId, code))

  override def addSubQuery(subQueryId: String, results: Batch): Task[Unit] =
    state.update(_.addSubQuery(subQueryId, results))

  override def endSubQuery(subQueryId: String, statistics: Map[String, Any]): Task[Unit] =
    state.update(_.endSubQuery(subQueryId))

  override def errorSubQuery(subQueryId: String, e: Throwable): Task[Unit] =
    state.update(_.error(subQueryId, e))

  override def log(subQueryId: String, line: String, level: String): Task[Unit] =
    state.update(_.addLogLine(subQueryId, line, level))

  private def get[A](f: State => A): A =
    state.get.map(f).runSyncUnsafe()

}

object FakeBuilder {
  def make: Task[FakeBuilder] =
    Ref.of[Task, State](State.Empty).map(FakeBuilder(_))
}

case class State(queries: Map[String, HistoricalQuery],
                 subQueries: Map[String, HistoricalSubQuery],
                 errors: List[Error],
                 log: List[LogLine]) {

  def rows: Long = subQueries.values.foldLeft(0L)(_ + _.rows)

  def start(execution: Query): State =
    copy(queries = queries + (execution.id -> HistoricalQuery(execution, QueryStatus.Started)))

  def end(query: Query): State =
    copy(queries = queries + (query.id -> HistoricalQuery(query, QueryStatus.Ended)))

  def error(queryId: String, e: Throwable): State =
    copy(errors = Error(queryId, e) :: errors)

  def lastError: Option[Throwable] =
    errors.headOption.map(_.error)

  def startSubQuery(queryId: String, code: String): State =
    copy(subQueries = subQueries + (queryId -> SubQuery(code)))

  def addSubQuery(queryId: String, results: Batch): State =
    copy(subQueries = updateSubQuery(queryId, _.addResults(results)))

  def endSubQuery(queryId: String): State =
    copy(subQueries = updateSubQuery(queryId, _.ended))

  def addLogLine(queryId: String, line: String, level: String): State =
    copy(log = LogLine(queryId, line, level) :: log)

  private def updateSubQuery(queryId: String, f: HistoricalSubQuery => HistoricalSubQuery): Map[String, HistoricalSubQuery] =
    subQueries.get(queryId).fold(subQueries)(query => subQueries + (queryId -> f(query)))
}

object State {
  val Empty = State(Map.empty, Map.empty, Nil, Nil)
}

sealed trait QueryStatus

object QueryStatus {

  case object Started extends QueryStatus

  case object Ended extends QueryStatus

}

case class HistoricalQuery(query: Query, status: QueryStatus)

case class HistoricalSubQuery(code: String,
                              results: List[Batch],
                              status: QueryStatus) {

  def rows: Long = results.foldLeft(0L)(_ + _.data.size)

  def addResults(moreResults: Batch): HistoricalSubQuery =
    copy(results = moreResults :: results)

  def ended: HistoricalSubQuery =
    copy(status = QueryStatus.Ended)

}

object SubQuery {
  def apply(code: String): HistoricalSubQuery =
    HistoricalSubQuery(code, List.empty, QueryStatus.Started)
}

case class Error(queryId: String, error: Throwable)

case class LogLine(queryId: String, line: String, level: String)


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/FakeClock.scala
================================================
package quix.core.history

import java.time.{Clock, Instant, ZoneId, ZoneOffset}
import java.util.concurrent.atomic.AtomicReference

import scala.concurrent.duration.FiniteDuration

case class FakeClock(now: AtomicReference[Instant],
                     getZone: ZoneId) extends Clock {

  override def withZone(zone: ZoneId): Clock = copy(getZone = zone)

  override def instant: Instant = now.get

  def sleep(duration: FiniteDuration): Unit =
    now.updateAndGet(_.plusMillis(duration.toMillis))

}

object FakeClock {
  def apply(now: Instant, zone: ZoneId = ZoneOffset.UTC): FakeClock =
    FakeClock(new AtomicReference(now), zone)
}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/HistoryBuilderTest.scala
================================================
package quix.core.history

import java.time.{Clock, Instant, ZoneOffset}

import monix.execution.Scheduler.Implicits.global
import org.specs2.mutable.SpecificationWithJUnit
import quix.api.v1.execute.Batch
import quix.api.v1.users.User
import quix.api.v2.execute.{ImmutableSubQuery, Query}
import quix.core.history.ExecutionMatchers._
import quix.core.history.HistoryBuilderTest._
import quix.core.history.dao.InMemoryHistoryDao

class HistoryBuilderTest extends SpecificationWithJUnit {

  val subQuery = "query3"
  val now = Instant.ofEpochMilli(0)
  val clock = Clock.fixed(now, ZoneOffset.UTC)
  val makeDao = InMemoryHistoryDao.make(clock)

  "delegate calls to internal builder" in {
    val result = for {
      delegate <- FakeBuilder.make
      dao <- makeDao
      builder = new HistoryBuilder(delegate, dao, queryType)
      _ <- builder.start(query1)
      _ <- builder.startSubQuery(subQuery, code1.text)
      _ <- builder.addSubQuery(subQuery, batch1)
      _ <- builder.addSubQuery(subQuery, batch2)
      _ <- builder.endSubQuery(subQuery)
      _ <- builder.end(query1)
      _ <- builder.start(query2)
      _ <- builder.log(query2.id, "some-log")
      _ <- builder.error(query2.id, error1)
      _ <- builder.errorSubQuery(subQuery, error2)
      state <- delegate.state.get
    } yield state

    result.runSyncUnsafe() must
      equalTo(
        State(
          queries = Map(
            query1.id -> HistoricalQuery(query1, QueryStatus.Ended),
            query2.id -> HistoricalQuery(query2, QueryStatus.Started)),
          subQueries = Map(subQuery -> HistoricalSubQuery(code1.text, List(batch2, batch1), QueryStatus.Ended)),
          errors = List(Error(subQuery, error2), Error(query2.id, error1)),
          log = List(LogLine(query2.id, "some-log", "INFO"))))
  }

  "persist execution history" in {
    val result = for {
      delegate <- FakeBuilder.make
      dao <- makeDao
      builder = new HistoryBuilder(delegate, dao, queryType)
      _ <- builder.start(query1)
      _ <- builder.end(query1)
      executions <- dao.executions()
    } yield executions

    result.runSyncUnsafe() must
      contain(executionWithStatus(ExecutionStatus.Finished))
  }

  "persist failed execution" in {
    val error = new RuntimeException("oops")
    val result = for {
      delegate <- FakeBuilder.make
      dao <- makeDao
      builder = new HistoryBuilder(delegate, dao, queryType)
      _ <- builder.start(query1)
      _ <- builder.error(query1.id, error)
      executions <- dao.executions()
    } yield executions

    result.runSyncUnsafe() must
      contain(executionWithStatus(ExecutionStatus.Failed))
  }

}

object HistoryBuilderTest {
  val user = User("foo@bar.com", "some-user")
  val code1 = ImmutableSubQuery("code1", user)
  val code2 = ImmutableSubQuery("code2", user)
  val code3 = ImmutableSubQuery("code3", user)
  val queryType = "query-type"
  val query1 = Query(List(code1, code2), id = "query1")
  val query2 = Query(List(code3), id = "query2")
  val batch1 = Batch(List(List(1), List(2)))
  val batch2 = Batch(List(List(3)))
  val error1 = new RuntimeException("foo")
  val error2 = new RuntimeException("bar")
}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/dao/HistoryDaoContractTest.scala
================================================
package quix.core.history.dao

import java.time.{Clock, Instant, ZoneOffset}

import cats.effect.Resource
import monix.eval.Task
import monix.execution.Scheduler.Implicits.global
import org.specs2.mutable.SpecificationWithJUnit
import quix.api.v1.users.User
import quix.api.v2.execute.{ImmutableSubQuery, Query}
import quix.core.history.ExecutionMatchers._
import quix.core.history.dao.HistoryDaoContractTest._
import quix.core.history.{Execution, ExecutionStatus, FakeClock}

import scala.concurrent.duration._

trait HistoryDaoContractTest extends SpecificationWithJUnit {

  def createDao(clock: Clock = defaultClock): Resource[Task, HistoryWriteDao with HistoryReadDao]

  "return empty list of executions if none was saved" in {
    val result = createDao().use(_.executions())

    result.runSyncUnsafe() must beEmpty
  }

  "return running execution" in {
    val result = createDao().use { dao =>
      dao.executionStarted(query, queryType) *>
        dao.executions()
    }

    result.runSyncUnsafe() must contain(
      Execution(
        id = "query-id",
        queryType = queryType,
        statements = statements,
        code = query.rawCode,
        user = user,
        startedAt = now,
        status = ExecutionStatus.Running))
  }

  "return succeeded execution" in {
    val result = createDao().use { dao =>
      dao.executionStarted(query, queryType) *>
        dao.executionSucceeded(queryId) *>
        dao.executions()
    }

    result.runSyncUnsafe() must
      contain(executionWithStatus(ExecutionStatus.Finished))
  }

  "return failed execution" in {
    val error = new RuntimeException("oops")
    val result = createDao().use { dao =>
      dao.executionStarted(query, queryType) *>
        dao.executionFailed(queryId, error) *>
        dao.executions()
    }

    result.runSyncUnsafe() must
      contain(executionWithStatus(ExecutionStatus.Failed))
  }

  "support paging" in {
    val query1 = query.copy(id = "query-1")
    val query2 = query.copy(id = "query-2")
    val query3 = query.copy(id = "query-3")
    val query4 = query.copy(id = "query-4")
    val query5 = query.copy(id = "query-5")

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- dao.executionStarted(query2, queryType)
        _ <- dao.executionStarted(query3, queryType)
        _ <- dao.executionStarted(query4, queryType)
        _ <- dao.executionStarted(query5, queryType)
        page1 <- dao.executions(page = Page(0, 3))
        page2 <- dao.executions(page = Page(3, 3))
      } yield (page1, page2)
    }

    result.runSyncUnsafe() must beLike {
      case (page1, page2) =>
        (page1 must contain(exactly(executionWithId(query1.id), executionWithId(query2.id), executionWithId(query3.id)))) and
          (page2 must contain(exactly(executionWithId(query4.id), executionWithId(query5.id))))
    }
  }

  "support filtering by queryType" in {
    val query1 = query.copy(id = "query-1")
    val query2 = query.copy(id = "query-2")
    val query3 = query.copy(id = "query-3")

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, "query-type-1")
        _ <- dao.executionStarted(query2, "query-type-1")
        _ <- dao.executionStarted(query3, "query-type-2")
        _ <- dao.executionSucceeded(query2.id)
        _ <- dao.executionFailed(query3.id, new RuntimeException)
        firstType <- dao.executions(filter = Filter.QueryType("query-type-1"))
        secondType <- dao.executions(filter = Filter.QueryType("query-type-2"))
      } yield (firstType, secondType)
    }

    result.runSyncUnsafe() must beLike {
      case (firstType, secondType) =>
        (firstType must contain(exactly(executionWithId(query1.id), executionWithId(query2.id)))) and
          (secondType must contain(exactly(executionWithId(query3.id))))
    }
  }

  "support filtering by status" in {
    val query1 = query.copy(id = "query-1")
    val query2 = query.copy(id = "query-2")
    val query3 = query.copy(id = "query-3")

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- dao.executionStarted(query2, queryType)
        _ <- dao.executionStarted(query3, queryType)
        _ <- dao.executionSucceeded(query2.id)
        _ <- dao.executionFailed(query3.id, new RuntimeException)
        running <- dao.executions(filter = Filter.Status(ExecutionStatus.Running))
        finished <- dao.executions(filter = Filter.Status(ExecutionStatus.Finished))
        failed <- dao.executions(filter = Filter.Status(ExecutionStatus.Failed))
      } yield (running, finished, failed)
    }

    result.runSyncUnsafe() must beLike {
      case (running, finished, failed) =>
        (running must contain(exactly(executionWithId(query1.id)))) and
          (finished must contain(exactly(executionWithId(query2.id)))) and
          (failed must contain(exactly(executionWithId(query3.id))))
    }
  }

  "support filtering by user email" in {
    def makeSubQueries(userEmail: String) =
      List(ImmutableSubQuery("select 1", User(email = userEmail)))

    val query1 = query.copy(id = "query-1", subQueries = makeSubQueries("foo@quix.com"))
    val query2 = query.copy(id = "query-2", subQueries = makeSubQueries("boo@quix.com"))
    val query3 = query.copy(id = "query-3", subQueries = makeSubQueries("bar@quix.com"))

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- dao.executionStarted(query2, queryType)
        _ <- dao.executionStarted(query3, queryType)
        foo <- dao.executions(filter = Filter.User("foo@quix.com"))
        boo <- dao.executions(filter = Filter.User("boo@quix.com"))
        bar <- dao.executions(filter = Filter.User("bar@quix.com"))
      } yield (foo, boo, bar)
    }

    result.runSyncUnsafe() must beLike {
      case (running, finished, failed) =>
        (running must contain(exactly(executionWithId(query1.id)))) and
          (finished must contain(exactly(executionWithId(query2.id)))) and
          (failed must contain(exactly(executionWithId(query3.id))))
    }
  }

  "support filtering by query text" in {
    def newQuery(queryId: String, userEmail: String) = query.copy(id = queryId,
      subQueries = List(ImmutableSubQuery(s"select $userEmail as email", User(email = userEmail))),
      rawCode = s"select $userEmail as email"
    )

    val query1 = newQuery("query-1", "foo@quix.com")
    val query2 = newQuery("query-2", "boo@quix.com")
    val query3 = newQuery("query-3", "bar@quix.com")

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- dao.executionStarted(query2, queryType)
        _ <- dao.executionStarted(query3, queryType)
        foo <- dao.executions(filter = Filter.Query("foo@quix.com"))
        boo <- dao.executions(filter = Filter.Query("boo@quix.com"))
        bar <- dao.executions(filter = Filter.Query("bar@quix.com"))
      } yield (foo, boo, bar)
    }

    result.runSyncUnsafe() must beLike {
      case (running, finished, failed) =>
        (running must contain(exactly(executionWithId(query1.id)))) and
          (finished must contain(exactly(executionWithId(query2.id)))) and
          (failed must contain(exactly(executionWithId(query3.id))))
    }
  }

  "support filtering by query and user email" in {
    def newQuery(queryId: String, sql: String, userEmail: String) = query.copy(id = queryId,
      subQueries = List(ImmutableSubQuery(sql, User(email = userEmail))),
      rawCode = sql
    )

    val query1 = newQuery("query-1", "select 1", "foo@quix.com")
    val query2 = newQuery("query-2", "select 2", "foo@quix.com")
    val query3 = newQuery("query-3", "select 3", "foo@quix.com")

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- dao.executionStarted(query2, queryType)
        _ <- dao.executionStarted(query3, queryType)
        first <- dao.executions(filter = Filter.CompoundFilter(List(Filter.Query("select 1"), Filter.User("foo@quix.com"))))
        second <- dao.executions(filter = Filter.CompoundFilter(List(Filter.Query("select 2"), Filter.User("foo@quix.com"))))
        third <- dao.executions(filter = Filter.CompoundFilter(List(Filter.Query("select 3"), Filter.User("foo@quix.com"))))
      } yield (first, second, third)
    }

    result.runSyncUnsafe() must beLike {
      case (running, finished, failed) =>
        (running must contain(exactly(executionWithId(query1.id)))) and
          (finished must contain(exactly(executionWithId(query2.id)))) and
          (failed must contain(exactly(executionWithId(query3.id))))
    }
  }

  "support sorting by start time" in {
    val clock = FakeClock(now)
    val query1 = query.copy(id = "query-1")
    val query2 = query.copy(id = "query-2")

    val result = createDao(clock).use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- Task(clock.sleep(1.second))
        _ <- dao.executionStarted(query2, queryType)
        ascending <- dao.executions(sort = Sort(SortField.StartTime, SortOrder.Ascending))
        descending <- dao.executions(sort = Sort(SortField.StartTime, SortOrder.Descending))
      } yield (ascending, descending)
    }

    result.runSyncUnsafe() must beLike {
      case (ascending, descending) =>
        (ascending must contain(exactly(executionWithId(query1.id), executionWithId(query2.id)).inOrder)) and
          (descending must contain(exactly(executionWithId(query2.id), executionWithId(query1.id)).inOrder))
    }
  }

  "support case-insentitive filtering by query text" in {
    def newQuery(queryId: String, userEmail: String) = query.copy(id = queryId,
      subQueries = List(ImmutableSubQuery(s"select $userEmail as email", User(email = userEmail))),
      rawCode = s"select $userEmail as email"
    )

    val query1 = newQuery("query-1", "foo@quix.com")
    val query2 = newQuery("query-2", "boo@quix.com")
    val query3 = newQuery("query-3", "bar@quix.com")

    val result = createDao().use { dao =>
      for {
        _ <- dao.executionStarted(query1, queryType)
        _ <- dao.executionStarted(query2, queryType)
        _ <- dao.executionStarted(query3, queryType)
        lower <- dao.executions(filter = Filter.Query("select"))
        upper <- dao.executions(filter = Filter.Query("SELECT"))
      } yield (lower, upper)
    }

    result.runSyncUnsafe() must beLike {
      case (lower, upper) =>
        (lower must haveSize(3)) and
          (upper must haveSize(3))
    }
  }

}

object HistoryDaoContractTest {
  val now = Instant.ofEpochMilli(0)
  val defaultClock = Clock.fixed(now, ZoneOffset.UTC)
  val queryType = "query-type"
  val user = User("foo@bar.com", "some-user")
  val queryId = "query-id"

  val query1 = ImmutableSubQuery("code1", user)
  val query2 = ImmutableSubQuery("code2", user)
  val query = Query(Seq(query1, query2), id = queryId, rawCode = "code1\ncode2")
  val statements = query.subQueries.map(_.text)
}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/dao/InMemoryHistoryDaoTest.scala
================================================
package quix.core.history.dao

import java.time.Clock

import cats.effect.Resource
import monix.eval.Task

class InMemoryHistoryDaoTest extends HistoryDaoContractTest {

  override def createDao(clock: Clock): Resource[Task, HistoryWriteDao with HistoryReadDao] =
    Resource.liftF(InMemoryHistoryDao.make(clock))

}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/history/dao/MySqlHistoryDaoTest.scala
================================================
package quix.core.history.dao

import java.time.Clock

import cats.effect.Resource
import com.typesafe.scalalogging.LazyLogging
import com.wix.mysql.EmbeddedMysql
import com.wix.mysql.EmbeddedMysql.anEmbeddedMysql
import com.wix.mysql.ScriptResolver.classPathScript
import com.wix.mysql.config.Charset.UTF8
import com.wix.mysql.config.MysqldConfig.aMysqldConfig
import com.wix.mysql.distribution.Version.v5_6_23
import monix.eval.Task
import org.specs2.specification.{AfterAll, BeforeAll, BeforeEach}
import quix.api.v2.execute.{Query => ActiveQuery}
import quix.core.history.Execution

class MySqlHistoryDaoTest
  extends HistoryDaoContractTest
    with BeforeAll
    with BeforeEach
    with AfterAll {

  sequential

  def beforeAll(): Unit = EmbeddedMysqlDb.start()

  def before(): Unit = EmbeddedMysqlDb.reloadSchema()

  def afterAll(): Unit = EmbeddedMysqlDb.stop()

  override def createDao(clock: Clock): Resource[Task, HistoryWriteDao with HistoryReadDao] =
    MySqlHistoryDao.connect(EmbeddedMysqlDb.Config).map { connection =>
      val reader = new MySqlHistoryReadDao(connection)
      val writer = new MySqlHistoryWriteDao(connection, clock)
      new HistoryWriteDao with HistoryReadDao {
        override def executionStarted(query: ActiveQuery, queryType: String): Task[Unit] =
          writer.executionStarted(query, queryType)

        override def executionSucceeded(queryId: String): Task[Unit] =
          writer.executionSucceeded(queryId)

        override def executionFailed(queryId: String, error: Throwable): Task[Unit] =
          writer.executionFailed(queryId, error)

        override def executions(filter: Filter, sort: Sort, page: Page): Task[List[Execution]] =
          reader.executions(filter, sort, page)
      }
    }

}

object EmbeddedMysqlDb extends LazyLogging {
  Class.forName("com.mysql.cj.jdbc.Driver")

  private val port = 2215

  private val user = "wix"

  private val pass = "wix"

  private val schema = "aschema"

  private var db: EmbeddedMysql = _

  val Config = JdbcConfig(s"jdbc:mysql://localhost:$port/$schema", user, pass)

  def reloadSchema(): Unit = {
    logger.info("method=reloadSchema")
    db.reloadSchema(schema, classPathScript("db/001_init.sql"))
  }

  def stop(): Unit = {
    logger.info("method=stop")
    db.stop()
  }

  def start(): Unit = {
    logger.info("method=start")
    db = anEmbeddedMysql(
      aMysqldConfig(v5_6_23)
        .withCharset(UTF8)
        .withPort(port)
        .withUser(user, pass)
        .build())
      .addSchema(schema, classPathScript("db/001_init.sql"))
      .start()
  }
}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/results/MultiBuilderTest.scala
================================================
package quix.core.results

import java.util.UUID

import monix.eval.Task
import monix.execution.Scheduler
import org.specs2.mutable.SpecWithJUnit
import org.specs2.specification.Scope
import quix.api.v1.execute.Batch._
import quix.api.v1.execute._
import quix.api.v1.users.User
import quix.api.v2.execute.{Query, ImmutableSubQuery}

import scala.collection.mutable.ListBuffer

class MultiBuilderTest extends SpecWithJUnit {

  class ctx extends Scope {
    val consumer = new TestConsumer[ExecutionEvent]
    val builder = new MultiBuilder(consumer)
    val query = ImmutableSubQuery("text", User("test"))
    val execution = Query(Seq(query), canceled = query.canceled)
  }

  "MultiBuilder.start" should {
    "send Start event on start(query)" in new ctx {
      builder.start(execution).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Start(execution.id, execution.subQueries.size))
      }
    }
  }

  "MultiBuilder.end" should {

    "send End event on end(query)" in new ctx {
      builder.end(execution).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(End(execution.id))
      }
    }
  }

  "MultiBuilder.startSubQuery" should {

    "send StartQuery & SubQueryDetails event on every startSubQuery(queryId, code, results)" in new ctx {
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(SubQueryStart("query-id"))
        consumer.payloads must contain(SubQueryDetails("query-id", "code"))
      }
    }

    "send SubQueryFields if columns are present in results during startSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List.empty, Option(List(BatchColumn("column"))))
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(SubQueryFields("query-id", List("column")))
      }
    }

    "send SubQueryFields only once if columns are present in results during startSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List.empty, Option(List(BatchColumn("column"))))
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads.filter(_ == SubQueryFields("query-id", List("column"))) must haveSize(1)
      }
    }

    "send Progress if present in results during startSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List.empty).withPercentage(100)
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Progress("query-id", 100))
      }
    }

    "send Progress on every batch during startSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List.empty).withPercentage(100)
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads.filter(_ == Progress("query-id", 100)) must haveSize(2)
      }
    }

    "send Error if present in results during startSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List.empty, error = Option(BatchError("boom!")))
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Error("query-id", "boom!"))
      }
    }

    "send Row events if data is present in results during startSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List(List("a", "b", "c"), List("d", "e", "f")))
      builder.startSubQuery("query-id", "code").runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Row("query-id", List("a", "b", "c")))
        consumer.payloads must contain(Row("query-id", List("d", "e", "f")))
      }
    }
  }

  "MultiBuilder.endSubQuery" should {

    "send SubQueryEnd event on endSubQuery(query)" in new ctx {
      builder.endSubQuery(query.id).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(SubQueryEnd(query.id))
      }
    }
  }

  "MultiBuilder.errorSubQuery" should {

    "send SubQueryError event on errorSubQuery(query)" in new ctx {
      builder.errorSubQuery(query.id, new Exception("boom!")).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(SubQueryError(query.id, "Exception(boom!)"))
      }
    }

    "omit exception class on ExceptionPropagatedToClient" in new ctx {
      builder.errorSubQuery(query.id, ExceptionPropagatedToClient("boom!")).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(SubQueryError(query.id, "boom!"))
      }
    }
  }

  "MultiBuilder.error" should {

    "send Error event on error(query)" in new ctx {
      builder.error(query.id, new Exception("boom!")).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Error(query.id, "Exception(boom!)"))
      }
    }

    "omit exception class on ExceptionPropagatedToClient" in new ctx {
      builder.error(query.id, ExceptionPropagatedToClient("boom!")).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Error(query.id, "boom!"))
      }
    }
  }

  "MultiBuilder.addSubQuery" should {

    "send SubQueryFields if columns are present in results during addSubQuery(queryId, results)" in new ctx {
      val batch = Batch(List.empty, Option(List(BatchColumn("column"))))
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(SubQueryFields("query-id", List("column")))
      }
    }

    "send SubQueryFields only once if columns are present in results during addSubQuery(queryId, results)" in new ctx {
      val batch = Batch(List.empty, Option(List(BatchColumn("column"))))
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads.filter(_ == SubQueryFields("query-id", List("column"))) must haveSize(1)
      }
    }

    "send Progress if present in results during addSubQuery(queryId, results)" in new ctx {
      val batch = Batch(List.empty).withPercentage(100)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Progress("query-id", 100))
      }
    }

    "send Progress on every batch during addSubQuery(queryId, results)" in new ctx {
      val batch = Batch(List.empty).withPercentage(100)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads.filter(_ == Progress("query-id", 100)) must haveSize(2)
      }
    }

    "send Error if present in results during addSubQuery(queryId, results)" in new ctx {
      val batch = Batch(List.empty, error = Option(BatchError("boom!")))
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Error("query-id", "boom!"))
      }
    }

    "send Row events if data is present in results during addSubQuery(queryId, code, results)" in new ctx {
      val batch = Batch(List(List("a", "b", "c"), List("d", "e", "f")))
      builder.addSubQuery("query-id", batch).runToFuture(Scheduler.global)

      eventually {
        consumer.payloads must contain(Row("query-id", List("a", "b", "c")))
        consumer.payloads must contain(Row("query-id", List("d", "e", "f")))
      }
    }
  }

}

class TestConsumer[T] extends Consumer[T] {
  val payloads = ListBuffer.empty[T]

  override def id: String = "id"

  override def user: User = User("test")

  override def write(payload: T): Task[Unit] = Task(payloads += payload)

  override def close(): Task[Unit] = Task.unit
}

================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/sql/PrestoSqlOpsTest.scala
================================================
package quix.core.sql

import org.specs2.mutable.SpecWithJUnit
import quix.core.sql.PrestoSqlOps.{splitToStatements => split}

class PrestoSqlOpsTest extends SpecWithJUnit {

  "PlainPrestoSqlSupport.splitToStatements" should {
    "handle single line statements" in {
      split("select 1") must contain("select 1")
    }

    "handle delimited statements" in {
      split("select 1;select 2") must_=== List("select 1", "select 2")
    }

    "handle delimited statements with empty partial statement" in {
      split("select 1;select 2;") must contain("select 1", "select 2")
    }

    "handle delimited statements with many empty lines between them" in {
      val newlines = List.fill(10)("\n").mkString
      val sql = "select 1;" + newlines + "select 2"
      split(sql) must contain("select 1", "select 2")
    }

    "handle empty strings" in {
      split("       \n\n\n\n\n") must beEmpty
    }

    "handle trailing comments" in {
      val sqls = split("select 1;\n--comment1\n--comment2")

      sqls must_=== List("select 1")
    }

    "do not strip leading newlines in case of single statement" in {
      val sqls = split("\nselect 1")

      sqls must_=== List("\nselect 1")
    }

    "do not strip leading newlines in case of multiple statements" in {
      val sqls = split("\nselect 1;\nselect 2;")

      sqls must_=== List("\nselect 1", "select 2")
    }

    "do not strip leading newlines in case of multiple statements" in {
      val sqls = split("\n--comment\nselect 1;\nselect 2;")

      sqls must_=== List("\n--comment\nselect 1", "select 2")
    }

  }

}


================================================
FILE: quix-backend/quix-core/src/test/scala/quix/core/sql/StopWordsSplitterTest.scala
================================================
package quix.core.sql

import org.specs2.mutable.SpecWithJUnit

class StopWordsSplitterTest extends SpecWithJUnit {

  "StopWordSqlSplitter.split" should {
    "do not split on stop word" in {
      val splitter = new StopWordSqlSplitter("FUNCTION")

      splitter.split(
        """
          |CREATE TEMP FUNCTION FOO;
          |SELECT 1;
          |""".stripMargin) must contain(
        """
          |CREATE TEMP FUNCTION FOO;
          |SELECT 1""".stripMargin)
    }

    "split on non stop word" in {
      val splitter = new StopWordSqlSplitter("FUNCTION")

      val splits = splitter.split(
        """
          |CREATE TEMP FUNCTION FOO;
          |SELECT 1;
          |SELECT 2;
          |""".stripMargin)

      splits must contain(
        """
          |CREATE TEMP FUNCTION FOO;
          |SELECT 1""".stripMargin)

      splits must contain("SELECT 2")

    }
  }

}


================================================
FILE: quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaAutocomplete.scala
================================================
package quix.athena

import monix.eval.Task
import quix.api.v1.db.{Autocomplete, Catalog, Catalogs}

class AthenaAutocomplete(val catalogs: Catalogs) extends Autocomplete {

  override def fast: Task[Map[String, List[String]]] = catalogs.fast.map(extractAutoCompleteItems)

  override def full: Task[Map[String, List[String]]] = catalogs.full.map(extractAutoCompleteItems)

  def extractAutoCompleteItems(catalogList: List[Catalog]): Map[String, List[String]] = {
    Map("schemas" -> catalogList.flatMap(_.children.map(_.name)),
      "tables" -> catalogList.flatMap(_.children.flatMap(_.children.map(_.name))))
  }
}


================================================
FILE: quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaCatalogs.scala
================================================
package quix.athena

import monix.eval.Task
import quix.api.v1.db.{Catalog, Catalogs, Schema, Table}
import quix.api.v2.execute.Executor
import quix.core.executions.SingleQueryExecutor

class AthenaCatalogs(val queryExecutor: Executor) extends Catalogs with SingleQueryExecutor {

  override def fast: Task[List[Catalog]] = {
    for {schemas <- executeForSingleColumn("show databases")}
      yield List(Catalog("__root", schemas.map(schema => Schema(schema, Nil))))
  }

  override def full: Task[List[Catalog]] = {
    for {
      schemaNames <- executeForSingleColumn("show databases")
      schemas <- Task.traverse(schemaNames)(inferSchemaInOneQuery)
    } yield List(Catalog("__root", schemas))
  }

  def inferSchemaInOneQuery(schemaName: String): Task[Schema] = {
    val sql = s"show tables in `$schemaName`"

    for {
      tablesNames <- executeForSingleColumn(sql)
    } yield {
      val tables = tablesNames.map(table => Table(table, List()))
      Schema(schemaName, tables.sortBy(_.name))
    }
  }
}


================================================
FILE: quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaClient.scala
================================================
package quix.athena

import com.amazonaws.services.athena.model.{GetQueryExecutionResult, GetQueryResultsResult, StartQueryExecutionResult}
import monix.eval.Task
import quix.api.v2.execute.SubQuery

trait AthenaClient {
  def init(query: SubQuery): Task[StartQueryExecutionResult]

  def get(queryId: String): Task[GetQueryExecutionResult]

  def advance(queryId: String, tokenOpt: Option[String] = None): Task[GetQueryResultsResult]

  def close(queryId: String): Task[Unit]
}


================================================
FILE: quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaConfig.scala
================================================
package quix.athena

case class AthenaConfig(output: String,
                        region: String,
                        database: String,
                        firstEmptyStateDelay : Long,
                        requestTimeout : Long,
                        accessKey : String = "",
                        secretKey : String = "") {
  override def toString: String = s"AthenaConfig($output,$region,$database,$firstEmptyStateDelay,$requestTimeout,****,***)"
}



================================================
FILE: quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaQueryExecutor.scala
================================================
package quix.athena

import java.net.{ConnectException, SocketException, SocketTimeoutException}

import com.amazonaws.SdkClientException
import com.amazonaws.auth._
import com.amazonaws.services.athena.AmazonAthenaClient
import com.amazonaws.services.athena.model.{AmazonAthenaException, GetQueryResultsResult, QueryExecutionState, StartQueryExecutionResult, Row => AthenaRow}
import com.typesafe.scalalogging.LazyLogging
import monix.eval.Task
import quix.api.v1.execute.{Batch, BatchColumn}
import quix.api.v2.execute._
import quix.core.utils.TaskOps._

import scala.concurrent.duration.{FiniteDuration, _}

class AthenaQueryExecutor(val client: AthenaClient,
                          val initialAdvanceDelay: FiniteDuration = 100.millis,
                          val maxAdvanceDelay: FiniteDuration = 15.seconds)
  extends Executor with LazyLogging {

  def waitLoop(queryId: String, activeQuery: SubQuery, builder: Builder, delay: FiniteDuration = initialAdvanceDelay): Task[QueryExecutionState] = {
    val runningStatuses = Set(QueryExecutionState.RUNNING, QueryExecutionState.QUEUED).map(_.toString)
    val failed = Set(QueryExecutionState.FAILED, QueryExecutionState.CANCELLED).map(_.toString)

    client.get(queryId).map(_.getQueryExecution).flatMap {
      case query if runningStatuses.contains(query.getStatus.getState) && !activeQuery.canceled.get =>
        for {
          _ <- Task(logger.info(s"method=waitLoop event=not-finished query-id=$queryId user=${activeQuery.user.email} status=${query.getStatus.getState} delay=$delay"))
          _ <- builder.addSubQuery(queryId, Batch(data = List.empty))
          status <- waitLoop(queryId, activeQuery, builder, maxAdvanceDelay.min(delay * 2)).delayExecution(delay)
        } yield status

      case query if failed.contains(query.getStatus.getState) =>
        for {
          _ <- Task(logger.info(s"method=waitLoop event=failed query-id=$queryId user=${activeQuery.user.email} delay=$delay status=${query.getStatus.getState} canceled=${activeQuery.canceled.get}"))
          _ <- builder.errorSubQuery(queryId, new IllegalStateException(s"Query failed with status ${query.getStatus.getState} with reason = ${query.getStatus.getStateChangeReason}"))
        } yield QueryExecutionState.fromValue(query.getStatus.getState)

      case query if query.getStatus.getState == QueryExecutionState.SUCCEEDED.toString || activeQuery.canceled.get =>
        Task.eval(logger.info(s"method=waitLoop event=finished query-id=$queryId user=${activeQuery.user.email} delay=$delay status=${query.getStatus.getState} canceled=${activeQuery.canceled.get}"))
          .map(_ => QueryExecutionState.fromValue(query.getStatus.getState))
    }
  }

  def drainResults(queryId: String, nextToken: Option[String], builder: Builder, query: SubQuery): Task[Option[String]] = {
    val log = Task(logger.info(s"method=drainResults event=start query-id=$queryId user=${query.user.email} tokenOpt=$nextToken"))

    val tokenTask = nextToken match {
      case Some(_) if !query.canceled.get =>
        for {
          nextState <- advance(builder, queryId, query, nextToken)

          _ <- builder.addSubQuery(queryId, makeBatch(nextState))

          futureState <- drainResults(queryId, Option(nextState.getNextToken), builder, query)
        } yield futureState

      case _ =>
        Task.now(nextToken)
    }

    log.flatMap(_ => tokenTask)
  }

  def fetchFirstBatch(queryId: String, builder: Builder, query: SubQuery): Task[Option[String]] = {
    val log = Task(logger.info(s"method=fetchFirstBatch event=start query-id=$queryId user=${query.user.email} cancelled=${query.canceled.get()}"))

    val batch = if (query.canceled.get) Task.now(None)
    else for {
      state <- advance(builder, queryId, query)
      _ <- builder.addSubQuery(queryId, makeBatch(state, isFirst = true))
      _ <- Task(logger.info(s"method=fetchFirstBatch event=done query-id=$queryId user=${query.user.email} cancelled=${query.canceled.get()} tokenOpt=${state.getNextToken}"))
    } yield Option(state.getNextToken)

    log.flatMap(_ => batch)
  }

  def makeBatch(result: GetQueryResultsResult, isFirst: Boolean = false): Batch = {
    logger.info(s"method=makeBatch event=start isFirst=$isFirst rows=${result.getResultSet.getRows.size()}")

    import scala.collection.JavaConverters._
    // first batch contains columns as first row

    val columns = if (isFirst) {
      val rs = result.getResultSet
      Option(rs.getResultSetMetadata.getColumnInfo.asScala.map(col => BatchColumn(col.getName)).toList)
    } else None

    val types = result.getResultSet.getResultSetMetadata.getColumnInfo.asScala.map(_.getType)

    val res = result.getResultSet

    val rows = res.getRows.asScala.toList

    val data = for ((row, index) <- rows.zipWithIndex if !columnsRow(row, index, columns))
      yield {
        for ((datatype, datum) <- types.zip(row.getData.asScala.map(_.getVarCharValue)).toList)
          yield convert(datatype, datum)
      }

    Batch(data = data, columns = columns)
  }

  /*
    athena docs states that first row contains column names, we need to skip that row
   */
  def columnsRow(row: AthenaRow, index: Int, maybeColumns: Option[List[BatchColumn]]) = {
    import scala.collection.JavaConverters._

    if (index == 0) {
      val values = row.getData.asScala.map(_.getVarCharValue).toList
      val types = maybeColumns.map(_.map(_.name)).getOrElse(Nil)

      values == types
    } else false
  }

  def convert(datatype: String, datum: String): AnyRef = {
    datatype match {
      case "varchar" => String.valueOf(datum)
      case "tinyint" => new Integer(datum)
      case "smallint" => new Integer(datum)
      case "integer" => new Integer(datum)
      case "bigint" => new java.lang.Long(datum)
      case "double" => new java.lang.Double(datum)
      case "boolean" => new java.lang.Boolean(datum)
      case "date" => String.valueOf(datum)
      case "timestamp" => String.valueOf(datum)
      case _ => String.valueOf(datum.toString)
    }
  }

  def advance(builder: Builder, queryId: String, query: SubQuery, token: Option[String] = None): Task[GetQueryResultsResult] = {

    client.advance(queryId, token)
      .onErrorHandleWith {
        case e@(_: ConnectException | _: SocketTimeoutException | _: SocketException) =>
          val ex = new IllegalStateException(s"Athena can't be reached, please try later. Underlying exception name is ${e.getClass.getSimpleName}", e)
          builder.errorSubQuery(queryId, ex)
            .flatMap(_ => Task.raiseError(ex))

        case ex: Exception =>
          val log = Task(logger.warn(s"method=advance event=error query-id=$queryId user=${query.user.email} cancelled=${query.canceled.get()}", ex))

          builder.errorSubQuery(queryId, ex)
            .flatMap(_ => log)
            .flatMap(_ => Task.raiseError(ex))
      }
  }

  def execute(query: SubQuery, builder: Builder): Task[Unit] = {
    val close = (startExecution: StartQueryExecutionResult) => client.close(startExecution.getQueryExecutionId)

    initClient(query, builder).bracket { startExecution =>
      val queryLoop = for {
        queryState <- waitLoop(startExecution.getQueryExecutionId, query, builder, initialAdvanceDelay)
        _ <- if (queryState == QueryExecutionState.SUCCEEDED) {
          for {
            token <- fetchFirstBatch(startExecution.getQueryExecutionId, builder, query)
            _ <- drainResults(startExecution.getQueryExecutionId, token, builder, query)
          } yield ()
        } else Task.unit
      } yield ()

      for {
        _ <- Task.eval(logger.info(s"method=runAsync event=start query-id=${query.id} user=${query.user.email} " +
          s"sql=${query.text.replace("\n", "-newline-").replace("\\s", "-space-")}"))

        _ <- builder.startSubQuery(startExecution.getQueryExecutionId, query.text)
        _ <- queryLoop.onErrorFallbackTo(Task.unit)
        _ <- builder.endSubQuery(startExecution.getQueryExecutionId)

        _ <- Task.eval(logger.info(s"method=runAsync event=end query-id=${query.id} user=${query.user.email} rows=${builder.rowCount}"))
      } yield ()
    }(close)
  }

  def initClient(query: SubQuery, builder: Builder): Task[StartQueryExecutionResult] = {
    val log = Task(logger.info(s"method=initClient event=start query-id=${query.id} user=${query.user.email} sql=${query.text}"))

    val clientTask = client
      .init(query)
      .logOnError(s"method=initClient event=error query-id=${query.id} user=${query.user.email} sql=${query.text}")
      .onErrorHandleWith {
        case e: Exception =>
          builder.error(query.id, rewriteException(e))
            .flatMap(_ => Task.raiseError(rewriteException(e)))
      }

    log.flatMap(_ => clientTask)
  }

  def rewriteException(e: Exception): Exception = {
    def badCredentials(e: Exception) = {
      new IllegalStateException(
        s"""
           |Athena can't be reached, make sure you configured aws credentials correctly.
           |Refer to https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html for details.
           |Quix is using DefaultAWSCredentialsProviderChain from aws-java-sdk to discover the aws credentials.
           |
           |Underlying exception name is ${e.getClass.getSimpleName} with message [${e.getMessage}]
           |
           |""".stripMargin, e)
    }

    e match {
      case e: SdkClientException
        if e.getMessage.contains("Unable to load AWS credentials") ||
          e.getMessage.contains("Unable to load credentials") => badCredentials(e)

      case e: AmazonAthenaException if e.getMessage.contains("Check your AWS Secret Access Key") =>
        badCredentials(e)

      case e: AmazonAthenaException if e.getMessage.contains("The security token included in the request is invalid") =>
        badCredentials(e)

      case e@(_: ConnectException | _: SocketTimeoutException | _: SocketException) =>
        new IllegalStateException(s"Athena can't be reached, please try later. Underlying exception name is ${e.getClass.getSimpleName}", e)
      case _ => e
    }
  }
}

object AthenaQueryExecutor {
  def apply(config: AthenaConfig) = {
    val credentials = {
      if (config.accessKey != null && config.secretKey != null && config.accessKey.nonEmpty && config.secretKey.nonEmpty) {
        new AWSCredentialsProvider {
          override def getCredentials: AWSCredentials = new BasicAWSCredentials(config.accessKey, config.secretKey)

          override def refresh(): Unit = {}
        }
      } else new DefaultAWSCredentialsProviderChain
    }

    val athena = AmazonAthenaClient.builder
      .withRegion(config.region)
      .withCredentials(credentials)
      .build()

    val client = new AwsAthenaClient(athena, config)
    new AthenaQueryExecutor(client)
  }
}

================================================
FILE: quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaTables.scala
==============================================
Download .txt
gitextract_w_z6e63k/

├── .dockerignore
├── .github/
│   └── workflows/
│       ├── quix-backend-build.yml
│       ├── quix-documentation-publish.yml
│       ├── quix-frontend-publish.yml
│       └── quix-frontend-release.yml
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── build-selector.sh
├── docker-compose.prebuilt.yml
├── docker-compose.yml
├── documentation/
│   ├── docs/
│   │   ├── about.md
│   │   ├── architecture.md
│   │   ├── athena.md
│   │   ├── bigquery.md
│   │   ├── clickhouse.md
│   │   ├── installation.md
│   │   ├── jdbc.md
│   │   ├── mariadb.md
│   │   ├── mysql.md
│   │   ├── oracle.md
│   │   ├── postgresql.md
│   │   ├── presto.md
│   │   ├── python.md
│   │   └── redshift.md
│   └── website/
│       ├── README.md
│       ├── blog/
│       │   └── 2019-11-25-first-release.md
│       ├── core/
│       │   └── Footer.js
│       ├── i18n/
│       │   └── en.json
│       ├── package.json
│       ├── pages/
│       │   └── en/
│       │       ├── help.js
│       │       ├── index.js
│       │       └── users.js
│       ├── sidebars.json
│       ├── siteConfig.js
│       └── static/
│           └── css/
│               └── custom.css
├── env-example
├── quix-backend/
│   ├── Dockerfile
│   ├── README.md
│   ├── build.sbt
│   ├── quix-api/
│   │   └── src/
│   │       └── main/
│   │           └── scala/
│   │               └── quix/
│   │                   └── api/
│   │                       ├── v1/
│   │                       │   ├── db/
│   │                       │   │   └── Db.scala
│   │                       │   ├── execute/
│   │                       │   │   ├── Api.scala
│   │                       │   │   ├── Batch.scala
│   │                       │   │   ├── ExecutionEngine.scala
│   │                       │   │   └── ExecutionProtocol.scala
│   │                       │   ├── module/
│   │                       │   │   └── ExecutionModule.scala
│   │                       │   └── users/
│   │                       │       └── Users.scala
│   │                       └── v2/
│   │                           └── execute/
│   │                               ├── Builder.scala
│   │                               ├── ExecutionModule.scala
│   │                               ├── Executor.scala
│   │                               ├── Session.scala
│   │                               └── SubQuery.scala
│   ├── quix-core/
│   │   └── src/
│   │       ├── main/
│   │       │   └── scala/
│   │       │       └── quix/
│   │       │           └── core/
│   │       │               ├── db/
│   │       │               │   ├── DbOps.scala
│   │       │               │   ├── RefreshableAutocomplete.scala
│   │       │               │   ├── RefreshableCatalogs.scala
│   │       │               │   ├── RefreshableDb.scala
│   │       │               │   └── State.scala
│   │       │               ├── download/
│   │       │               │   ├── DownloadConfig.scala
│   │       │               │   └── DownloadableBuilder.scala
│   │       │               ├── executions/
│   │       │               │   ├── DelegatingBuilder.scala
│   │       │               │   ├── SingleQueryExecutor.scala
│   │       │               │   └── SqlModule.scala
│   │       │               ├── history/
│   │       │               │   ├── Execution.scala
│   │       │               │   ├── HistoryBuilder.scala
│   │       │               │   └── dao/
│   │       │               │       ├── HistoryReadDao.scala
│   │       │               │       ├── HistoryWriteDao.scala
│   │       │               │       ├── InMemoryHistoryDao.scala
│   │       │               │       └── MySqlHistoryDao.scala
│   │       │               ├── results/
│   │       │               │   ├── MultiBuilder.scala
│   │       │               │   └── SingleBuilder.scala
│   │       │               ├── sql/
│   │       │               │   ├── PrestoSqlOps.scala
│   │       │               │   └── SqlSplitter.scala
│   │       │               └── utils/
│   │       │                   ├── Chores.scala
│   │       │                   ├── JsonOps.scala
│   │       │                   └── TaskOps.scala
│   │       └── test/
│   │           ├── resources/
│   │           │   └── db/
│   │           │       └── 001_init.sql
│   │           └── scala/
│   │               └── quix/
│   │                   └── core/
│   │                       ├── db/
│   │                       │   ├── DbOpsTest.scala
│   │                       │   └── DbQueryTest.scala
│   │                       ├── executions/
│   │                       │   └── SqlModuleTest.scala
│   │                       ├── history/
│   │                       │   ├── ExecutionMatchers.scala
│   │                       │   ├── FakeBuilder.scala
│   │                       │   ├── FakeClock.scala
│   │                       │   ├── HistoryBuilderTest.scala
│   │                       │   └── dao/
│   │                       │       ├── HistoryDaoContractTest.scala
│   │                       │       ├── InMemoryHistoryDaoTest.scala
│   │                       │       └── MySqlHistoryDaoTest.scala
│   │                       ├── results/
│   │                       │   └── MultiBuilderTest.scala
│   │                       └── sql/
│   │                           ├── PrestoSqlOpsTest.scala
│   │                           └── StopWordsSplitterTest.scala
│   ├── quix-modules/
│   │   ├── quix-athena-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── athena/
│   │   │       │               ├── AthenaAutocomplete.scala
│   │   │       │               ├── AthenaCatalogs.scala
│   │   │       │               ├── AthenaClient.scala
│   │   │       │               ├── AthenaConfig.scala
│   │   │       │               ├── AthenaQueryExecutor.scala
│   │   │       │               ├── AthenaTables.scala
│   │   │       │               ├── AwsAthenaClient.scala
│   │   │       │               └── TryAthena.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── athena/
│   │   │                       └── AthenaQueryExecutorTest.scala
│   │   ├── quix-bigquery-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── bigquery/
│   │   │       │               ├── BigQueryClient.scala
│   │   │       │               ├── BigQueryConfig.scala
│   │   │       │               ├── BigQueryQueryExecutor.scala
│   │   │       │               ├── BigQueryTestQueryExecutor.scala
│   │   │       │               ├── GoogleBigQueryClient.scala
│   │   │       │               ├── TryBigQuery.scala
│   │   │       │               └── db/
│   │   │       │                   ├── BigQueryAutocomplete.scala
│   │   │       │                   ├── BigQueryCatalogs.scala
│   │   │       │                   └── BigQueryTables.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── bigquery/
│   │   │                       └── BigQueryQueryExecutorTest.scala
│   │   ├── quix-dummy-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── dummy/
│   │   │       │               └── DummyQueryExecutor.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── dummy/
│   │   │                       └── DummyQueryExecutorTest.scala
│   │   ├── quix-jdbc-module/
│   │   │   └── src/
│   │   │       ├── it/
│   │   │       │   ├── resources/
│   │   │       │   │   └── db/
│   │   │       │   │       └── 001_init.sql
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── jdbc/
│   │   │       │               ├── EmbeddedMysqlDb.scala
│   │   │       │               ├── MysqlJdbcIntegrationTest.scala
│   │   │       │               ├── MysqlJdbcQueryExecutorIntegrationTest.scala
│   │   │       │               └── MysqlJdbcTablesIntegrationTest.scala
│   │   │       └── main/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── jdbc/
│   │   │                       ├── JdbcAutocomplete.scala
│   │   │                       ├── JdbcCatalogs.scala
│   │   │                       ├── JdbcQueryExecutor.scala
│   │   │                       └── JdbcTables.scala
│   │   ├── quix-presto-module/
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   └── scala/
│   │   │       │       └── quix/
│   │   │       │           └── presto/
│   │   │       │               ├── PrestoConfig.scala
│   │   │       │               ├── QueryExecutor.scala
│   │   │       │               ├── TestQueryExecutor.scala
│   │   │       │               ├── TryPresto.scala
│   │   │       │               ├── db/
│   │   │       │               │   ├── PrestoAutocomplete.scala
│   │   │       │               │   ├── PrestoCatalogs.scala
│   │   │       │               │   └── PrestoTables.scala
│   │   │       │               └── rest/
│   │   │       │                   ├── PrestoRestApi.scala
│   │   │       │                   ├── PrestoStateClient.scala
│   │   │       │                   ├── ScalaJPrestoOps.scala
│   │   │       │                   └── ScalaJPrestoStateClient.scala
│   │   │       └── test/
│   │   │           └── scala/
│   │   │               └── quix/
│   │   │                   └── presto/
│   │   │                       ├── QueryExecutorTest.scala
│   │   │                       ├── db/
│   │   │                       │   ├── PrestoAutocompleteTest.scala
│   │   │                       │   ├── PrestoCatalogsTest.scala
│   │   │                       │   └── PrestoTablesTest.scala
│   │   │                       └── rest/
│   │   │                           ├── ScalaJPrestoOpsTest.scala
│   │   │                           └── ScalaJPrestoStateClientTest.scala
│   │   └── quix-python-module/
│   │       └── src/
│   │           ├── main/
│   │           │   ├── resources/
│   │           │   │   ├── activator.py
│   │           │   │   ├── packages.py
│   │           │   │   └── quix.py
│   │           │   └── scala/
│   │           │       └── quix/
│   │           │           └── python/
│   │           │               ├── PythonApi.scala
│   │           │               ├── PythonBridge.scala
│   │           │               ├── PythonConfig.scala
│   │           │               ├── PythonExecutor.scala
│   │           │               ├── PythonModule.scala
│   │           │               ├── PythonProcessHandler.scala
│   │           │               ├── PythonRunningProcess.scala
│   │           │               └── TryPython.scala
│   │           └── test/
│   │               └── scala/
│   │                   └── quix/
│   │                       └── python/
│   │                           ├── PythonBridgeTest.scala
│   │                           └── PythonExecutorTest.scala
│   ├── quix-webapps/
│   │   └── quix-web-spring/
│   │       ├── pom.xml
│   │       └── src/
│   │           ├── main/
│   │           │   ├── resources/
│   │           │   │   ├── application.properties
│   │           │   │   └── logback-spring.xml
│   │           │   └── scala/
│   │           │       └── quix/
│   │           │           └── web/
│   │           │               ├── Server.scala
│   │           │               ├── auth/
│   │           │               │   ├── DemoUsers.scala
│   │           │               │   └── JwtUsers.scala
│   │           │               ├── controllers/
│   │           │               │   ├── DbController.scala
│   │           │               │   ├── DownloadController.scala
│   │           │               │   ├── HealthController.scala
│   │           │               │   ├── HistoryController.scala
│   │           │               │   └── SqlStreamingController.scala
│   │           │               └── spring/
│   │           │                   ├── HistoryDaoConfig.scala
│   │           │                   ├── SpringConfig.scala
│   │           │                   └── WebsocketsConfig.scala
│   │           └── test/
│   │               ├── resources/
│   │               │   ├── db/
│   │               │   │   └── 001_init.sql
│   │               │   ├── logback-test.xml
│   │               │   └── test.properties
│   │               └── scala/
│   │                   └── quix/
│   │                       └── web/
│   │                           ├── E2EContext.scala
│   │                           ├── SpringConfigWithTestExecutor.scala
│   │                           ├── auth/
│   │                           │   ├── DemoUsersTest.scala
│   │                           │   └── JwtUsersTest.scala
│   │                           └── controllers/
│   │                               ├── DownloadControllerTest.scala
│   │                               ├── EmbeddedMySql.scala
│   │                               ├── ExecutionEventTest.scala
│   │                               ├── HealthControllerTest.scala
│   │                               ├── HistoryControllerTest.scala
│   │                               ├── JdbcSqlStreamingControllerTest.scala
│   │                               ├── PrestoDbControllerTest.scala
│   │                               ├── PythonStreamingControllerTest.scala
│   │                               └── SqlStreamingControllerTest.scala
│   └── version.sbt
├── quix-frontend/
│   ├── .dockerignore
│   ├── .nvmrc
│   ├── Dockerfile
│   ├── README.md
│   ├── client/
│   │   ├── .dockerignore
│   │   ├── .gitignore
│   │   ├── .npmignore
│   │   ├── .npmrc
│   │   ├── .nvmrc
│   │   ├── README.md
│   │   ├── index.js
│   │   ├── package.json
│   │   ├── src/
│   │   │   ├── app.scss
│   │   │   ├── app.ts
│   │   │   ├── bootstrap.ts
│   │   │   ├── components/
│   │   │   │   ├── User/
│   │   │   │   │   ├── UserAvatar.tsx
│   │   │   │   │   └── UserAvatarAndName.tsx
│   │   │   │   ├── actions/
│   │   │   │   │   ├── actions-testkit.ts
│   │   │   │   │   ├── actions-types.ts
│   │   │   │   │   ├── actions.html
│   │   │   │   │   ├── actions.scss
│   │   │   │   │   └── actions.ts
│   │   │   │   ├── breadcrumbs/
│   │   │   │   │   ├── breadcrumbs-testkit.ts
│   │   │   │   │   ├── breadcrumbs-types.ts
│   │   │   │   │   ├── breadcrumbs.html
│   │   │   │   │   ├── breadcrumbs.scss
│   │   │   │   │   └── breadcrumbs.ts
│   │   │   │   ├── db-sidebar/
│   │   │   │   │   ├── db-sidebar-testkit.ts
│   │   │   │   │   ├── db-sidebar-types.ts
│   │   │   │   │   ├── db-sidebar.html
│   │   │   │   │   ├── db-sidebar.scss
│   │   │   │   │   └── db-sidebar.ts
│   │   │   │   ├── destination-picker/
│   │   │   │   │   ├── destination-picker-testkit.ts
│   │   │   │   │   ├── destination-picker-types.ts
│   │   │   │   │   ├── destination-picker.html
│   │   │   │   │   ├── destination-picker.scss
│   │   │   │   │   └── destination-picker.ts
│   │   │   │   ├── files-sidebar/
│   │   │   │   │   ├── files-sidebar-testkit.ts
│   │   │   │   │   ├── files-sidebar-types.ts
│   │   │   │   │   ├── files-sidebar.html
│   │   │   │   │   ├── files-sidebar.scss
│   │   │   │   │   └── files-sidebar.ts
│   │   │   │   ├── header/
│   │   │   │   │   ├── header-testkit.ts
│   │   │   │   │   ├── header-types.ts
│   │   │   │   │   ├── header.html
│   │   │   │   │   ├── header.scss
│   │   │   │   │   └── header.ts
│   │   │   │   ├── image/
│   │   │   │   │   ├── image-types.ts
│   │   │   │   │   ├── image.html
│   │   │   │   │   ├── image.scss
│   │   │   │   │   └── image.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── meta/
│   │   │   │   │   ├── meta-testkit.ts
│   │   │   │   │   ├── meta-types.ts
│   │   │   │   │   ├── meta.html
│   │   │   │   │   ├── meta.scss
│   │   │   │   │   └── meta.ts
│   │   │   │   ├── note/
│   │   │   │   │   ├── note-events.ts
│   │   │   │   │   ├── note-testkit.ts
│   │   │   │   │   ├── note-types.ts
│   │   │   │   │   ├── note.html
│   │   │   │   │   ├── note.scss
│   │   │   │   │   └── note.ts
│   │   │   │   ├── note-hints/
│   │   │   │   │   ├── note-hints.html
│   │   │   │   │   ├── note-hints.scss
│   │   │   │   │   └── note-hints.ts
│   │   │   │   ├── note-share/
│   │   │   │   │   ├── note-share-testkit.ts
│   │   │   │   │   ├── note-share-types.ts
│   │   │   │   │   ├── note-share.html
│   │   │   │   │   ├── note-share.scss
│   │   │   │   │   └── note-share.ts
│   │   │   │   ├── npc/
│   │   │   │   │   ├── npc.html
│   │   │   │   │   ├── npc.scss
│   │   │   │   │   └── npc.ts
│   │   │   │   ├── plugin-picker/
│   │   │   │   │   ├── plugin-picker-testkit.ts
│   │   │   │   │   ├── plugin-picker-types.ts
│   │   │   │   │   ├── plugin-picker.html
│   │   │   │   │   ├── plugin-picker.scss
│   │   │   │   │   └── plugin-picker.ts
│   │   │   │   ├── runner/
│   │   │   │   │   ├── runner-results-formatter.ts
│   │   │   │   │   ├── runner-testkit.ts
│   │   │   │   │   ├── runner-types.ts
│   │   │   │   │   ├── runner.html
│   │   │   │   │   ├── runner.scss
│   │   │   │   │   └── runner.ts
│   │   │   │   ├── search-results/
│   │   │   │   │   ├── search-results-testkit.ts
│   │   │   │   │   ├── search-results-types.ts
│   │   │   │   │   ├── search-results.html
│   │   │   │   │   ├── search-results.scss
│   │   │   │   │   └── search-results.ts
│   │   │   │   └── temp-query/
│   │   │   │       ├── temp-query-testkit.ts
│   │   │   │       ├── temp-query-types.ts
│   │   │   │       ├── temp-query.html
│   │   │   │       ├── temp-query.scss
│   │   │   │       └── temp-query.ts
│   │   │   ├── config.ts
│   │   │   ├── custom.d.ts
│   │   │   ├── data/
│   │   │   │   ├── examples-notebook.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── quix-folder.ts
│   │   │   ├── external-types.d.ts
│   │   │   ├── hooks.ts
│   │   │   ├── index.vm
│   │   │   ├── lib/
│   │   │   │   ├── app/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── constants.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── app/
│   │   │   │   │   │   │   ├── app.html
│   │   │   │   │   │   │   ├── app.scss
│   │   │   │   │   │   │   └── app.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── login/
│   │   │   │   │   │       ├── login.html
│   │   │   │   │   │       ├── login.scss
│   │   │   │   │   │       └── login.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── app.ts
│   │   │   │   │   │   ├── appStoreProvider.tsx
│   │   │   │   │   │   ├── builder.ts
│   │   │   │   │   │   ├── navigator.ts
│   │   │   │   │   │   ├── plugin-builder.ts
│   │   │   │   │   │   ├── sso.ts
│   │   │   │   │   │   └── user.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── typings/
│   │   │   │   │   │   ├── story-builder.ts
│   │   │   │   │   │   ├── types.d.ts
│   │   │   │   │   │   └── window.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       └── scope-utils.ts
│   │   │   │   ├── code-editor/
│   │   │   │   │   ├── ace-extensions/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── language-tools.ts
│   │   │   │   │   │   ├── presto-snippets.ts
│   │   │   │   │   │   ├── presto.mode.ts
│   │   │   │   │   │   └── searchbox.ts
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── code-editor.html
│   │   │   │   │   │   ├── code-editor.scss
│   │   │   │   │   │   ├── code-editor.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   └── services/
│   │   │   │   │       ├── code-editor-annotator.ts
│   │   │   │   │       ├── code-editor-completer.ts
│   │   │   │   │       ├── code-editor-instance.ts
│   │   │   │   │       ├── code-editor-params.ts
│   │   │   │   │       ├── code-editor-selection.ts
│   │   │   │   │       ├── code-editor-service.ts
│   │   │   │   │       ├── code-editor-shortcuts.ts
│   │   │   │   │       └── param-parser/
│   │   │   │   │           ├── index.ts
│   │   │   │   │           ├── param-renderers/
│   │   │   │   │           │   ├── boolean-param-renderer.ts
│   │   │   │   │           │   ├── datetime-param-renderer.ts
│   │   │   │   │           │   ├── index.ts
│   │   │   │   │           │   ├── input-param-renderer.ts
│   │   │   │   │           │   ├── list-param-renderer.ts
│   │   │   │   │           │   ├── option-param-renderer.ts
│   │   │   │   │           │   └── textarea-param-renderer.ts
│   │   │   │   │           ├── param-serializers/
│   │   │   │   │           │   ├── default-param-serializer.ts
│   │   │   │   │           │   ├── index.ts
│   │   │   │   │           │   ├── param-serializer.ts
│   │   │   │   │           │   └── python-param-serializer.ts
│   │   │   │   │           ├── param-types.ts
│   │   │   │   │           ├── params-parser.ts
│   │   │   │   │           └── params-predefined-types.ts
│   │   │   │   ├── core/
│   │   │   │   │   ├── ang/
│   │   │   │   │   │   ├── drv/
│   │   │   │   │   │   │   ├── bi-options.drv.ts
│   │   │   │   │   │   │   └── bi-validator.drv.ts
│   │   │   │   │   │   └── srv/
│   │   │   │   │   │       ├── ng-model/
│   │   │   │   │   │       │   ├── ng-model-test.drv.ts
│   │   │   │   │   │       │   ├── ng-model.test.ts
│   │   │   │   │   │       │   └── ng-model.ts
│   │   │   │   │   │       └── scope/
│   │   │   │   │   │           ├── index.ts
│   │   │   │   │   │           ├── scope.test.ts
│   │   │   │   │   │           └── scope.ts
│   │   │   │   │   ├── config/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── main.angular.ts
│   │   │   │   │   ├── srv/
│   │   │   │   │   │   ├── collections/
│   │   │   │   │   │   │   ├── buffered-collection.test.ts
│   │   │   │   │   │   │   ├── buffered-collection.ts
│   │   │   │   │   │   │   ├── collection.test.ts
│   │   │   │   │   │   │   ├── collection.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── partitioned-collection.test.ts
│   │   │   │   │   │   │   └── partitioned-collection.ts
│   │   │   │   │   │   ├── event-emitter/
│   │   │   │   │   │   │   ├── event-emitter.test.ts
│   │   │   │   │   │   │   ├── event-emitter.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── injector/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── local-storage/
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── local-storage.test.ts
│   │   │   │   │   │   │   └── local-storage.ts
│   │   │   │   │   │   ├── model/
│   │   │   │   │   │   │   ├── model.test.ts
│   │   │   │   │   │   │   └── model.ts
│   │   │   │   │   │   ├── socket/
│   │   │   │   │   │   │   └── socket.ts
│   │   │   │   │   │   ├── state/
│   │   │   │   │   │   │   ├── localstorage-state-provider.test.ts
│   │   │   │   │   │   │   ├── localstorage-state-provider.ts
│   │   │   │   │   │   │   ├── state-wrapper.test.ts
│   │   │   │   │   │   │   ├── state-wrapper.ts
│   │   │   │   │   │   │   ├── state.test.ts
│   │   │   │   │   │   │   ├── state.ts
│   │   │   │   │   │   │   ├── types.ts
│   │   │   │   │   │   │   ├── url-params.test.ts
│   │   │   │   │   │   │   ├── url-params.ts
│   │   │   │   │   │   │   ├── url-state-provider.test.ts
│   │   │   │   │   │   │   └── url-state-provider.ts
│   │   │   │   │   │   └── view-model/
│   │   │   │   │   │       ├── view-model.test.ts
│   │   │   │   │   │       └── view-model.ts
│   │   │   │   │   ├── types/
│   │   │   │   │   │   └── angular-promise.d.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── lodash4-polyfill.ts
│   │   │   │   │       ├── lodash4-polyfill.types.ts
│   │   │   │   │       ├── utils.test-prepare.ts
│   │   │   │   │       └── utils.test.ts
│   │   │   │   ├── file-explorer/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── file-explorer-dynamic.html
│   │   │   │   │   │   ├── file-explorer-static.html
│   │   │   │   │   │   ├── file-explorer-vm.ts
│   │   │   │   │   │   ├── file-explorer.scss
│   │   │   │   │   │   ├── file-explorer.ts
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   └── services/
│   │   │   │   │       ├── file-explorer-controller.ts
│   │   │   │   │       ├── file-explorer-instance.ts
│   │   │   │   │       ├── file-explorer-models.ts
│   │   │   │   │       ├── file-explorer-tools.ts
│   │   │   │   │       └── index.ts
│   │   │   │   ├── language-parsers/
│   │   │   │   │   ├── presto-grammar/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── lang/
│   │   │   │   │   │       └── presto/
│   │   │   │   │   │           ├── SqlBase.tokens
│   │   │   │   │   │           ├── SqlBaseLexer.tokens
│   │   │   │   │   │           ├── SqlBaseLexer.ts
│   │   │   │   │   │           ├── SqlBaseListener.ts
│   │   │   │   │   │           ├── SqlBaseParser.ts
│   │   │   │   │   │           └── SqlBaseVisitor.ts
│   │   │   │   │   ├── python-grammar/
│   │   │   │   │   │   └── lang/
│   │   │   │   │   │       └── python/
│   │   │   │   │   │           ├── Python3Lexer.js
│   │   │   │   │   │           ├── Python3Lexer.tokens
│   │   │   │   │   │           ├── Python3Listener.js
│   │   │   │   │   │           ├── Python3Parser.js
│   │   │   │   │   │           ├── Python3Visitor.js
│   │   │   │   │   │           └── index.js
│   │   │   │   │   ├── python-parser/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── parser/
│   │   │   │   │   │   │   ├── errors-listener.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   ├── parser.spec.ts
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   ├── tokenizer/
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── types/
│   │   │   │   │   │   │   ├── 3rd-party.d.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── web-worker/
│   │   │   │   │   │       ├── types.ts
│   │   │   │   │   │       ├── web-worker-entry.ts
│   │   │   │   │   │       ├── web-worker-manager.ts
│   │   │   │   │   │       └── web-worker.ts
│   │   │   │   │   └── sql-parser/
│   │   │   │   │       ├── auto-format/
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── parser/
│   │   │   │   │       │   ├── errors-listener.ts
│   │   │   │   │       │   ├── index.ts
│   │   │   │   │       │   ├── parser.spec.ts
│   │   │   │   │       │   ├── presto-listener.ts
│   │   │   │   │       │   └── types.ts
│   │   │   │   │       ├── tokenizer/
│   │   │   │   │       │   ├── index.ts
│   │   │   │   │       │   ├── tokenizer.spec.ts
│   │   │   │   │       │   └── tokensMap.ts
│   │   │   │   │       ├── types/
│   │   │   │   │       │   ├── 3rd-party.d.ts
│   │   │   │   │       │   └── index.ts
│   │   │   │   │       └── web-worker/
│   │   │   │   │           ├── types.ts
│   │   │   │   │           ├── web-worker-entry.ts
│   │   │   │   │           ├── web-worker-manager.ts
│   │   │   │   │           └── web-worker.ts
│   │   │   │   ├── runner/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── config/
│   │   │   │   │   │   └── index.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── python-runner/
│   │   │   │   │   │   │   ├── python-runner-init.ts
│   │   │   │   │   │   │   ├── python-runner.html
│   │   │   │   │   │   │   ├── python-runner.scss
│   │   │   │   │   │   │   └── python-runner.ts
│   │   │   │   │   │   ├── results/
│   │   │   │   │   │   │   └── console/
│   │   │   │   │   │   │       ├── console-result-testkit.ts
│   │   │   │   │   │   │       ├── console-result.html
│   │   │   │   │   │   │       ├── console-result.scss
│   │   │   │   │   │   │       ├── console-result.ts
│   │   │   │   │   │   │       └── console-types.ts
│   │   │   │   │   │   ├── runner/
│   │   │   │   │   │   │   ├── runner.html
│   │   │   │   │   │   │   ├── runner.scss
│   │   │   │   │   │   │   └── runner.ts
│   │   │   │   │   │   └── sql-runner/
│   │   │   │   │   │       ├── sql-runner.html
│   │   │   │   │   │       ├── sql-runner.scss
│   │   │   │   │   │       └── sql-runner.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── autocomplete/
│   │   │   │   │   │   │   ├── autocomplete-service.ts
│   │   │   │   │   │   │   ├── autocomplete-utils.ts
│   │   │   │   │   │   │   ├── highlight-and-score.ts
│   │   │   │   │   │   │   └── old-autocomplete-service.ts
│   │   │   │   │   │   ├── db/
│   │   │   │   │   │   │   └── db-service.ts
│   │   │   │   │   │   ├── permissions/
│   │   │   │   │   │   │   └── permissions-service.ts
│   │   │   │   │   │   ├── runner-event.ts
│   │   │   │   │   │   ├── runner-events.ts
│   │   │   │   │   │   ├── runner-query.ts
│   │   │   │   │   │   ├── runner-service.ts
│   │   │   │   │   │   ├── runner-socket.ts
│   │   │   │   │   │   ├── runner-state.ts
│   │   │   │   │   │   ├── syntax-valdator/
│   │   │   │   │   │   │   └── syntax-validator-service.ts
│   │   │   │   │   │   └── workers/
│   │   │   │   │   │       ├── python-parser-worker.ts
│   │   │   │   │   │       └── sql-parser-worker.ts
│   │   │   │   │   └── typings/
│   │   │   │   │       ├── angular-promise.d.ts
│   │   │   │   │       ├── runner-types.ts
│   │   │   │   │       └── types.d.ts
│   │   │   │   ├── sql-autocomplete/
│   │   │   │   │   ├── adapter/
│   │   │   │   │   │   ├── sql-autocomplete-adapter-utills.ts
│   │   │   │   │   │   ├── sql-autocomplete-adapter.ts
│   │   │   │   │   │   ├── tests/
│   │   │   │   │   │   │   ├── get-completion-tests/
│   │   │   │   │   │   │   │   ├── expected-results.ts
│   │   │   │   │   │   │   │   ├── get-completion-Items.spec.ts
│   │   │   │   │   │   │   │   └── test-inputs/
│   │   │   │   │   │   │   │       ├── input-query-context.ts
│   │   │   │   │   │   │   │       └── input-table.ts
│   │   │   │   │   │   │   └── test-utils/
│   │   │   │   │   │   │       ├── mock-db-config.ts
│   │   │   │   │   │   │       ├── test-getCompletionItemsFromQueryContext.spec.ts
│   │   │   │   │   │   │       └── tests-utils.ts
│   │   │   │   │   │   ├── trinoToJs.spec.ts
│   │   │   │   │   │   ├── trinoToJs.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── db-info/
│   │   │   │   │   │   ├── db-info-service.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── languge/
│   │   │   │   │   │   └── reserved-words.ts
│   │   │   │   │   └── sql-context-evaluator/
│   │   │   │   │       ├── context-evaluator.ts
│   │   │   │   │       ├── index.ts
│   │   │   │   │       ├── position-evaluator.ts
│   │   │   │   │       ├── presto-context-listener.ts
│   │   │   │   │       ├── tests/
│   │   │   │   │       │   ├── queries-spec/
│   │   │   │   │       │   │   ├── basic-queries.spec.ts
│   │   │   │   │       │   │   ├── join-queries.spec.ts
│   │   │   │   │       │   │   ├── nested-queries.spec.ts
│   │   │   │   │       │   │   ├── union-queries.spec.ts
│   │   │   │   │       │   │   ├── utils.ts
│   │   │   │   │       │   │   └── with-queries.spec.ts
│   │   │   │   │       │   └── result-options/
│   │   │   │   │       │       ├── basic-results.ts
│   │   │   │   │       │       ├── nested-results.ts
│   │   │   │   │       │       ├── utils.ts
│   │   │   │   │       │       └── with-results.ts
│   │   │   │   │       ├── tree-analyzer.ts
│   │   │   │   │       ├── types.ts
│   │   │   │   │       ├── utils.ts
│   │   │   │   │       └── with-clause-analyzer.ts
│   │   │   │   ├── sql-formatter/
│   │   │   │   │   ├── LICENSE
│   │   │   │   │   ├── core/
│   │   │   │   │   │   ├── Formatter.ts
│   │   │   │   │   │   ├── Indentation.ts
│   │   │   │   │   │   ├── InlineBlock.ts
│   │   │   │   │   │   ├── Params.ts
│   │   │   │   │   │   ├── Tokenizer.ts
│   │   │   │   │   │   └── tokenTypes.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── languages/
│   │   │   │   │   │   ├── SqlWithQuixVarFormmater.ts
│   │   │   │   │   │   └── StandardSqlFormatter.ts
│   │   │   │   │   └── sqlFormatter.ts
│   │   │   │   ├── store/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   └── services/
│   │   │   │   │       ├── store-cache.ts
│   │   │   │   │       ├── store-logger.ts
│   │   │   │   │       └── store.ts
│   │   │   │   ├── ui/
│   │   │   │   │   ├── app.scss
│   │   │   │   │   ├── assets/
│   │   │   │   │   │   └── css/
│   │   │   │   │   │       ├── action.scss
│   │   │   │   │   │       ├── alert.scss
│   │   │   │   │   │       ├── align.scss
│   │   │   │   │   │       ├── animations.scss
│   │   │   │   │   │       ├── app/
│   │   │   │   │   │       │   ├── app-header.scss
│   │   │   │   │   │       │   └── app-menu.scss
│   │   │   │   │   │       ├── badge.scss
│   │   │   │   │   │       ├── border.scss
│   │   │   │   │   │       ├── button.scss
│   │   │   │   │   │       ├── caret.scss
│   │   │   │   │   │       ├── colors.scss
│   │   │   │   │   │       ├── def/
│   │   │   │   │   │       │   ├── action.def.scss
│   │   │   │   │   │       │   ├── alert.def.scss
│   │   │   │   │   │       │   ├── align.def.scss
│   │   │   │   │   │       │   ├── animations.def.scss
│   │   │   │   │   │       │   ├── app/
│   │   │   │   │   │       │   │   ├── app-header.def.scss
│   │   │   │   │   │       │   │   └── app-menu.def.scss
│   │   │   │   │   │       │   ├── badge.def.scss
│   │   │   │   │   │       │   ├── border.def.scss
│   │   │   │   │   │       │   ├── button.def.scss
│   │   │   │   │   │       │   ├── caret.def.scss
│   │   │   │   │   │       │   ├── colors.def.scss
│   │   │   │   │   │       │   ├── content.def.scss
│   │   │   │   │   │       │   ├── defaults.def.scss
│   │   │   │   │   │       │   ├── dropdown.def.scss
│   │   │   │   │   │       │   ├── empty-state.def.scss
│   │   │   │   │   │       │   ├── flex.def.scss
│   │   │   │   │   │       │   ├── header.def.scss
│   │   │   │   │   │       │   ├── heading.def.scss
│   │   │   │   │   │       │   ├── hint.def.scss
│   │   │   │   │   │       │   ├── icon.def.scss
│   │   │   │   │   │       │   ├── input.def.scss
│   │   │   │   │   │       │   ├── label.def.scss
│   │   │   │   │   │       │   ├── link.def.scss
│   │   │   │   │   │       │   ├── media.def.scss
│   │   │   │   │   │       │   ├── morph.def.scss
│   │   │   │   │   │       │   ├── nav-tabs.def.scss
│   │   │   │   │   │       │   ├── panel.def.scss
│   │   │   │   │   │       │   ├── section.def.scss
│   │   │   │   │   │       │   ├── space.def.scss
│   │   │   │   │   │       │   ├── spinner.def.scss
│   │   │   │   │   │       │   ├── state.def.scss
│   │   │   │   │   │       │   ├── table.def.scss
│   │   │   │   │   │       │   ├── tag.def.scss
│   │   │   │   │   │       │   ├── theme.def.scss
│   │   │   │   │   │       │   ├── toggle.def.scss
│   │   │   │   │   │       │   └── trim.def.scss
│   │   │   │   │   │       ├── dialog.scss
│   │   │   │   │   │       ├── dropdown.scss
│   │   │   │   │   │       ├── empty-state.scss
│   │   │   │   │   │       ├── flex.scss
│   │   │   │   │   │       ├── fonts.scss
│   │   │   │   │   │       ├── form.scss
│   │   │   │   │   │       ├── heading.scss
│   │   │   │   │   │       ├── hint.scss
│   │   │   │   │   │       ├── home-action.scss
│   │   │   │   │   │       ├── hover.scss
│   │   │   │   │   │       ├── icon.scss
│   │   │   │   │   │       ├── input.scss
│   │   │   │   │   │       ├── label.scss
│   │   │   │   │   │       ├── link.scss
│   │   │   │   │   │       ├── media.scss
│   │   │   │   │   │       ├── mouse.scss
│   │   │   │   │   │       ├── nav-tabs.scss
│   │   │   │   │   │       ├── no-select.scss
│   │   │   │   │   │       ├── panel.scss
│   │   │   │   │   │       ├── reset.scss
│   │   │   │   │   │       ├── scroll.scss
│   │   │   │   │   │       ├── section.scss
│   │   │   │   │   │       ├── space.scss
│   │   │   │   │   │       ├── spinner.scss
│   │   │   │   │   │       ├── state.scss
│   │   │   │   │   │       ├── table.scss
│   │   │   │   │   │       ├── tag.scss
│   │   │   │   │   │       ├── text.scss
│   │   │   │   │   │       ├── theme.scss
│   │   │   │   │   │       ├── toggle.scss
│   │   │   │   │   │       └── wrap.scss
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── components/
│   │   │   │   │   │   ├── Highlighter.tsx
│   │   │   │   │   │   ├── autocomplete/
│   │   │   │   │   │   │   ├── Autocomplete.tsx
│   │   │   │   │   │   │   └── autocomplete.hook.ts
│   │   │   │   │   │   ├── date-picker/
│   │   │   │   │   │   │   ├── DatePicker.tsx
│   │   │   │   │   │   │   ├── date-picker-utils.ts
│   │   │   │   │   │   │   └── date-picker.hook.ts
│   │   │   │   │   │   ├── dropdown/
│   │   │   │   │   │   │   ├── Dropdown.tsx
│   │   │   │   │   │   │   └── dropdown.scss
│   │   │   │   │   │   ├── hoc/
│   │   │   │   │   │   │   └── makePagination.tsx
│   │   │   │   │   │   ├── input/
│   │   │   │   │   │   │   ├── Input.tsx
│   │   │   │   │   │   │   └── input.scss
│   │   │   │   │   │   ├── panel/
│   │   │   │   │   │   │   └── Panel.tsx
│   │   │   │   │   │   ├── states/
│   │   │   │   │   │   │   ├── EmptyState.tsx
│   │   │   │   │   │   │   ├── ErrorState.tsx
│   │   │   │   │   │   │   ├── FilterInitialState.tsx
│   │   │   │   │   │   │   ├── InitialState.tsx
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   └── table/
│   │   │   │   │   │       ├── Table.scss
│   │   │   │   │   │       ├── Table.tsx
│   │   │   │   │   │       ├── TableRow.tsx
│   │   │   │   │   │       └── table-testkit.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── breadcrumbs/
│   │   │   │   │   │   │   ├── breadcrumbs.html
│   │   │   │   │   │   │   ├── breadcrumbs.scss
│   │   │   │   │   │   │   ├── breadcrumbs.story.ts
│   │   │   │   │   │   │   └── breadcrumbs.ts
│   │   │   │   │   │   ├── common/
│   │   │   │   │   │   │   └── dropdown-list.ts
│   │   │   │   │   │   ├── content-editable/
│   │   │   │   │   │   │   ├── content-editable.scss
│   │   │   │   │   │   │   └── content-editable.ts
│   │   │   │   │   │   ├── copy-to-clipboard/
│   │   │   │   │   │   │   ├── copy-to-clipboard.html
│   │   │   │   │   │   │   ├── copy-to-clipboard.scss
│   │   │   │   │   │   │   ├── copy-to-clipboard.story.ts
│   │   │   │   │   │   │   └── copy-to-clipboard.ts
│   │   │   │   │   │   ├── date-picker/
│   │   │   │   │   │   │   ├── date-picker.scss
│   │   │   │   │   │   │   ├── date-picker.story.ts
│   │   │   │   │   │   │   └── date-picker.ts
│   │   │   │   │   │   ├── draggable/
│   │   │   │   │   │   │   ├── draggable.story.ts
│   │   │   │   │   │   │   └── draggable.ts
│   │   │   │   │   │   ├── dropdown/
│   │   │   │   │   │   │   ├── dropdown.html
│   │   │   │   │   │   │   ├── dropdown.scss
│   │   │   │   │   │   │   ├── dropdown.story.ts
│   │   │   │   │   │   │   └── dropdown.ts
│   │   │   │   │   │   ├── droppable/
│   │   │   │   │   │   │   ├── droppable.story.ts
│   │   │   │   │   │   │   └── droppable.ts
│   │   │   │   │   │   ├── dual-action/
│   │   │   │   │   │   │   ├── dual-action.html
│   │   │   │   │   │   │   ├── dual-action.scss
│   │   │   │   │   │   │   └── dual-action.ts
│   │   │   │   │   │   ├── editable/
│   │   │   │   │   │   │   ├── editable.html
│   │   │   │   │   │   │   ├── editable.scss
│   │   │   │   │   │   │   ├── editable.story.ts
│   │   │   │   │   │   │   └── editable.ts
│   │   │   │   │   │   ├── filter/
│   │   │   │   │   │   │   ├── filter-items.ts
│   │   │   │   │   │   │   ├── filter-term.ts
│   │   │   │   │   │   │   ├── filter.story.ts
│   │   │   │   │   │   │   ├── filter.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── focus/
│   │   │   │   │   │   │   ├── focus-if.ts
│   │   │   │   │   │   │   ├── focus.story.ts
│   │   │   │   │   │   │   ├── focus.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── foldable/
│   │   │   │   │   │   │   ├── foldable.html
│   │   │   │   │   │   │   ├── foldable.scss
│   │   │   │   │   │   │   ├── foldable.story.ts
│   │   │   │   │   │   │   └── foldable.ts
│   │   │   │   │   │   ├── html/
│   │   │   │   │   │   │   └── html.ts
│   │   │   │   │   │   ├── icon-badge/
│   │   │   │   │   │   │   ├── icon-badge.html
│   │   │   │   │   │   │   ├── icon-badge.scss
│   │   │   │   │   │   │   └── icon-badge.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── infinite-scroll/
│   │   │   │   │   │   │   └── infinite-scroll.ts
│   │   │   │   │   │   ├── info/
│   │   │   │   │   │   │   ├── info.html
│   │   │   │   │   │   │   ├── info.scss
│   │   │   │   │   │   │   └── info.ts
│   │   │   │   │   │   ├── key-nav/
│   │   │   │   │   │   │   └── key-nav.ts
│   │   │   │   │   │   ├── maximizable/
│   │   │   │   │   │   │   ├── maximizable.scss
│   │   │   │   │   │   │   ├── maximizable.story.ts
│   │   │   │   │   │   │   └── maximizable.ts
│   │   │   │   │   │   ├── on-image-load/
│   │   │   │   │   │   │   └── on-image-load.ts
│   │   │   │   │   │   ├── progress-gauge/
│   │   │   │   │   │   │   ├── progress-gauge.html
│   │   │   │   │   │   │   ├── progress-gauge.scss
│   │   │   │   │   │   │   ├── progress-gauge.story.ts
│   │   │   │   │   │   │   └── progress-gauge.ts
│   │   │   │   │   │   ├── progress-line/
│   │   │   │   │   │   │   ├── progress-line.html
│   │   │   │   │   │   │   ├── progress-line.scss
│   │   │   │   │   │   │   └── progress-line.ts
│   │   │   │   │   │   ├── resizable/
│   │   │   │   │   │   │   └── resizable.ts
│   │   │   │   │   │   ├── scroll/
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── scroll-to.ts
│   │   │   │   │   │   ├── search/
│   │   │   │   │   │   │   ├── search.html
│   │   │   │   │   │   │   ├── search.scss
│   │   │   │   │   │   │   ├── search.story.ts
│   │   │   │   │   │   │   └── search.ts
│   │   │   │   │   │   ├── simple-select/
│   │   │   │   │   │   │   ├── simple-select.html
│   │   │   │   │   │   │   ├── simple-select.scss
│   │   │   │   │   │   │   ├── simple-select.story.ts
│   │   │   │   │   │   │   └── simple-select.ts
│   │   │   │   │   │   ├── state-loader/
│   │   │   │   │   │   │   ├── state-loader.scss
│   │   │   │   │   │   │   └── state-loader.ts
│   │   │   │   │   │   ├── table/
│   │   │   │   │   │   │   ├── header/
│   │   │   │   │   │   │   │   ├── table-header.html
│   │   │   │   │   │   │   │   ├── table-header.scss
│   │   │   │   │   │   │   │   └── table-header.ts
│   │   │   │   │   │   │   ├── row/
│   │   │   │   │   │   │   │   └── table-row.ts
│   │   │   │   │   │   │   ├── table.html
│   │   │   │   │   │   │   ├── table.scss
│   │   │   │   │   │   │   ├── table.story.ts
│   │   │   │   │   │   │   └── table.ts
│   │   │   │   │   │   ├── tabs/
│   │   │   │   │   │   │   ├── tabs-router.html
│   │   │   │   │   │   │   ├── tabs-router.ts
│   │   │   │   │   │   │   ├── tabs.html
│   │   │   │   │   │   │   ├── tabs.scss
│   │   │   │   │   │   │   ├── tabs.story.ts
│   │   │   │   │   │   │   └── tabs.ts
│   │   │   │   │   │   ├── tags/
│   │   │   │   │   │   │   ├── tags.html
│   │   │   │   │   │   │   ├── tags.scss
│   │   │   │   │   │   │   ├── tags.story.ts
│   │   │   │   │   │   │   └── tags.ts
│   │   │   │   │   │   └── tooltip/
│   │   │   │   │   │       ├── tooltip.html
│   │   │   │   │   │       ├── tooltip.scss
│   │   │   │   │   │       ├── tooltip.story.ts
│   │   │   │   │   │       └── tooltip.ts
│   │   │   │   │   ├── filters/
│   │   │   │   │   │   ├── absolute-date.ts
│   │   │   │   │   │   ├── date-utc.ts
│   │   │   │   │   │   ├── date.ts
│   │   │   │   │   │   ├── highlight.story.ts
│   │   │   │   │   │   ├── highlight.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── relative-date.ts
│   │   │   │   │   │   └── to-human-case.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── confirm.story.ts
│   │   │   │   │   │   ├── confirm.ts
│   │   │   │   │   │   ├── date.ts
│   │   │   │   │   │   ├── dialog-testkit.ts
│   │   │   │   │   │   ├── dialog.story.ts
│   │   │   │   │   │   ├── dialog.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── toast.scss
│   │   │   │   │   │   ├── toast.story.ts
│   │   │   │   │   │   └── toast.ts
│   │   │   │   │   ├── stories/
│   │   │   │   │   │   ├── action.story.ts
│   │   │   │   │   │   ├── alert.story.ts
│   │   │   │   │   │   ├── align.story.ts
│   │   │   │   │   │   ├── badge.story.ts
│   │   │   │   │   │   ├── border.story.ts
│   │   │   │   │   │   ├── button.story.ts
│   │   │   │   │   │   ├── colors.story.ts
│   │   │   │   │   │   ├── empty-state.story.ts
│   │   │   │   │   │   ├── flex.story.ts
│   │   │   │   │   │   ├── form.story.ts
│   │   │   │   │   │   ├── hint.story.ts
│   │   │   │   │   │   ├── home-action.story.ts
│   │   │   │   │   │   ├── input.story.ts
│   │   │   │   │   │   ├── label.story.ts
│   │   │   │   │   │   ├── media.story.ts
│   │   │   │   │   │   ├── scroll.story.ts
│   │   │   │   │   │   ├── space.story.ts
│   │   │   │   │   │   ├── spinner.story.ts
│   │   │   │   │   │   ├── tag.story.ts
│   │   │   │   │   │   └── text.story.ts
│   │   │   │   │   └── typings/
│   │   │   │   │       ├── globals.d.ts
│   │   │   │   │       ├── turnerjs.d.ts
│   │   │   │   │       └── types.d.ts
│   │   │   │   ├── viz/
│   │   │   │   │   ├── bootstrap.ts
│   │   │   │   │   ├── directives/
│   │   │   │   │   │   ├── chart/
│   │   │   │   │   │   │   ├── chart-renderer.ts
│   │   │   │   │   │   │   ├── chart.html
│   │   │   │   │   │   │   ├── chart.scss
│   │   │   │   │   │   │   ├── chart.ts
│   │   │   │   │   │   │   └── filter/
│   │   │   │   │   │   │       ├── chart-filter.html
│   │   │   │   │   │   │       ├── chart-filter.scss
│   │   │   │   │   │   │       └── chart-filter.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── picker/
│   │   │   │   │   │   │   ├── picker.html
│   │   │   │   │   │   │   ├── picker.scss
│   │   │   │   │   │   │   └── picker.ts
│   │   │   │   │   │   ├── pie/
│   │   │   │   │   │   │   ├── filter/
│   │   │   │   │   │   │   │   ├── pie-filter.html
│   │   │   │   │   │   │   │   ├── pie-filter.scss
│   │   │   │   │   │   │   │   └── pie-filter.ts
│   │   │   │   │   │   │   ├── pie-renderer.ts
│   │   │   │   │   │   │   ├── pie.html
│   │   │   │   │   │   │   ├── pie.scss
│   │   │   │   │   │   │   └── pie.ts
│   │   │   │   │   │   ├── table/
│   │   │   │   │   │   │   ├── table-renderer.ts
│   │   │   │   │   │   │   ├── table.html
│   │   │   │   │   │   │   ├── table.scss
│   │   │   │   │   │   │   └── table.ts
│   │   │   │   │   │   ├── viz.html
│   │   │   │   │   │   ├── viz.scss
│   │   │   │   │   │   └── viz.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── init.ts
│   │   │   │   │   ├── services/
│   │   │   │   │   │   ├── chart/
│   │   │   │   │   │   │   ├── chart-conf.ts
│   │   │   │   │   │   │   ├── chart-data-service.ts
│   │   │   │   │   │   │   ├── chart-filter-service.ts
│   │   │   │   │   │   │   ├── chart-utils.ts
│   │   │   │   │   │   │   └── chart-viz-service.ts
│   │   │   │   │   │   ├── viz-conf.ts
│   │   │   │   │   │   ├── viz-data-service.ts
│   │   │   │   │   │   ├── viz-filter-service.ts
│   │   │   │   │   │   └── viz-service.ts
│   │   │   │   │   ├── transducers/
│   │   │   │   │   │   ├── chart/
│   │   │   │   │   │   │   ├── chart-input-filter-transducer.ts
│   │   │   │   │   │   │   ├── chart-meta-transducer.ts
│   │   │   │   │   │   │   └── index.ts
│   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   ├── parse-dates-transducer.ts
│   │   │   │   │   │   ├── parse-floats-transducer.ts
│   │   │   │   │   │   ├── sort-transducer.ts
│   │   │   │   │   │   └── ungroup-transducer.ts
│   │   │   │   │   └── utils/
│   │   │   │   │       ├── index.ts
│   │   │   │   │       └── utils.ts
│   │   │   │   └── web-worker-infra/
│   │   │   │       ├── types.ts
│   │   │   │       ├── web-worker/
│   │   │   │       │   └── index.ts
│   │   │   │       └── web-worker-manager/
│   │   │   │           └── index.ts
│   │   │   ├── plugins/
│   │   │   │   ├── db/
│   │   │   │   │   ├── athena-db-plugin.ts
│   │   │   │   │   ├── bigquery-db-plugin.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── jdbc-db-plugin.ts
│   │   │   │   │   └── presto-db-plugin.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── note/
│   │   │   │   │   ├── athena-note-plugin.ts
│   │   │   │   │   ├── bigquery-note-plugin.ts
│   │   │   │   │   ├── default-note-plugin.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── jdbc-note-plugin.ts
│   │   │   │   │   ├── presto-note-plugin.ts
│   │   │   │   │   └── python-note-plugin.ts
│   │   │   │   └── plugin-factory.ts
│   │   │   ├── react-components/
│   │   │   │   ├── file-explorer/
│   │   │   │   │   ├── FileExplorerComponent.scss
│   │   │   │   │   ├── FileExplorerComponent.tsx
│   │   │   │   │   ├── TreeItem.tsx
│   │   │   │   │   ├── TreeItemMenu.tsx
│   │   │   │   │   ├── file-explorer-testkit.ts
│   │   │   │   │   └── file-explorer.ts
│   │   │   │   └── index.ts
│   │   │   ├── services/
│   │   │   │   ├── db.ts
│   │   │   │   ├── dialog.ts
│   │   │   │   ├── files.ts
│   │   │   │   ├── hooks/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── use-view-state.ts
│   │   │   │   │   └── with-outside-click.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── notebook.ts
│   │   │   │   ├── notifications.ts
│   │   │   │   ├── permissions.ts
│   │   │   │   ├── plugins/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── plugin-manager.ts
│   │   │   │   │   └── plugin-types.ts
│   │   │   │   ├── popup.ts
│   │   │   │   ├── resources.ts
│   │   │   │   ├── runners.ts
│   │   │   │   ├── scope.ts
│   │   │   │   ├── search.ts
│   │   │   │   ├── state.ts
│   │   │   │   └── subscription.ts
│   │   │   ├── state-components/
│   │   │   │   ├── base/
│   │   │   │   │   ├── base.html
│   │   │   │   │   └── base.ts
│   │   │   │   ├── embed/
│   │   │   │   │   ├── embed.ts
│   │   │   │   │   └── note/
│   │   │   │   │       ├── embed-note-events.ts
│   │   │   │   │       ├── embed-note-reactions.ts
│   │   │   │   │       ├── embed-note-scope.ts
│   │   │   │   │       ├── embed-note-url.ts
│   │   │   │   │       ├── embed-note-vm.ts
│   │   │   │   │       ├── embed-note.html
│   │   │   │   │       ├── embed-note.scss
│   │   │   │   │       └── embed-note.ts
│   │   │   │   ├── favorites/
│   │   │   │   │   ├── FavoritesComponent.tsx
│   │   │   │   │   ├── favorites-events.ts
│   │   │   │   │   ├── favorites-table-fields.tsx
│   │   │   │   │   ├── favorites-testkit.ts
│   │   │   │   │   ├── favorites.scss
│   │   │   │   │   └── favorites.ts
│   │   │   │   ├── files/
│   │   │   │   │   ├── files-events.ts
│   │   │   │   │   ├── files-reactions.ts
│   │   │   │   │   ├── files-scope.ts
│   │   │   │   │   ├── files-table-fields.ts
│   │   │   │   │   ├── files-testkit.ts
│   │   │   │   │   ├── files-types.ts
│   │   │   │   │   ├── files-url.ts
│   │   │   │   │   ├── files-vm.ts
│   │   │   │   │   ├── files.html
│   │   │   │   │   ├── files.scss
│   │   │   │   │   └── files.ts
│   │   │   │   ├── history/
│   │   │   │   │   ├── HistoryComponent.scss
│   │   │   │   │   ├── HistoryComponent.tsx
│   │   │   │   │   ├── history-events.ts
│   │   │   │   │   ├── history-table-fields.tsx
│   │   │   │   │   ├── history-testkit.ts
│   │   │   │   │   └── history.ts
│   │   │   │   ├── home/
│   │   │   │   │   ├── HomeComponent.tsx
│   │   │   │   │   ├── home-testkit.ts
│   │   │   │   │   ├── home.scss
│   │   │   │   │   └── home.ts
│   │   │   │   ├── import/
│   │   │   │   │   ├── import.html
│   │   │   │   │   └── import.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── notebook/
│   │   │   │   │   ├── notebook-events.ts
│   │   │   │   │   ├── notebook-reactions.ts
│   │   │   │   │   ├── notebook-scope.ts
│   │   │   │   │   ├── notebook-testkit.ts
│   │   │   │   │   ├── notebook-types.ts
│   │   │   │   │   ├── notebook-url.ts
│   │   │   │   │   ├── notebook-vm.ts
│   │   │   │   │   ├── notebook.html
│   │   │   │   │   ├── notebook.scss
│   │   │   │   │   └── notebook.ts
│   │   │   │   ├── trash-bin/
│   │   │   │   │   ├── TrashBinComponent.tsx
│   │   │   │   │   ├── trash-bin-events.ts
│   │   │   │   │   ├── trash-bin-table-fields.tsx
│   │   │   │   │   └── trash-bin.ts
│   │   │   │   └── users/
│   │   │   │       ├── UsersComponent.tsx
│   │   │   │       ├── users-events.ts
│   │   │   │       ├── users-table-fields.tsx
│   │   │   │       ├── users-testkit.ts
│   │   │   │       ├── users.scss
│   │   │   │       └── users.ts
│   │   │   ├── store/
│   │   │   │   ├── app/
│   │   │   │   │   ├── app-actions.ts
│   │   │   │   │   └── app-branch.ts
│   │   │   │   ├── db/
│   │   │   │   │   ├── db-actions.ts
│   │   │   │   │   ├── db-branch.ts
│   │   │   │   │   └── db-cache.ts
│   │   │   │   ├── deleted-notebook/
│   │   │   │   │   ├── deleted-notebook-actions.ts
│   │   │   │   │   ├── deleted-notebook-branch.ts
│   │   │   │   │   └── deleted-notebook-cache.ts
│   │   │   │   ├── favorites/
│   │   │   │   │   ├── favorites-actions.ts
│   │   │   │   │   ├── favorites-branch.ts
│   │   │   │   │   └── favorites-cache.ts
│   │   │   │   ├── files/
│   │   │   │   │   ├── files-actions.ts
│   │   │   │   │   ├── files-branch.ts
│   │   │   │   │   └── files-cache.ts
│   │   │   │   ├── folder/
│   │   │   │   │   ├── folder-actions.ts
│   │   │   │   │   ├── folder-branch.ts
│   │   │   │   │   └── folder-cache.ts
│   │   │   │   ├── history/
│   │   │   │   │   ├── history-actions.ts
│   │   │   │   │   ├── history-branch.ts
│   │   │   │   │   └── history-cache.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── notebook/
│   │   │   │   │   ├── notebook-actions.ts
│   │   │   │   │   ├── notebook-branch.ts
│   │   │   │   │   └── notebook-cache.ts
│   │   │   │   └── users/
│   │   │   │       ├── users-actions.ts
│   │   │   │       ├── users-branch.ts
│   │   │   │       └── users-cache.ts
│   │   │   ├── types.ts
│   │   │   └── utils.ts
│   │   ├── test/
│   │   │   ├── dev/
│   │   │   │   ├── localhost.crt
│   │   │   │   ├── localhost.key
│   │   │   │   ├── server.ts
│   │   │   │   ├── vm.ts
│   │   │   │   └── websocket-mock.ts
│   │   │   ├── e2e/
│   │   │   │   ├── dbExplorer.e2e.ts
│   │   │   │   ├── driver.ts
│   │   │   │   ├── e2e-common.ts
│   │   │   │   ├── favorites.e2e.ts
│   │   │   │   ├── files.e2e.ts
│   │   │   │   ├── history.e2e.ts
│   │   │   │   ├── home.e2e.ts
│   │   │   │   ├── notebook.e2e.ts
│   │   │   │   └── users.e2e.ts
│   │   │   ├── mocha-setup.ts
│   │   │   ├── mocks.ts
│   │   │   └── test-common.ts
│   │   ├── tsconfig.json
│   │   ├── tslint.json
│   │   ├── velocity.data.json
│   │   ├── velocity.private.data.json
│   │   └── wallaby.js
│   ├── lerna.json
│   ├── npm-deploy.sh
│   ├── package.json
│   ├── service/
│   │   ├── .gitignore
│   │   ├── .npmrc
│   │   ├── .nvmrc
│   │   ├── .prettierrc
│   │   ├── .quixroot
│   │   ├── .testenv
│   │   ├── .travis.yml
│   │   ├── README.md
│   │   ├── ecosystem.config.js
│   │   ├── index.js
│   │   ├── nest-cli.json
│   │   ├── nodemon-debug.json
│   │   ├── nodemon.json
│   │   ├── ormconfig.json
│   │   ├── package.json
│   │   ├── scripts/
│   │   │   ├── create_migrations.sh
│   │   │   ├── helpers/
│   │   │   │   └── copy-statics.ts
│   │   │   ├── ormconfig.json.template
│   │   │   ├── run_migrations.sh
│   │   │   ├── start.ts
│   │   │   └── update-statics.ts
│   │   ├── src/
│   │   │   ├── app.controller.spec.ts
│   │   │   ├── app.controller.ts
│   │   │   ├── app.module.ts
│   │   │   ├── base.module.ts
│   │   │   ├── common/
│   │   │   │   ├── demo-mode-interceptor.ts
│   │   │   │   ├── entity-type.enum.ts
│   │   │   │   └── user-sanitizer.ts
│   │   │   ├── config/
│   │   │   │   ├── config.module.ts
│   │   │   │   ├── config.service.ts
│   │   │   │   ├── db-conf.ts
│   │   │   │   ├── db-connection.ts
│   │   │   │   ├── env/
│   │   │   │   │   ├── computed-settings.ts
│   │   │   │   │   ├── engine-settings.ts
│   │   │   │   │   ├── env.spec.ts
│   │   │   │   │   ├── env.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── static-settings.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── index.ts
│   │   │   │   └── utils.ts
│   │   │   ├── consts.ts
│   │   │   ├── entities/
│   │   │   │   ├── deleted-notebook/
│   │   │   │   │   ├── dbdeleted-notebook.entity.ts
│   │   │   │   │   └── deleted-notebook.repository.ts
│   │   │   │   ├── favorites/
│   │   │   │   │   └── favorites.entity.ts
│   │   │   │   ├── filenode/
│   │   │   │   │   ├── filenode.entity.ts
│   │   │   │   │   └── filenode.repository.ts
│   │   │   │   ├── folder/
│   │   │   │   │   └── folder.entity.ts
│   │   │   │   ├── index.ts
│   │   │   │   ├── note/
│   │   │   │   │   ├── dbnote.entity.ts
│   │   │   │   │   └── note.repository.ts
│   │   │   │   ├── notebook/
│   │   │   │   │   ├── dbnotebook.entity.ts
│   │   │   │   │   └── notebook.repository.ts
│   │   │   │   ├── user/
│   │   │   │   │   └── user.entity.ts
│   │   │   │   ├── utils.ts
│   │   │   │   └── version-metadata.entity.ts
│   │   │   ├── errors/
│   │   │   │   ├── exceptions.ts
│   │   │   │   └── index.ts
│   │   │   ├── main.ts
│   │   │   ├── migrations/
│   │   │   │   ├── 1558528771647-v1.ts
│   │   │   │   ├── 1558528771648-v1-metadata.ts
│   │   │   │   ├── 1562174176877-v2.ts
│   │   │   │   ├── 1614173960671-v3.ts
│   │   │   │   ├── 1614712161318-v4.ts
│   │   │   │   └── 1634023683491-v5.ts
│   │   │   ├── modules/
│   │   │   │   ├── auth/
│   │   │   │   │   ├── auth.controller.ts
│   │   │   │   │   ├── auth.module.ts
│   │   │   │   │   ├── common-auth.ts
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── login.service.ts
│   │   │   │   │   ├── types.ts
│   │   │   │   │   ├── user-decorator.ts
│   │   │   │   │   └── users.service.ts
│   │   │   │   ├── event-sourcing/
│   │   │   │   │   ├── base-action-validation.ts
│   │   │   │   │   ├── event-sourcing.module.ts
│   │   │   │   │   ├── events.service.ts
│   │   │   │   │   ├── infrastructure/
│   │   │   │   │   │   ├── action-store/
│   │   │   │   │   │   │   ├── action-store.spec.ts
│   │   │   │   │   │   │   ├── action-store.ts
│   │   │   │   │   │   │   ├── entities/
│   │   │   │   │   │   │   │   └── db-action.entity.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   ├── event-bus/
│   │   │   │   │   │   │   ├── api.ts
│   │   │   │   │   │   │   ├── context.ts
│   │   │   │   │   │   │   ├── event-bus-builder.ts
│   │   │   │   │   │   │   ├── event-bus.drawio
│   │   │   │   │   │   │   ├── event-bus.spec.ts
│   │   │   │   │   │   │   ├── event-bus.ts
│   │   │   │   │   │   │   ├── index.ts
│   │   │   │   │   │   │   └── types.ts
│   │   │   │   │   │   └── types.ts
│   │   │   │   │   ├── plugins/
│   │   │   │   │   │   ├── deleted-notebook-plugin.ts
│   │   │   │   │   │   ├── events-plugin.ts
│   │   │   │   │   │   ├── favorites-plugin.ts
│   │   │   │   │   │   ├── file-tree-plugin.ts
│   │   │   │   │   │   ├── note-plugin.ts
│   │   │   │   │   │   ├── notebook-plugin.ts
│   │   │   │   │   │   ├── trash-bin-plugin.ts
│   │   │   │   │   │   ├── user-plugin.ts
│   │   │   │   │   │   └── utils.ts
│   │   │   │   │   ├── quix-event-bus.driver.ts
│   │   │   │   │   ├── quix-event-bus.spec.ts
│   │   │   │   │   ├── quix-event-bus.ts
│   │   │   │   │   └── types.ts
│   │   │   │   ├── logger/
│   │   │   │   │   ├── logger.module.ts
│   │   │   │   │   └── logger.service.ts
│   │   │   │   ├── proxy-backend/
│   │   │   │   │   └── proxy-backend.module.ts
│   │   │   │   ├── search/
│   │   │   │   │   ├── index.ts
│   │   │   │   │   ├── parser.spec.ts
│   │   │   │   │   ├── parser.ts
│   │   │   │   │   ├── search.module.ts
│   │   │   │   │   ├── search.spec.ts
│   │   │   │   │   ├── search.ts
│   │   │   │   │   └── types.ts
│   │   │   │   └── web-api/
│   │   │   │       ├── autocomplete/
│   │   │   │       │   ├── autocomplete.controller.ts
│   │   │   │       │   └── autocomplete.service.ts
│   │   │   │       ├── deleted-notebooks/
│   │   │   │       │   ├── deleted-notebook.controller.ts
│   │   │   │       │   └── deleted-notebook.service.ts
│   │   │   │       ├── events.controller.ts
│   │   │   │       ├── events.gateway.ts
│   │   │   │       ├── favorites/
│   │   │   │       │   ├── favorites.controller.ts
│   │   │   │       │   └── favorites.service.ts
│   │   │   │       ├── folders/
│   │   │   │       │   ├── folders.controller.ts
│   │   │   │       │   ├── folders.service.ts
│   │   │   │       │   └── utils.ts
│   │   │   │       ├── notebooks/
│   │   │   │       │   ├── notebooks.controller.ts
│   │   │   │       │   └── notebooks.service.ts
│   │   │   │       ├── search.controller.ts
│   │   │   │       ├── user-list.controller.ts
│   │   │   │       ├── web-api.driver.ts
│   │   │   │       ├── web-api.module.ts
│   │   │   │       └── web-api.spec.ts
│   │   │   ├── template-engine/
│   │   │   │   └── velocity.ts
│   │   │   ├── types/
│   │   │   │   ├── 3rd-party/
│   │   │   │   │   ├── uuid.d.ts
│   │   │   │   │   └── velocity.d.ts
│   │   │   │   └── index.ts
│   │   │   └── utils/
│   │   │       ├── create-schema-helpers.ts
│   │   │       ├── deferred-promise.ts
│   │   │       └── retry-promise.ts
│   │   ├── test/
│   │   │   ├── app.e2e-spec.ts
│   │   │   ├── builder.ts
│   │   │   ├── custom-matchers.ts
│   │   │   ├── driver.ts
│   │   │   └── jest-e2e.js
│   │   ├── tsconfig.build.json
│   │   ├── tsconfig.json
│   │   └── tslint.json
│   └── shared/
│       ├── .gitignore
│       ├── config-helper/
│       │   ├── config-helper.ts
│       │   └── consts.ts
│       ├── entities/
│       │   ├── common/
│       │   │   ├── actions.ts
│       │   │   ├── common-types.ts
│       │   │   ├── create-reducer.spec.ts
│       │   │   └── create-reducer.ts
│       │   ├── deleted-notebook/
│       │   │   ├── actions.ts
│       │   │   ├── deleted-notebook.ts
│       │   │   ├── index.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── file/
│       │   │   ├── actions.ts
│       │   │   ├── file.ts
│       │   │   ├── index.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── folder/
│       │   │   ├── folder.ts
│       │   │   ├── index.ts
│       │   │   └── types.ts
│       │   ├── history/
│       │   │   ├── actions.ts
│       │   │   ├── history.ts
│       │   │   ├── index.ts
│       │   │   └── types.ts
│       │   ├── note/
│       │   │   ├── actions.ts
│       │   │   ├── index.ts
│       │   │   ├── note.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── notebook/
│       │   │   ├── actions.ts
│       │   │   ├── index.ts
│       │   │   ├── notebook.ts
│       │   │   ├── reducer.ts
│       │   │   └── types.ts
│       │   ├── trash-bin/
│       │   │   ├── actions.ts
│       │   │   ├── index.ts
│       │   │   └── types.ts
│       │   └── user/
│       │       ├── actions.ts
│       │       ├── index.ts
│       │       ├── types.ts
│       │       └── user.ts
│       ├── index.ts
│       ├── package.json
│       ├── tsconfig.json
│       ├── types/
│       │   └── search-types.ts
│       └── utils/
│           └── utils.ts
└── terraform/
    ├── README.md
    ├── acme_certificate.tf
    ├── aws-tf-backend.tf
    ├── ecs.tf
    ├── iam.tf
    ├── initialize.tf
    ├── lb.tf
    ├── outputs.tf
    ├── parameter_store.tf
    ├── provider.tf
    ├── rds.tf
    ├── route_53.tf
    ├── security_groups.tf
    ├── variables.tf
    ├── versions.tf
    └── vpc.tf
Download .txt
Showing preview only (217K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (2476 symbols across 463 files)

FILE: documentation/website/core/Footer.js
  class Footer (line 10) | class Footer extends React.Component {
    method docUrl (line 11) | docUrl(doc, language) {
    method pageUrl (line 19) | pageUrl(doc, language) {
    method render (line 24) | render() {

FILE: documentation/website/pages/en/help.js
  function Help (line 15) | function Help(props) {

FILE: documentation/website/pages/en/index.js
  class HomeSplash (line 15) | class HomeSplash extends React.Component {
    method render (line 16) | render() {
  class Index (line 76) | class Index extends React.Component {
    method render (line 77) | render() {

FILE: documentation/website/pages/en/users.js
  class Users (line 14) | class Users extends React.Component {
    method render (line 15) | render() {

FILE: quix-backend/quix-core/src/test/resources/db/001_init.sql
  type executions_history (line 1) | CREATE TABLE executions_history (

FILE: quix-backend/quix-modules/quix-jdbc-module/src/it/resources/db/001_init.sql
  type empty_table (line 1) | create table empty_table
  type small_table (line 6) | create table small_table
  type large_table (line 14) | create table large_table
  type wide_table (line 31) | create table wide_table

FILE: quix-backend/quix-modules/quix-python-module/src/main/resources/packages.py
  class Packages (line 1) | class Packages:
    method __init__ (line 3) | def __init__(self, dir, index_url, extra_url):
    method __get_installed_packages (line 8) | def __get_installed_packages(self):
    method __create_environment (line 15) | def __create_environment(self):
    method __clean (line 27) | def __clean(self, packages):
    method list (line 43) | def list(self):
    method install (line 58) | def install(self, *required_packages):
    method uninstall (line 89) | def uninstall(self, *packages):

FILE: quix-backend/quix-modules/quix-python-module/src/main/resources/quix.py
  class Quix (line 1) | class Quix:
    method __init__ (line 3) | def __init__(self):
    method fields (line 12) | def fields(self, *fields):
    method row (line 15) | def row(self, *row):
    method error (line 18) | def error(self, message):
    method info (line 21) | def info(self, message):
    method tab (line 24) | def tab(self, name):
  class Tab (line 28) | class Tab:
    method __init__ (line 29) | def __init__(self, bridge, name):
    method columns (line 33) | def columns(self, *columns):
    method row (line 36) | def row(self, *row):
    method end (line 39) | def end(self):

FILE: quix-backend/quix-webapps/quix-web-spring/src/test/resources/db/001_init.sql
  type empty_table (line 1) | create table empty_table
  type small_table (line 6) | create table small_table
  type large_table (line 14) | create table large_table

FILE: quix-frontend/client/src/bootstrap.ts
  method onClick (line 26) | onClick(window) {
  method onClick (line 42) | onClick() {

FILE: quix-frontend/client/src/components/User/UserAvatar.tsx
  type Props (line 4) | interface Props {

FILE: quix-frontend/client/src/components/User/UserAvatarAndName.tsx
  type Props (line 5) | interface Props {

FILE: quix-frontend/client/src/components/actions/actions-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class ActionsTestkit (line 8) | class ActionsTestkit extends Testkit {
    method isDeleteEnabled (line 9) | async isDeleteEnabled() {

FILE: quix-frontend/client/src/components/actions/actions-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/actions/actions.ts
  method pre (line 26) | async pre(scope: IScope) {
  function isTrashable (line 72) | function isTrashable(scope: IScope) {

FILE: quix-frontend/client/src/components/breadcrumbs/breadcrumbs-testkit.ts
  class BreadcrumbsTestkit (line 3) | class BreadcrumbsTestkit extends Testkit {
    method numOfFiles (line 4) | async numOfFiles() {
    method clickFile (line 8) | async clickFile(index: number) {
    method isFileNameFocused (line 18) | async isFileNameFocused() {
    method isFileNameEditable (line 22) | async isFileNameEditable() {

FILE: quix-frontend/client/src/components/breadcrumbs/breadcrumbs-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/breadcrumbs/breadcrumbs.ts
  method pre (line 20) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/db-sidebar/db-sidebar-testkit.ts
  class DbSidebarTestkit (line 3) | class DbSidebarTestkit extends Testkit {

FILE: quix-frontend/client/src/components/db-sidebar/db-sidebar-types.ts
  type IScope (line 3) | interface IScope extends ngIscope {
  type ServerTreeItem (line 7) | interface ServerTreeItem {

FILE: quix-frontend/client/src/components/db-sidebar/db-sidebar.ts
  type States (line 18) | enum States {
  method pre (line 46) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/destination-picker/destination-picker-testkit.ts
  class DestinationPickerTestkit (line 3) | class DestinationPickerTestkit extends Testkit {

FILE: quix-frontend/client/src/components/destination-picker/destination-picker-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/destination-picker/destination-picker.ts
  type States (line 17) | enum States {
  method pre (line 66) | async pre(scope: IScope, element, attr, ngModel) {

FILE: quix-frontend/client/src/components/files-sidebar/files-sidebar-testkit.ts
  class FilesSidebarTestkit (line 3) | class FilesSidebarTestkit extends Testkit {

FILE: quix-frontend/client/src/components/files-sidebar/files-sidebar-types.ts
  type IScope (line 3) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/files-sidebar/files-sidebar.ts
  type States (line 22) | enum States {
  method pre (line 60) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/header/header-testkit.ts
  class HeaderTestkit (line 3) | class HeaderTestkit extends Testkit {

FILE: quix-frontend/client/src/components/header/header-types.ts
  type IScope (line 3) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/header/header.ts
  method pre (line 37) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/image/image-types.ts
  type IScope (line 3) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/image/image.ts
  method pre (line 16) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/meta/meta-testkit.ts
  class ActionsTestkit (line 3) | class ActionsTestkit extends Testkit {

FILE: quix-frontend/client/src/components/meta/meta-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/meta/meta.ts
  method pre (line 15) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/note-hints/note-hints.ts
  method pre (line 9) | pre(scope: any) {

FILE: quix-frontend/client/src/components/note-share/note-share-testkit.ts
  class NoteSHareTestkit (line 3) | class NoteSHareTestkit extends Testkit {

FILE: quix-frontend/client/src/components/note-share/note-share-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/note-share/note-share.ts
  method pre (line 17) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/note/note-testkit.ts
  type Hooks (line 5) | const enum Hooks {
  class NoteTestkit (line 10) | class NoteTestkit extends Testkit {
    method getActionsTestkit (line 11) | async getActionsTestkit() {
    method getRunnerTestkit (line 15) | async getRunnerTestkit() {
    method isNameFocused (line 19) | async isNameFocused() {
    method isSelectEnabled (line 23) | async isSelectEnabled() {
    method isNameEditable (line 27) | async isNameEditable() {

FILE: quix-frontend/client/src/components/note/note-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/note/note.ts
  method pre (line 37) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/npc/npc.ts
  method pre (line 77) | async pre(scope: any, element: any) {

FILE: quix-frontend/client/src/components/plugin-picker/plugin-picker-testkit.ts
  class PluginPickerTestkit (line 3) | class PluginPickerTestkit extends Testkit {

FILE: quix-frontend/client/src/components/plugin-picker/plugin-picker-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/plugin-picker/plugin-picker.ts
  method pre (line 21) | async pre(scope: IScope, element, attr, ngModel) {

FILE: quix-frontend/client/src/components/runner/runner-testkit.ts
  type Hooks (line 4) | const enum Hooks {
  class RunnerTestkit (line 7) | class RunnerTestkit extends Testkit {
    method getConsoleResultTestkit (line 9) | async getConsoleResultTestkit() {
    method clickRun (line 13) | async clickRun() {

FILE: quix-frontend/client/src/components/runner/runner-types.ts
  type IScope (line 4) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/runner/runner.ts
  method pre (line 35) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/search-results/search-results-testkit.ts
  class SearchResultsTestkit (line 3) | class SearchResultsTestkit extends Testkit {

FILE: quix-frontend/client/src/components/search-results/search-results-types.ts
  type IScope (line 3) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/search-results/search-results.ts
  type States (line 18) | enum States {
  method pre (line 111) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/components/temp-query/temp-query-testkit.ts
  class TempQueryTestkit (line 3) | class TempQueryTestkit extends Testkit {

FILE: quix-frontend/client/src/components/temp-query/temp-query-types.ts
  type IScope (line 3) | interface IScope extends ngIscope {

FILE: quix-frontend/client/src/components/temp-query/temp-query.ts
  method pre (line 20) | pre(scope: IScope) {

FILE: quix-frontend/client/src/external-types.d.ts
  type Global (line 7) | interface Global {
  type DedicatedWorkerGlobalScope (line 12) | interface DedicatedWorkerGlobalScope {}
  type Window (line 14) | interface Window {

FILE: quix-frontend/client/src/lib/app/directives/app/app.ts
  type IScope (line 11) | interface IScope extends ng.IScope {
  function setCurrentMenuItem (line 16) | function setCurrentMenuItem(scope: IScope, item: IMenuItem) {
  method pre (line 32) | pre(scope: IScope) {

FILE: quix-frontend/client/src/lib/app/directives/login/login.ts
  type IScope (line 7) | interface IScope extends ng.IScope {
  method pre (line 19) | pre(scope: IScope) {

FILE: quix-frontend/client/src/lib/app/index.ts
  function app (line 13) | function app<Config = any>(id: string | {

FILE: quix-frontend/client/src/lib/app/services/app.ts
  type IMenuItem (line 9) | interface IMenuItem {
  class App (line 18) | class App<Config = any> {
    method constructor (line 22) | constructor(
    method init (line 50) | init(modules: string[] = []) {
    method login (line 59) | login() {
    method getId (line 64) | getId() {
    method getTitle (line 68) | getTitle() {
    method getLogoUrl (line 72) | getLogoUrl() {
    method getUser (line 76) | getUser(): User {
    method getModule (line 80) | getModule(): angular.IModule {
    method getNavigator (line 84) | getNavigator(): Navigator {
    method getPlugin (line 88) | getPlugin(id: string) {
    method getMenuItems (line 92) | getMenuItems() {
    method getStore (line 96) | getStore() {
    method getConfig (line 100) | getConfig() {
    method toggleHeader (line 104) | toggleHeader(state: boolean) {
    method toggleMenu (line 108) | toggleMenu(state: boolean) {
    method go (line 112) | go(state: string, params?: Object, options?) {

FILE: quix-frontend/client/src/lib/app/services/appStoreProvider.tsx
  type InjectedAppStoreProps (line 11) | interface InjectedAppStoreProps {

FILE: quix-frontend/client/src/lib/app/services/builder.ts
  type PluginFactory (line 26) | type PluginFactory<Config> = (app: PluginBuilder<Config>) => any;
  class Builder (line 50) | class Builder<Config = any> extends srv.eventEmitter.EventEmitter {
    method constructor (line 58) | constructor(
    method plugin (line 91) | plugin(id: string, factory: (pluginBuilder: PluginBuilder<Config>) => ...
    method state (line 104) | state(options: any): Builder<Config> {
    method component (line 119) | component(name: string, factory: angular.IDirectiveFactory): Builder<C...
    method reactComponent (line 124) | reactComponent(name: string, factory: angular.IComponentOptions): Buil...
    method stateComponent (line 134) | stateComponent(config: IStateComponentConfig, app: App, store: Store):...
    method modules (line 230) | modules(modules: string[]) {
    method menuItem (line 234) | menuItem(item: IMenuItem) {
    method config (line 239) | config(config: Config) {
    method getUser (line 244) | getUser() {
    method build (line 251) | build(): App<Config> {

FILE: quix-frontend/client/src/lib/app/services/navigator.ts
  constant EVENT_MAP (line 6) | const EVENT_MAP = {
  type TEventType (line 12) | type TEventType = 'start' | 'success' | 'visible';
  type INavigatorCallback (line 14) | type INavigatorCallback = (params: any, stateName: string) => any;
  class Navigator (line 16) | class Navigator extends srv.eventEmitter.EventEmitter {
    method constructor (line 21) | constructor(private readonly options: Options) {
    method init (line 25) | init(user: User, ngApp: IModule) {
    method finishLogin (line 102) | finishLogin(data: any) {
    method getStatePrefix (line 108) | getStatePrefix() {
    method state (line 112) | state(name, options) {
    method go (line 119) | go(
    method getUrl (line 131) | getUrl(state?: string, params?: Object): string {
    method goHome (line 142) | goHome() {
    method listen (line 146) | listen(
    method listenFrom (line 177) | listenFrom(
    method reload (line 208) | reload(state?: string) {

FILE: quix-frontend/client/src/lib/app/services/plugin-builder.ts
  type IComponentFactory (line 9) | type IComponentFactory<Config = any> = (app: App<Config>, store: Store) ...
  type IReactComponentFactory (line 10) | type IReactComponentFactory = () => IReactComponentConfig;
  type IStateComponentFactory (line 11) | type IStateComponentFactory<Config = any> = (app: App<Config>, store: St...
  type IStateFactory (line 13) | type IStateFactory<Config = any> = (app: App<Config>, store: Store) => o...
  type IBranchFactory (line 15) | type IBranchFactory<Config = any> = (app: App<Config>) => IBranch;
  type IPluginComponent (line 17) | interface IPluginComponent<Config = any> {
  type IPluginReactComponent (line 22) | interface IPluginReactComponent {
  type IPluginBranches (line 27) | interface IPluginBranches<Config = any> {
  type IUrlParamListener (line 33) | type IUrlParamListener = Function | {from: Function; to: Function};
  type IScopeListener (line 35) | type IScopeListener = (scope, current: any, previous: any, store: Store)...
  type IScopeListeners (line 36) | interface IScopeListeners extends Record<string, IScopeListener | IScope...
  type IStateComponentConfigBase (line 38) | interface IStateComponentConfigBase {
  type IAngularStateComponentConfig (line 55) | interface IAngularStateComponentConfig extends IStateComponentConfigBase{
  type IReactStateComponentConfig (line 60) | interface IReactStateComponentConfig extends IStateComponentConfigBase{
  type IStateComponentConfig (line 63) | type IStateComponentConfig = IAngularStateComponentConfig | IReactStateC...
  type IReactComponentConfig (line 65) | interface IReactComponentConfig{
  class PluginBuilder (line 74) | class PluginBuilder<Config> {
    method constructor (line 81) | constructor(private readonly id: string, private readonly builder: Bui...
    method state (line 90) | state(options: Object): PluginBuilder<Config> {
    method states (line 100) | states(states?: {[name: string]: IStateFactory}) {
    method reactComponent (line 115) | reactComponent(name: string, factory: IReactComponentFactory): PluginB...
    method reactComponents (line 125) | reactComponents(components?: {[name: string]: IReactComponentFactory}) {
    method component (line 140) | component(name: string, factory: IComponentFactory): PluginBuilder<Con...
    method components (line 150) | components(components?: {[name: string]: IComponentFactory}) {
    method stateComponent (line 164) | stateComponent(factory?: IStateComponentFactory) {
    method stateComponents (line 174) | stateComponents(stateComponents?: {[name: string]: IStateComponentFact...
    method store (line 190) | store(branches?: Record<string, IBranchFactory> , logUrl?: string, ser...
    method modules (line 199) | modules(modules) {
    method menuItem (line 204) | menuItem(item: IMenuItem) {
    method getUser (line 209) | getUser() {
    method getId (line 213) | getId() {
    method ready (line 222) | ready(fn: (app: App) => any) {
    method onPluginReady (line 231) | onPluginReady(fn: (app: App<Config>, store: Store) => any) {

FILE: quix-frontend/client/src/lib/app/services/user.ts
  class Permission (line 3) | class Permission {
    method elevate (line 8) | elevate(password) {
    method deelevate (line 12) | deelevate() {
    method isElevated (line 16) | isElevated() {
    method getPassword (line 20) | getPassword() {
    method renew (line 24) | renew() {
  class User (line 38) | class User {
    method fetch (line 48) | fetch(apiBasePath?: string) {
    method set (line 56) | set({ email, name, avatar, role, id, stats }: Record<string, string>) {
    method getStats (line 68) | getStats() {
    method getEmail (line 72) | getEmail() {
    method getName (line 76) | getName() {
    method getAvatar (line 80) | getAvatar() {
    method getRole (line 84) | getRole() {
    method getId (line 88) | getId() {
    method getPermission (line 92) | getPermission() {
    method isLoggedIn (line 96) | isLoggedIn() {
    method toggleLoggedIn (line 100) | toggleLoggedIn(loggedIn) {

FILE: quix-frontend/client/src/lib/app/types.ts
  type Options (line 1) | interface Options {

FILE: quix-frontend/client/src/lib/app/typings/story-builder.ts
  type StoryBuilder (line 3) | interface StoryBuilder extends PluginBuilder<any> {
  type StoryDefiniton (line 7) | type StoryDefiniton = (sb: StoryBuilder) => any;

FILE: quix-frontend/client/src/lib/app/typings/window.ts
  type Window (line 5) | interface Window {

FILE: quix-frontend/client/src/lib/code-editor/ace-extensions/language-tools.ts
  function TabstopToken (line 23) | function TabstopToken(str, _, stack) {
  function escape (line 29) | function escape(ch) {
  function gotoNext (line 249) | function gotoNext(ch) {
  function copyValue (line 304) | function copyValue(val) {
  function wrapRegexp (line 483) | function wrapRegexp(src) {
  function guardedRegexp (line 489) | function guardedRegexp(re, guard, opening) {
  function addSnippet (line 504) | function addSnippet(s) {
  function removeSnippet (line 549) | function removeSnippet(s) {
  function getWordIndex (line 1822) | function getWordIndex(doc, pos) {
  function wordDistance (line 1826) | function wordDistance(doc, pos, _) {

FILE: quix-frontend/client/src/lib/code-editor/directives/code-editor.ts
  function initEditor (line 15) | function initEditor(scope, element, container, text) {
  function exportParams (line 36) | function exportParams(editor: CodeEditor) {
  function importParams (line 46) | function importParams(editor: CodeEditor, urlImports) {
  function render (line 61) | function render(scope, element, text, editor: CodeEditor, urlImports): C...
  method pre (line 94) | pre (scope: IScope & {model: string}, element, attrs, ngModel) {

FILE: quix-frontend/client/src/lib/code-editor/init.ts
  function toDirectiveName (line 4) | function toDirectiveName(name: string) {
  function init (line 8) | function init(ngApp: angular.IModule) {

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-annotator.ts
  class CodeEditorAnnotator (line 1) | class CodeEditorAnnotator {
    method constructor (line 2) | constructor (private readonly ace) {
    method showError (line 6) | showError(row: number, message: string) {
    method hideAll (line 15) | hideAll() {

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-completer.ts
  type ICompleterFn (line 4) | type ICompleterFn = (prefix: string, session?: IEditSession) => ng.IProm...
  type ICompleterItem (line 8) | interface ICompleterItem {
  type IAceCompleter (line 16) | interface IAceCompleter {
  function createCompleter (line 24) | function createCompleter(fn: ICompleterFn, prefixRegex: RegExp,
  function createLiveCompleter (line 46) | function createLiveCompleter(prefix: string, fn: ICompleterFn) {
  class CodeEditorCompleter (line 53) | class CodeEditorCompleter {
    method constructor (line 56) | constructor(ace: Editor) {
    method addLiveCompleter (line 70) | addLiveCompleter(prefix: string, fn: ICompleterFn) {
    method addOnDemandCompleter (line 74) | addOnDemandCompleter(identifierRegex: RegExp, fn: ICompleterFn, option...

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-instance.ts
  class CodeEditorInstance (line 10) | class CodeEditorInstance extends srv.eventEmitter.EventEmitter {
    method constructor (line 11) | constructor(private readonly editor: CodeEditor, scope) {
    method setValid (line 19) | setValid(valid: boolean): CodeEditorInstance {
    method addLiveCompleter (line 25) | addLiveCompleter(prefix: string, fn: ICompleterFn): CodeEditorInstance {
    method addOnDemandCompleter (line 31) | addOnDemandCompleter(identifierRegex: RegExp, fn: ICompleterFn, option...
    method setLiveAutocompletion (line 36) | setLiveAutocompletion(value: boolean) {
    method addShortcut (line 42) | addShortcut(winShortcut: string, macShortcut: string, fn: Function, sc...
    method getAnnotator (line 48) | getAnnotator(): Annotator {
    method getSelection (line 52) | getSelection(): Selection {
    method getParams (line 56) | getParams(): Params {
    method getLockedRange (line 60) | getLockedRange() {
    method resize (line 64) | resize(): CodeEditorInstance {
    method focus (line 70) | focus(): CodeEditorInstance {
    method getValue (line 76) | getValue() {

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-params.ts
  class CodeEditorParams (line 9) | class CodeEditorParams {
    method constructor (line 17) | constructor(private readonly editor: CodeEditor, private readonly ace,...
    method init (line 30) | private init(scope) {
    method replace (line 51) | private replace(text, needle, replacement): string {
    method setLock (line 67) | private setLock(ranges: [number, number][]) {
    method setFold (line 75) | private setFold(ranges: [number, number][]) {
    method getParser (line 91) | getParser(): ParamParser {
    method getParams (line 95) | getParams(): IParam[] {
    method hasParams (line 99) | hasParams(): boolean {
    method addParam (line 103) | addParam(key: string, type: TType, value, options?: string[]): CodeEdi...
    method addAutoParam (line 112) | addAutoParam(key: string): CodeEditorParams {
    method removeParam (line 118) | removeParam(key: string): CodeEditorParams {
    method removeAllParams (line 125) | removeAllParams(): CodeEditorParams {
    method getParamOverrides (line 132) | getParamOverrides(key: string) {
    method overrideParam (line 136) | overrideParam(key: string, param: Partial<IParam>): CodeEditorParams {
    method syncParams (line 158) | syncParams() {
    method format (line 172) | format(text?: string): string {
    method formatEmbed (line 179) | formatEmbed(options?): string {

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-selection.ts
  class CodeEditorSelection (line 4) | class CodeEditorSelection extends srv.eventEmitter.EventEmitter {
    method constructor (line 7) | constructor (private readonly ace, scope) {
    method getRange (line 30) | getRange() {
    method clearSelection (line 34) | clearSelection() {
    method getOffset (line 39) | getOffset() {

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-service.ts
  type AceEditorOptions (line 12) | interface AceEditorOptions {
  type CodeEditorOptions (line 21) | interface CodeEditorOptions {
  function getHeight (line 34) | function getHeight(_ace) {
  function setHeight (line 39) | function setHeight(_ace, element) {
  class CodeEditor (line 44) | class CodeEditor extends srv.eventEmitter.EventEmitter {
    method constructor (line 55) | constructor(scope, private readonly element, text, options?: CodeEdito...
    method init (line 69) | private init(options: CodeEditorOptions = {}): CodeEditor {
    method isValid (line 128) | isValid(): boolean {
    method getCompleter (line 132) | getCompleter(): Completer {
    method getAnnotator (line 136) | getAnnotator(): Annotator {
    method getSelection (line 140) | getSelection(): Selection {
    method getShortcuts (line 144) | getShortcuts(): Shortcuts {
    method getParams (line 148) | getParams(): Params {
    method getValue (line 152) | getValue(): string {
    method getLockedRange (line 156) | getLockedRange(): [number, number][] {
    method setReadonly (line 160) | setReadonly(readonly: boolean): CodeEditor {
    method setLiveAutocompletion (line 168) | setLiveAutocompletion(value: boolean) {
    method setValid (line 174) | setValid(valid: boolean): CodeEditor {
    method setValue (line 182) | setValue(value): CodeEditor {
    method lockLines (line 189) | lockLines(range: [number, number][]): CodeEditor {
    method unlockLines (line 195) | unlockLines(): CodeEditor {
    method resize (line 201) | resize(): CodeEditor {
    method focus (line 208) | focus(): CodeEditor {
    method destroy (line 214) | destroy(): CodeEditor {

FILE: quix-frontend/client/src/lib/code-editor/services/code-editor-shortcuts.ts
  class CodeEditorShortcuts (line 3) | class CodeEditorShortcuts {
    method constructor (line 4) | constructor (private readonly ace) {
    method addShortcut (line 8) | addShortcut(winShortcut: string, macShortcut: string, fn, scope) {

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/param-renderers/index.ts
  function compile (line 11) | function compile(scope, param, html, overrides: Partial<IParam> = {}) {
  function getHtml (line 23) | function getHtml(param: IParam, options: {dateFormat?: string} = {}) {
  function renderParam (line 46) | function renderParam(scope, param: IParam, options, overrides?: Partial<...

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/param-serializers/default-param-serializer.ts
  constant EMBED_PREFIX (line 4) | const EMBED_PREFIX = 'AUTOGENERATED';
  constant EMBED_SUFFIX (line 5) | const EMBED_SUFFIX = 'AUTOGENERATED END';
  class DefaultParamSerializer (line 7) | class DefaultParamSerializer extends ParamSerializer {
    method parse (line 8) | public *parse(text: string): Iterable<string[]> {
    method stringify (line 18) | public stringify(param: any[]): string {
    method convert (line 29) | public convert([match, key, type, options, value, keyOnlyParamMatch, k...
    method unconvert (line 36) | public unconvert(param: any[]): string[] {
    method transform (line 40) | public transform(param: ITokenizedParam): ITokenizedParam {
    method untransform (line 44) | public untransform(param: ITokenizedParam): ITokenizedParam {
    method tokenize (line 48) | public tokenize([match, key, type, options, value, keyOnlyParamMatch, ...
    method detokenize (line 65) | public detokenize({key, type, value, isAutoParam, isKeyOnlyParam, opti...
    method embed (line 92) | public embed(text: string, params: IParam[]): string {
    method extract (line 98) | public extract(text: string): string {
    method getLockRange (line 104) | public getLockRange(text: string): [number, number][] {
    method toJs (line 108) | public toJs(value: string, type: TType = 'string'): any {
    method toString (line 128) | public toString(value: any, type: TType = 'string'): any {

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/param-serializers/index.ts
  function paramSerializerFactory (line 6) | function paramSerializerFactory(type) {

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/param-serializers/param-serializer.ts
  type ITokenizedParam (line 3) | interface ITokenizedParam {
  method serialize (line 54) | public serialize(param: ITokenizedParam, serializationType: 'serialize' ...
  method params (line 61) | public params(text: string): Iterable<ITokenizedParam> {
  method removeEmbed (line 68) | public removeEmbed(text: string): string {

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/param-serializers/python-param-serializer.ts
  constant EMBED_PREFIX (line 5) | const EMBED_PREFIX = '# AUTOGENERATED {';
  constant EMBED_SUFFIX (line 6) | const EMBED_SUFFIX = '# AUTOGENERATED END }';
  constant CUSTOM_FN_DEF (line 7) | const CUSTOM_FN_DEF = 'def __custom__():';
  constant CUSTOM_FN_CALL (line 8) | const CUSTOM_FN_CALL = '__custom__()';
  constant INIT_FN_DEF (line 9) | const INIT_FN_DEF = 'def __init__(c):';
  constant INIT_FN_CALL (line 10) | const INIT_FN_CALL = '__init__(False)';
  constant CUSTOM_REGEX (line 11) | const CUSTOM_REGEX = `(${CUSTOM_FN_DEF.replace(/(\(|\))/g, '\\$1')})([\\...
  constant EMBED_REGEX (line 12) | const EMBED_REGEX = `^${EMBED_PREFIX}[\\s\\S]+${EMBED_SUFFIX}\\n`;
  constant PARAM_REGEX (line 13) | const PARAM_REGEX = `\\((?:"([a-zA-Z0-9_]+)","([a-z]+)",(.+?),(\\[.*?\\]...
  constant PARAMS_VAR (line 14) | const PARAMS_VAR = 'p';
  constant PYTHON_TO_JS (line 16) | const PYTHON_TO_JS = {
  constant PYTHON_TO_JS_BY_TYPE (line 22) | const PYTHON_TO_JS_BY_TYPE = {
  constant JS_TO_PYTHON (line 29) | const JS_TO_PYTHON = {
  constant JS_TO_PYTHON_BY_TYPE (line 35) | const JS_TO_PYTHON_BY_TYPE = {
  function transform (line 42) | function transform(value, transformations) {
  function getSerializedParamsText (line 46) | function getSerializedParamsText(serializedParams: string[]) {
  function getEmbedText (line 50) | function getEmbedText(params: IParam[], serializedParams: any[]): string {
  class PythonParamSerializer (line 68) | class PythonParamSerializer extends ParamSerializer {
    method parse (line 69) | public *parse(text: string): Iterable<string[]> {
    method stringify (line 79) | public stringify(param: any[]): string {
    method convert (line 83) | public convert([match, key, type, value, options, autoParamMatch, auto...
    method unconvert (line 90) | public unconvert(param: any[], type: TType): string[] {
    method tokenize (line 94) | public tokenize([match, key, type, value, options, autoParamMatch, aut...
    method detokenize (line 107) | public detokenize({key, type, value, isAutoParam, options}: ITokenized...
    method transform (line 127) | public transform(param: ITokenizedParam): ITokenizedParam {
    method untransform (line 131) | public untransform(param: ITokenizedParam): ITokenizedParam {
    method embed (line 135) | public embed(text: string, params: IParam[]): string {
    method extract (line 146) | public extract(text: string, options = {runCustom: false}): string {
    method getLockRange (line 163) | public getLockRange(text: string): [number, number][] {
    method toJs (line 181) | public toJs(value: string, type: TType): any {
    method toString (line 191) | public toString(value: any, type: TType = 'string'): string {

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/param-types.ts
  constant DATE_FORMAT (line 4) | const DATE_FORMAT = BiDate.DATE_FORMAT.replace(/\//g, '-');
  type TType (line 6) | type TType = 'string' | 'number' | 'boolean' | 'option' | 'list' | 'date...
  constant TYPES (line 7) | const TYPES: TType[] = ['string', 'number', 'boolean', 'option', 'list',...
  type TUserSelectableTypes (line 8) | type TUserSelectableTypes = TPredefindListsTypes | TType;
  constant TYPE_DEFAULTS (line 10) | const TYPE_DEFAULTS = {
  constant AUTO_PARAMS (line 20) | const AUTO_PARAMS = [
  constant AUTO_PARAM_TYPES (line 25) | const AUTO_PARAM_TYPES = {
  constant AUTO_PARAM_DEFAULTS (line 30) | const AUTO_PARAM_DEFAULTS = {
  method START_TIME (line 31) | get START_TIME() {
  method STOP_TIME (line 35) | get STOP_TIME() {
  type IParam (line 40) | interface IParam {

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/params-parser.ts
  type IParamTransformer (line 8) | type IParamTransformer = (param: ITokenizedParam) => string;
  type IParamReplacer (line 10) | type IParamReplacer = (text: string, oldParam: string, newParam: string)...
  function defaultReplacer (line 12) | function defaultReplacer(text: string, oldParam: string, newParam: strin...
  class ParamParser (line 19) | class ParamParser {
    method constructor (line 20) | constructor(private readonly serializer: ParamSerializer) {
    method each (line 31) | public *each(text: string, all: boolean = false): Iterable<ITokenizedP...
    method all (line 48) | private all(text: string): Iterable<ITokenizedParam> {
    method replace (line 55) | private replace(text: string, transformer: IParamTransformer, replacer...
    method paramsByKey (line 62) | private paramsByKey(params: IParam[]): {[key: string]: IParam} {
    method getSerializer (line 73) | public getSerializer(): ParamSerializer {
    method isSynced (line 80) | public isSynced(params: IParam[], text: string): boolean {
    method embed (line 97) | public embed(text, params: IParam[], replacer: IParamReplacer = defaul...
    method params (line 110) | public params(text: string, {customParamsEnabled} = {customParamsEnabl...
    method sync (line 128) | public sync(text: string, params: IParam[], {customParamsEnabled} = {c...
    method format (line 146) | public format(text: string, params: IParam[], options = {customParamsE...
    method createParam (line 163) | public createParam(key: string, type: TUserSelectableTypes = 'string',...

FILE: quix-frontend/client/src/lib/code-editor/services/param-parser/params-predefined-types.ts
  constant PREDEFINED_LISTS_DATA (line 1) | const PREDEFINED_LISTS_DATA = {
  constant PREDEFINED_LISTS (line 34) | const PREDEFINED_LISTS: TPredefindListsTypes[] = [];
  type TPredefindListsTypes (line 35) | type TPredefindListsTypes = keyof typeof PREDEFINED_LISTS_DATA;

FILE: quix-frontend/client/src/lib/core/ang/drv/bi-options.drv.ts
  function biOptions (line 6) | function biOptions() {

FILE: quix-frontend/client/src/lib/core/ang/drv/bi-validator.drv.ts
  method link (line 13) | link(scope: ng.IScope, element, attrs, ngCtrl) {

FILE: quix-frontend/client/src/lib/core/ang/srv/ng-model/ng-model-test.drv.ts
  function ngModelTest (line 5) | function ngModelTest() {

FILE: quix-frontend/client/src/lib/core/ang/srv/ng-model/ng-model.test.ts
  function createModel (line 8) | function createModel(params) {
  method parser (line 185) | parser(model) {
  method formatter (line 199) | formatter(model) {
  class DemoClass (line 286) | class DemoClass {
    method constructor (line 288) | constructor(data) {
    method foobar (line 292) | foobar() {

FILE: quix-frontend/client/src/lib/core/ang/srv/ng-model/ng-model.ts
  type OptionalCloneable (line 11) | interface OptionalCloneable<T> {
  type IScope (line 15) | interface IScope<T> extends angular.IScope {
  method createItem (line 20) | createItem(item: any = {}) {
  method defaultsDeep (line 30) | defaultsDeep(data, defaults) {
  class ModelConf (line 52) | class ModelConf {
    method fromTemplate (line 68) | fromTemplate(template): ModelConf {
    method formatWith (line 73) | formatWith(formatter: (model) => any): ModelConf {
    method parseWith (line 78) | parseWith(parser: (model) => any): ModelConf {
    method validateWith (line 83) | validateWith(validator: () => Object): ModelConf {
    method validateAsyncWith (line 88) | validateAsyncWith(validator: () => Object): ModelConf {
    method renderWith (line 93) | renderWith(renderer: (model) => void): ModelConf {
    method watchWith (line 98) | watchWith(watcher: (model, prevModel) => void): ModelConf {
    method watchDeep (line 103) | watchDeep(val: boolean): ModelConf {
    method feedBack (line 108) | feedBack(val: boolean): ModelConf {
    method log (line 113) | log(): ModelConf {
    method then (line 118) | then(doThen: Function): ModelConf {
  class Model (line 124) | class Model<T extends OptionalCloneable<T>> {
    method constructor (line 127) | constructor(private readonly scope: IScope<T>, private readonly ngMode...
    method initFormat (line 140) | private initFormat() {
    method initRender (line 160) | private initRender(then) {
    method initWatch (line 179) | private initWatch() {
    method initParse (line 208) | private initParse() {
    method initValidate (line 226) | private initValidate() {
  function create (line 241) | function create<T>(scope: IScope<T>, ngModel: angular.INgModelController...

FILE: quix-frontend/client/src/lib/core/ang/srv/scope/scope.test.ts
  function updateURL (line 349) | function updateURL(url) {

FILE: quix-frontend/client/src/lib/core/ang/srv/scope/scope.ts
  class ScopeHelper (line 7) | class ScopeHelper {
    method constructor (line 10) | constructor(private readonly scope, private readonly controllers = {ng...
    method readonly (line 15) | readonly(readonly) {
    method withEvents (line 21) | withEvents(events = {}) {
    method withEditableEvents (line 27) | withEditableEvents(events = {}) {
    method withPermissionEvents (line 35) | withPermissionEvents<T extends {[eventName: string]: Function}>(events...
    method withActions (line 49) | withActions(actions = {}) {
    method withEditableActions (line 55) | withEditableActions(actions = {}) {
    method withVM (line 63) | withVM(vm, params = {}) {
    method withErrors (line 108) | withErrors(messages: any[]) {
    method withOptions (line 116) | withOptions(options, defaults, watch?: any) {
    method withState (line 132) | withState(state: StateWrapper | string, clientName, options: StateWrap...
    method thenIfNotReadonly (line 161) | thenIfNotReadonly(fn) {
  function init (line 170) | function init(scope, {ngModel = null, errors = null} = {}) {

FILE: quix-frontend/client/src/lib/core/config/index.ts
  class Config (line 1) | class Config<T> {
    method get (line 4) | get() {
    method set (line 8) | set(options: Partial<T>) {

FILE: quix-frontend/client/src/lib/core/index.ts
  type IScope (line 30) | type IScope<T> = IScope_<T>;

FILE: quix-frontend/client/src/lib/core/main.angular.ts
  method setPrefix (line 12) | setPrefix(name) {
  method $get (line 15) | $get() {

FILE: quix-frontend/client/src/lib/core/srv/collections/buffered-collection.test.ts
  function createCollection (line 16) | function createCollection(chunkSize?) {

FILE: quix-frontend/client/src/lib/core/srv/collections/buffered-collection.ts
  class BufferedCollection (line 8) | class BufferedCollection<T extends IBaseModel = any>  extends Partitione...
    method constructor (line 14) | constructor(Mdl?: ModelCtor<T>) {
    method _getAction (line 19) | _getAction() {
    method _startRequestHook (line 28) | _startRequestHook(deferred) {
    method _finishRequestHook (line 32) | _finishRequestHook(models) {
    method _getNextChunk (line 38) | _getNextChunk() {
    method _resolveNextChunk (line 44) | _resolveNextChunk() {
    method _isNextChunkReady (line 48) | _isNextChunkReady() {
    method _isRequestPending (line 52) | _isRequestPending() {
    method buffer (line 58) | get buffer() {
    method isSealed (line 63) | isSealed() {
    method hasMore (line 67) | hasMore() {
    method bufferSize (line 71) | bufferSize() {
    method fetch (line 75) | fetch() {
    method more (line 84) | more() {
    method feed (line 98) | feed(models: T | Model<T> | T[] | Model<T>[]) {
    method seal (line 108) | seal() {
    method rewind (line 115) | rewind() {
    method flush (line 120) | flush() {

FILE: quix-frontend/client/src/lib/core/srv/collections/collection.test.ts
  function createModelClass (line 19) | function createModelClass() {
  function createCollection (line 45) | function createCollection(Model?, action?) {
  function toDataArray (line 49) | function toDataArray(collection) {

FILE: quix-frontend/client/src/lib/core/srv/collections/collection.ts
  type ModelCtor (line 5) | type ModelCtor<T> = new (...args: any[]) => Model<T>;
  class Collection (line 6) | class Collection<T extends IBaseModel = any> {
    method constructor (line 16) | constructor(Mdl?: ModelCtor<T>, action = 'query') {
    method _startRequestHook (line 24) | _startRequestHook(deferred) {
    method _finishRequestHook (line 28) | _finishRequestHook(models) {
    method _getAction (line 32) | _getAction() {
    method _fetch (line 43) | _fetch(params) {
    method _startRequest (line 48) | _startRequest(params) {
    method _finishRequest (line 58) | _finishRequest(promise) {
    method _setModels (line 64) | _setModels(models: T | Model<T> | Model<T>[] | T[]) {
    method _resolveAsSelf (line 69) | _resolveAsSelf(promise) {
    method models (line 75) | get models() {
    method promise (line 79) | get promise() {
    method resolved (line 83) | get resolved() {
    method setResource (line 88) | setResource(resource) {
    method size (line 93) | size() {
    method fetch (line 97) | fetch(params?) {
    method add (line 101) | add(model: T | Model<T> | Model<T>[] | T[]) {
    method remove (line 115) | remove(model) {
    method get (line 119) | get(id) {
    method has (line 123) | has(id) {
    method filter (line 127) | filter(what, value) {
    method format (line 131) | format() {

FILE: quix-frontend/client/src/lib/core/srv/collections/partitioned-collection.test.ts
  function createModelClass (line 19) | function createModelClass() {
  function createCollection (line 45) | function createCollection(chunkSize?) {
  function toDataArray (line 52) | function toDataArray(collection) {

FILE: quix-frontend/client/src/lib/core/srv/collections/partitioned-collection.ts
  class PartitionedCollection (line 7) | class PartitionedCollection<T extends IBaseModel = any> extends Collecti...
    method constructor (line 19) | constructor(Model?: ModelCtor<T>, action = 'partitionedQuery') {
    method _getParams (line 26) | _getParams() {
    method _startRequestHook (line 35) | _startRequestHook(deferred) {
    method _finishRequestHook (line 39) | _finishRequestHook(models) {
    method _more (line 53) | _more(params?) {
    method setChunkSize (line 59) | setChunkSize(chunkSize) {
    method getChunkSize (line 64) | getChunkSize() {
    method fetch (line 68) | fetch(optionalParams?) {
    method more (line 75) | more() {
    method hasMore (line 83) | hasMore() {
    method transformRequestParams (line 87) | transformRequestParams(transformer) {
    method onRequestStart (line 92) | onRequestStart(handler: (x) => any) {
    method onRequestFinish (line 97) | onRequestFinish(handler: (x) => any) {

FILE: quix-frontend/client/src/lib/core/srv/event-emitter/event-emitter.test.ts
  class ChildEventEmitter (line 16) | class ChildEventEmitter extends EventEmitter {
    method constructor (line 17) | constructor(private scope?) {
    method getScope (line 21) | getScope(): angular.IScope {
  function createEventEmitter (line 26) | function createEventEmitter({withScope} = {withScope: false}): ChildEven...

FILE: quix-frontend/client/src/lib/core/srv/event-emitter/event-emitter.ts
  function cloneArray (line 10) | function cloneArray(arr: any[]) {
  method clear (line 17) | clear() {
  method init (line 21) | init(id) {
  method get (line 25) | get(id) {
  method destroy (line 29) | destroy(id) {
  class State (line 35) | class State {
    method getEvent (line 38) | private getEvent(eventName: string) {
    method addHandler (line 45) | addHandler(eventName: string, handler: (...args) => any) {
    method removeHandler (line 53) | removeHandler(eventName: string, handler: (...args) => any) {
    method setArgs (line 57) | setArgs(eventName, ...args) {
    method setArgsKeepHistory (line 65) | setArgsKeepHistory(eventName, ...args) {
  class EventEmitter (line 80) | class EventEmitter {
    method constructor (line 87) | constructor(scope?: angular.IScope) {
    method $state (line 98) | private $state() {
    method fire (line 105) | protected fire(eventName: string, ...args): EventEmitter {
    method stream (line 116) | protected stream(eventName: string, ...args): EventEmitter {
    method on (line 130) | public on(eventName: string, handler: (...args) => any, invoke: boolea...
    method onOnce (line 152) | onOnce(eventName: string, handler: (...args) => any, invoke: boolean =...
    method trigger (line 170) | public trigger(eventName: string, ...args): EventEmitter {
    method triggerStream (line 179) | public triggerStream(eventName: string, ...args): EventEmitter {
    method setScope (line 188) | public setScope(scope: angular.IScope): EventEmitter {

FILE: quix-frontend/client/src/lib/core/srv/injector/index.ts
  function use (line 6) | function use(realInjector): void {
  function get (line 11) | function get(dependencyName: string): any {
  function on (line 15) | function on(event: string, callback: (...args: any[]) => any) {

FILE: quix-frontend/client/src/lib/core/srv/local-storage/local-storage.test.ts
  method setItem (line 42) | setItem(name, _data) {
  method getItem (line 45) | getItem(name) {
  method clear (line 48) | clear() {

FILE: quix-frontend/client/src/lib/core/srv/local-storage/local-storage.ts
  class LocalStorage (line 3) | class LocalStorage {
    method constructor (line 7) | constructor(storage?: Storage) {
    method setPrefix (line 11) | static setPrefix(prefix: string) {
    method setStorage (line 15) | setStorage(storage: Storage) {
    method setItem (line 19) | setItem(name: string, data: string) {
    method getItem (line 24) | getItem(name: string) {
    method clear (line 29) | clear() {

FILE: quix-frontend/client/src/lib/core/srv/model/model.test.ts
  function createModel (line 44) | function createModel(data?, template?, options?, responseHook?) {

FILE: quix-frontend/client/src/lib/core/srv/model/model.ts
  function flatten (line 7) | function flatten(data, keys = [], res = {}) {
  function unflatten (line 23) | function unflatten(data, keys = []) {
  function unflattenKey (line 33) | function unflattenKey(keys, value, res = {}) {
  type IBaseModel (line 44) | interface IBaseModel {
  class Model (line 50) | class Model<T extends IBaseModel = any> {
    method constructor (line 63) | constructor(model?, template?, options = {autoId: false, autoOwner: nu...
    method _responseHook (line 85) | _responseHook(data, action, options) {
    method _assignId (line 89) | _assignId() {
    method _doRequest (line 95) | _doRequest(action, data) {
    method _processResponse (line 100) | _processResponse(promise, action) {
    method _action (line 131) | _action(action, data?) {
    method _initPromise (line 142) | _initPromise(promise) {
    method _assignAutoOwner (line 151) | _assignAutoOwner() {
    method _stripDollars (line 156) | _stripDollars(data: any) {
    method _parseCollection (line 170) | _parseCollection(collectionString, data) {
    method _parseModel (line 183) | _parseModel(modelString, data) {
    method _smartMerge (line 198) | _smartMerge(current, source) {
    method _parse (line 228) | _parse(data, defaults) {
    method _format (line 266) | _format(data, filter) {
    method id (line 305) | get id() {
    method id (line 309) | set id(value) {
    method data (line 313) | get data() {
    method data (line 317) | set data(data) {
    method promise (line 321) | get promise() {
    method resolved (line 325) | get resolved() {
    method permission (line 329) | get permission() {
    method isNew (line 334) | isNew() {
    method isValid (line 338) | isValid() {
    method setPermission (line 342) | setPermission(Permission) {
    method setValidity (line 347) | setValidity(valid) {
    method format (line 351) | format() {
    method parse (line 355) | parse(data) {
    method fetch (line 359) | fetch(id, ...rest) {
    method clone (line 370) | clone(fetch = false, params?) {
    method save (line 390) | save() {
    method destroy (line 400) | destroy() {
    method meta (line 408) | meta(key, value?, once = false) {

FILE: quix-frontend/client/src/lib/core/srv/socket/socket.ts
  function createSocket (line 4) | function createSocket(self: Socket, url: string): any {
  class Socket (line 24) | class Socket extends EventEmitter {
    method constructor (line 27) | constructor (private readonly url: string) {
    method send (line 33) | send(payload): Socket {
    method close (line 38) | close(): Socket {
    method getUrl (line 43) | getUrl() {
    method getWebSocket (line 47) | getWebSocket() {

FILE: quix-frontend/client/src/lib/core/srv/state/localstorage-state-provider.ts
  method getStateData (line 8) | getStateData(stateName: string): string {
  method setStateData (line 12) | setStateData(stateName: string, data: string): void {

FILE: quix-frontend/client/src/lib/core/srv/state/state-wrapper.test.ts
  type Dictionary (line 4) | type Dictionary<T> = _.Dictionary<T>;
  function createDefaultExportImport (line 6) | function createDefaultExportImport(obj, paramList: string[]) {
  function updateURL (line 43) | function updateURL(url) {

FILE: quix-frontend/client/src/lib/core/srv/state/state-wrapper.ts
  type traverseFunction (line 25) | type traverseFunction = (obj: any, callback: (obj: any, args: any[]) => ...
  function defaultTraverse (line 26) | function defaultTraverse(obj: any, callback, args: any[] = [], deep = tr...
  function createLoadFunction (line 37) | function createLoadFunction(obj: any, deep = true, oneTimeLoad = false, ...
  function createSaveFunction (line 56) | function createSaveFunction(obj: Object, deep = true, customTraverse?): ...
  type StateWrapperOptions (line 72) | interface StateWrapperOptions {
  class StateWrapperBuilder (line 79) | class StateWrapperBuilder {
    method useObject (line 93) | useObject(object) {
    method setClientName (line 98) | setClientName(name) {
    method withOptions (line 103) | withOptions(options: StateWrapperOptions) {
    method withState (line 108) | withState(state: StateWrapper) {
    method withNewState (line 113) | withNewState(name: string) {
    method withProviders (line 118) | withProviders(providers: string[]) {
    method withCustomTraverse (line 123) | withCustomTraverse(traverseFunc: traverseFunction) {
    method verifyMandatoryParametrs (line 128) | private verifyMandatoryParametrs() {
    method end (line 140) | public end() {
  class StateWrapper (line 176) | class StateWrapper {
    method build (line 179) | static build() {
    method constructor (line 183) | constructor(private readonly state: State, private readonly clientName...
    method getBaseState (line 191) | getBaseState() {
    method _load (line 195) | private _load(clientList: string[] = []) {
    method load (line 204) | load(...clientList) {
    method loadAll (line 211) | loadAll() {
    method _save (line 215) | private _save(clientList: string[] = []) {
    method save (line 224) | save(...clientList) {
    method saveAll (line 231) | saveAll() {
    method unregister (line 235) | unregister() {

FILE: quix-frontend/client/src/lib/core/srv/state/state.ts
  type Dictionary (line 2) | type Dictionary<T> = Record<string, T>;
  class State (line 5) | class State {
    method constructor (line 11) | constructor (private readonly name: string, private doLoad: boolean | ...
    method getName (line 19) | getName() {
    method getClientByName (line 23) | getClientByName(name: string) {
    method register (line 32) | register (client: IStateClient): State {
    method unregister (line 43) | unregister(name: string): State {
    method _export (line 57) | private _export (providerName: string, clientList: string[]) {
    method exportAsJSON (line 73) | exportAsJSON (providerName?: string, ...clientList: string[]) {
    method exportAsURL (line 78) | exportAsURL (providerName?: string, ...clientList: string[]) {
    method _import (line 89) | private _import (data: Object, clientList: string[]) {
    method importFromJSON (line 104) | importFromJSON(stringData: string, ...clientList: string[]) {
    method importFromURL (line 114) | importFromURL(stringData: string, ...clientList: string[]) {

FILE: quix-frontend/client/src/lib/core/srv/state/types.ts
  type IStateClient (line 1) | interface IStateClient {
  type IStateProvider (line 7) | interface IStateProvider {

FILE: quix-frontend/client/src/lib/core/srv/state/url-params.test.ts
  function updateURL (line 9) | function updateURL(url) {

FILE: quix-frontend/client/src/lib/core/srv/state/url-params.ts
  function processParam (line 6) | function processParam(moduleName: string, paramName: string, paramValue:...
  type decodeFunc (line 17) | type decodeFunc = (input: {}) => any;
  type encodeFunc (line 18) | type encodeFunc = () => {[key: string]: string | boolean};
  type ModuleCallbacks (line 20) | interface ModuleCallbacks {
  class UrlParams (line 25) | class UrlParams {
    method constructor (line 29) | constructor() {
    method register (line 33) | register(moduleName: string, decode: decodeFunc, encode: encodeFunc) {
    method generateURL (line 55) | public generateURL(moduleList: Array<string> = null) {
    method decode (line 69) | public decode(moduleList: Array<string> = null) {
    method _sperateParamsByModule (line 79) | private _sperateParamsByModule() {

FILE: quix-frontend/client/src/lib/core/srv/state/url-state-provider.test.ts
  function updateURL (line 9) | function updateURL(url) {

FILE: quix-frontend/client/src/lib/core/srv/state/url-state-provider.ts
  method constructor (line 7) | constructor() {
  method getStateData (line 13) | getStateData(stateName: string): string {
  method setStateData (line 19) | setStateData(stateName: string, data: string): void {

FILE: quix-frontend/client/src/lib/core/srv/view-model/view-model.ts
  function createVM (line 10) | function createVM(template, root) {
  class ItemsViewModel (line 32) | class ItemsViewModel {
    method constructor (line 36) | constructor(private readonly vm?) { }
    method get (line 38) | get(item: Object): ViewModel {
    method all (line 48) | all(): ViewModel[] {
    method delete (line 52) | delete(item: Object): ItemsViewModel {
    method deleteAll (line 58) | deleteAll(): ItemsViewModel {
    method identifyBy (line 63) | identifyBy(identifier: (item: Object) => number): ItemsViewModel {
    method forEach (line 69) | forEach(fn) {
  class ViewModel (line 81) | class ViewModel {
    method constructor (line 85) | constructor(vm: Object = null, protected $root = null) {
    method init (line 100) | init(params?) {
    method isHead (line 112) | isHead() {
    method toggle (line 119) | toggle(enabled) {
    method toggleEnabled (line 131) | toggleEnabled(enabled) {
    method toggleVisible (line 144) | toggleVisible(visible) {
    method reload (line 154) | reload() {
    method createItemsVm (line 163) | createItemsVm(vm?) {
    method forEach (line 167) | forEach(fn) {
  function create (line 191) | function create(vm: Object = null, root?): ViewModel {

FILE: quix-frontend/client/src/lib/core/types/angular-promise.d.ts
  type IPromise (line 5) | interface IPromise<T> {

FILE: quix-frontend/client/src/lib/core/utils/index.ts
  function isPromise (line 8) | function isPromise(obj: any): boolean {
  function uuid (line 12) | function uuid() {
  method safeApply (line 17) | safeApply(sc, fn: Function) {
  method safeDigest (line 27) | safeDigest(sc, fn: Function) {
  method onBlur (line 44) | onBlur(element, fn, sc?): Function {
  method onKey (line 79) | onKey(key, fn, s?): Function {
  method escape (line 110) | escape(str) {
  method scrollIntoView (line 114) | scrollIntoView(element, animate = false, offset = 0) {
  function stripDollars (line 123) | function stripDollars<T extends object>(data: T): Partial<T> {
  function copyToClipboard (line 137) | function copyToClipboard(text: string) {

FILE: quix-frontend/client/src/lib/core/utils/lodash4-polyfill.types.ts
  type LoDashStatic (line 2) | interface LoDashStatic {

FILE: quix-frontend/client/src/lib/file-explorer/directives/file-explorer-vm.ts
  method setField (line 6) | setField(field: string, reversed = false) {
  method getPermissions (line 14) | getPermissions(folder) {
  method canDelete (line 18) | canDelete(folder) {
  method canRename (line 21) | canRename(folder) {
  method hasMenu (line 24) | hasMenu(folder) {
  method toggleOpen (line 27) | toggleOpen(folder, value) {
  method toggleEdit (line 30) | toggleEdit(folder, value) {
  method isOpen (line 33) | isOpen(folder) {
  method setCurrent (line 36) | setCurrent(folder: Folder) {
  method getCurrent (line 39) | getCurrent(): Folder {
  method isActive (line 42) | isActive(folder: File): boolean {
  method isEmpty (line 45) | isEmpty(): boolean {
  method $init (line 48) | $init() {
  method setCurrent (line 61) | setCurrent(file: File) {
  method getCurrent (line 64) | getCurrent(): File {
  method isActive (line 67) | isActive(file: File): boolean {
  method $init (line 71) | $init() {

FILE: quix-frontend/client/src/lib/file-explorer/directives/file-explorer.ts
  type Mode (line 16) | type Mode = 'static' | 'dynamic';
  function directive (line 18) | function directive(mode: Mode, params) {
  function initScope (line 28) | function initScope(scope, controller: Controller, depth: number, mode: M...

FILE: quix-frontend/client/src/lib/file-explorer/init.ts
  function toDirectiveName (line 4) | function toDirectiveName(name: string) {
  function init (line 8) | function init(ngApp: angular.IModule) {

FILE: quix-frontend/client/src/lib/file-explorer/services/file-explorer-controller.ts
  type Permissions (line 7) | interface Permissions {
  class Controller (line 12) | class Controller {
    method constructor (line 19) | constructor(private readonly $scope, private readonly $element, privat...
    method render (line 25) | private render(html) {
    method getInstance (line 29) | getInstance(): Instance {
    method getPermissions (line 33) | getPermissions(folder): Permissions {
    method getContainer (line 41) | getContainer() {
    method setCurrentFolder (line 45) | setCurrentFolder(folder: Folder): Controller {
    method setCurrentFile (line 50) | setCurrentFile(file: File): Controller {
    method getCurrentFolder (line 55) | getCurrentFolder(): Folder {
    method getCurrentFile (line 59) | getCurrentFile(): File {
    method fireEvent (line 63) | fireEvent(item: Item, eventName: string, ...args): Controller {
    method syncItem (line 69) | syncItem(item: Item, eventName: string, ...args): Controller {
    method clickFile (line 77) | clickFile(file: File): Controller {
    method clickFolder (line 82) | clickFolder(folder: Folder): Controller {
    method fetchLazyFolder (line 87) | fetchLazyFolder(folder: Folder) {
    method transclude (line 91) | transclude(element, file) {
    method renderFolder (line 98) | renderFolder(scope) {
    method renderFile (line 119) | renderFile(scope) {
    method renderFolderIcon (line 128) | renderFolderIcon(scope, folder: Folder) {
    method renderFileIcon (line 142) | renderFileIcon(scope, file: File) {
    method renderMenu (line 156) | renderMenu(scope, folder: Folder) {

FILE: quix-frontend/client/src/lib/file-explorer/services/file-explorer-instance.ts
  class Instance (line 9) | class Instance extends srv.eventEmitter.EventEmitter {
    method constructor (line 10) | constructor (private readonly scope) {
    method createFolder (line 14) | createFolder() {
    method createFile (line 18) | createFile(type?: string) {
    method setActive (line 22) | setActive(fileDef: IItemDef) {
    method clearActive (line 28) | clearActive() {

FILE: quix-frontend/client/src/lib/file-explorer/services/file-explorer-models.ts
  class Item (line 7) | class Item {
    method constructor (line 11) | constructor(
    method getId (line 20) | public getId(): string {
    method getName (line 24) | public getName(): string {
    method getType (line 28) | public getType(): string {
    method setParent (line 32) | public setParent(parent: Folder): Item {
    method getParent (line 37) | public getParent(): Folder {
    method getDepth (line 41) | public getDepth(): number {
    method getData (line 53) | public getData(): any {
    method getParentById (line 57) | public getParentById(id: string): Item {
    method on (line 72) | public on(name, fn, invoke?, scope?) {
    method trigger (line 76) | public trigger(name, ...args) {
  class File (line 81) | class File extends Item {
    method constructor (line 82) | constructor(id: string, name: string, type: string = 'file', data = {}) {
    method moveTo (line 86) | public moveTo(folder: Folder): File {
  class Folder (line 92) | class Folder extends Item {
    method constructor (line 104) | constructor(id: string, name: string, data = {}) {
    method setPool (line 108) | public setPool(pool: Record<string, Folder | File>): Folder {
    method setFolders (line 114) | public setFolders(folders: Folder[]): Folder {
    method setFiles (line 120) | public setFiles(files: File[]): Folder {
    method setLazy (line 126) | public setLazy(lazy: boolean = false): Folder {
    method isLazy (line 132) | public isLazy(): boolean {
    method getFolderById (line 136) | public getFolderById(id: string): Folder {
    method getFileById (line 140) | public getFileById(id: string): File {
    method getFolders (line 144) | public getFolders(): Folder[] {
    method getFiles (line 148) | public getFiles(): File[] {
    method createFolder (line 152) | public createFolder(name: string): Folder {
    method createFile (line 156) | public createFile(name: string, type?): File {
    method addFolder (line 160) | public addFolder(idOrFolder: string | Folder, name?: string, data = {}...
    method addFile (line 171) | public addFile(idOrFile: string | File, name?: string, type?: string, ...
    method removeFile (line 182) | public removeFile(file: File): File {
    method removeFolder (line 191) | public removeFolder(folder: Folder): Folder {
    method hasFiles (line 200) | public hasFiles(): boolean {
    method hasFolders (line 204) | public hasFolders(): boolean {
    method isEmpty (line 208) | public isEmpty(): boolean {
    method hasFileLeaf (line 212) | public hasFileLeaf(): boolean {
    method isOpen (line 216) | public isOpen(): boolean {
    method toggleOpen (line 220) | public toggleOpen(open?: boolean): Folder {
    method toggleEdit (line 230) | public toggleEdit(edit?: boolean): Folder {
    method toggleHasFileLeaf (line 240) | public toggleHasFileLeaf(hasFileLeaf: boolean): Folder {
    method moveTo (line 245) | public moveTo(folder: Folder): Folder {
    method getLength (line 250) | public getLength(res = 1): number {
    method setLimit (line 254) | public setLimit(limit: number) {
    method getLimit (line 258) | public getLimit() {
    method destroy (line 262) | public destroy() {
    method $clone (line 266) | public $clone(): Folder {

FILE: quix-frontend/client/src/lib/file-explorer/services/file-explorer-tools.ts
  function getId (line 4) | function getId(parent) {
  function goToFile (line 11) | function goToFile(fileDef: IItemDef, folder: Folder): File {
  function addFolder (line 19) | function addFolder(folder: Folder, {id, name, lazy, path, ...data}: IIte...
  function addFile (line 30) | function addFile(folder: Folder, {id, name, type, path, ...data}: IItemD...
  function defToTree (line 37) | function defToTree(items: IItemDef[], options: any): Folder {
  function treeToDef (line 73) | function treeToDef(item: Item, path = [], res: IItemDef[] = []): IItemDe...
  function itemToDef (line 117) | function itemToDef(item: Item): IItemDef {

FILE: quix-frontend/client/src/lib/file-explorer/services/index.ts
  type IPathItemDef (line 1) | interface IPathItemDef {
  type IItemDef (line 6) | interface IItemDef {

FILE: quix-frontend/client/src/lib/language-parsers/presto-grammar/lang/presto/SqlBaseParser.ts
  function MultiStatementContext (line 1500) | function MultiStatementContext(parser, parent, invokingState) {
  function SingleStatementContext (line 1616) | function SingleStatementContext(parser, parent, invokingState) {
  function SingleExpressionContext (line 1689) | function SingleExpressionContext(parser, parent, invokingState) {
  function StatementContext (line 1762) | function StatementContext(parser, parent, invokingState) {
  function ExplainContext (line 1785) | function ExplainContext(parser, ctx) {
  function PrepareContext (line 1839) | function PrepareContext(parser, ctx) {
  function CreateTableContext (line 1886) | function CreateTableContext(parser, ctx) {
  function StartTransactionContext (line 1960) | function StartTransactionContext(parser, ctx) {
  function CreateTableAsSelectContext (line 2010) | function CreateTableAsSelectContext(parser, ctx) {
  function UseContext (line 2097) | function UseContext(parser, ctx) {
  function DeallocateContext (line 2145) | function DeallocateContext(parser, ctx) {
  function RenameTableContext (line 2188) | function RenameTableContext(parser, ctx) {
  function CommitContext (line 2248) | function CommitContext(parser, ctx) {
  function RevokeContext (line 2287) | function RevokeContext(parser, ctx) {
  function ShowPartitionsContext (line 2374) | function ShowPartitionsContext(parser, ctx) {
  function DropViewContext (line 2465) | function DropViewContext(parser, ctx) {
  function DeleteContext (line 2516) | function DeleteContext(parser, ctx) {
  function ShowTablesContext (line 2567) | function ShowTablesContext(parser, ctx) {
  function DescribeInputContext (line 2627) | function DescribeInputContext(parser, ctx) {
  function ShowCatalogsContext (line 2670) | function ShowCatalogsContext(parser, ctx) {
  function StatementDefaultContext (line 2718) | function StatementDefaultContext(parser, ctx) {
  function RenameColumnContext (line 2753) | function RenameColumnContext(parser, ctx) {
  function SetSessionContext (line 2822) | function SetSessionContext(parser, ctx) {
  function CreateViewContext (line 2873) | function CreateViewContext(parser, ctx) {
  function ShowCreateTableContext (line 2932) | function ShowCreateTableContext(parser, ctx) {
  function ShowSchemasContext (line 2979) | function ShowSchemasContext(parser, ctx) {
  function DropTableContext (line 3039) | function DropTableContext(parser, ctx) {
  function ShowColumnsContext (line 3090) | function ShowColumnsContext(parser, ctx) {
  function RollbackContext (line 3149) | function RollbackContext(parser, ctx) {
  function AddColumnContext (line 3188) | function AddColumnContext(parser, ctx) {
  function ResetSessionContext (line 3245) | function ResetSessionContext(parser, ctx) {
  function InsertIntoContext (line 3288) | function InsertIntoContext(parser, ctx) {
  function ShowSessionContext (line 3339) | function ShowSessionContext(parser, ctx) {
  function CreateSchemaContext (line 3378) | function CreateSchemaContext(parser, ctx) {
  function ExecuteContext (line 3441) | function ExecuteContext(parser, ctx) {
  function CallContext (line 3495) | function CallContext(parser, ctx) {
  function RenameSchemaContext (line 3545) | function RenameSchemaContext(parser, ctx) {
  function ShowFunctionsContext (line 3600) | function ShowFunctionsContext(parser, ctx) {
  function DescribeOutputContext (line 3639) | function DescribeOutputContext(parser, ctx) {
  function DropSchemaContext (line 3682) | function DropSchemaContext(parser, ctx) {
  function GrantContext (line 3741) | function GrantContext(parser, ctx) {
  function ShowCreateViewContext (line 3832) | function ShowCreateViewContext(parser, ctx) {
  function QueryContext (line 5095) | function QueryContext(parser, parent, invokingState) {
  function Presto_withContext (line 5175) | function Presto_withContext(parser, parent, invokingState) {
  function TableElementContext (line 5280) | function TableElementContext(parser, parent, invokingState) {
  function ColumnDefinitionContext (line 5459) | function ColumnDefinitionContext(parser, parent, invokingState) {
  function LikeClauseContext (line 5532) | function LikeClauseContext(parser, parent, invokingState) {
  function TablePropertiesContext (line 5637) | function TablePropertiesContext(parser, parent, invokingState) {
  function TablePropertyContext (line 5728) | function TablePropertyContext(parser, parent, invokingState) {
  function QueryNoWithContext (line 5807) | function QueryNoWithContext(parser, parent, invokingState) {
  function QueryTermContext (line 5949) | function QueryTermContext(parser, parent, invokingState) {
  function QueryTermDefaultContext (line 5971) | function QueryTermDefaultContext(parser, ctx) {
  function SetOperationContext (line 6006) | function SetOperationContext(parser, ctx) {
  function QueryPrimaryContext (line 6174) | function QueryPrimaryContext(parser, parent, invokingState) {
  function SubqueryContext (line 6197) | function SubqueryContext(parser, ctx) {
  function QueryPrimaryDefaultContext (line 6232) | function QueryPrimaryDefaultContext(parser, ctx) {
  function TableContext (line 6267) | function TableContext(parser, ctx) {
  function InlineTableContext (line 6306) | function InlineTableContext(parser, ctx) {
  function SortItemContext (line 6427) | function SortItemContext(parser, parent, invokingState) {
  function QuerySpecificationContext (line 6551) | function QuerySpecificationContext(parser, parent, invokingState) {
  function GroupByContext (line 6764) | function GroupByContext(parser, parent, invokingState) {
  function GroupingElementContext (line 6866) | function GroupingElementContext(parser, parent, invokingState) {
  function MultipleGroupingSetsContext (line 6889) | function MultipleGroupingSetsContext(parser, ctx) {
  function SingleGroupingSetContext (line 6939) | function SingleGroupingSetContext(parser, ctx) {
  function CubeContext (line 6974) | function CubeContext(parser, ctx) {
  function RollupContext (line 7020) | function RollupContext(parser, ctx) {
  function GroupingExpressionsContext (line 7306) | function GroupingExpressionsContext(parser, parent, invokingState) {
  function GroupingSetContext (line 7417) | function GroupingSetContext(parser, parent, invokingState) {
  function NamedQueryContext (line 7622) | function NamedQueryContext(parser, parent, invokingState) {
  function SetQuantifierContext (line 7719) | function SetQuantifierContext(parser, parent, invokingState) {
  function SelectItemContext (line 7798) | function SelectItemContext(parser, parent, invokingState) {
  function SelectAllContext (line 7821) | function SelectAllContext(parser, ctx) {
  function SelectSingleContext (line 7860) | function SelectSingleContext(parser, ctx) {
  function RelationContext (line 7972) | function RelationContext(parser, parent, invokingState) {
  function RelationDefaultContext (line 7994) | function RelationDefaultContext(parser, ctx) {
  function JoinRelationContext (line 8029) | function JoinRelationContext(parser, ctx) {
  function JoinTypeContext (line 8192) | function JoinTypeContext(parser, parent, invokingState) {
  function JoinCriteriaContext (line 8330) | function JoinCriteriaContext(parser, parent, invokingState) {
  function SampledRelationContext (line 8450) | function SampledRelationContext(parser, parent, invokingState) {
  function SampleTypeContext (line 8546) | function SampleTypeContext(parser, parent, invokingState) {
  function AliasedRelationContext (line 8629) | function AliasedRelationContext(parser, parent, invokingState) {
  function ColumnAliasesContext (line 8736) | function ColumnAliasesContext(parser, parent, invokingState) {
  function RelationPrimaryContext (line 8827) | function RelationPrimaryContext(parser, parent, invokingState) {
  function SubqueryRelationContext (line 8850) | function SubqueryRelationContext(parser, ctx) {
  function ParenthesizedRelationContext (line 8885) | function ParenthesizedRelationContext(parser, ctx) {
  function UnnestContext (line 8920) | function UnnestContext(parser, ctx) {
  function TableNameContext (line 8974) | function TableNameContext(parser, ctx) {
  function ExpressionContext (line 9101) | function ExpressionContext(parser, parent, invokingState) {
  function BooleanExpressionContext (line 9168) | function BooleanExpressionContext(parser, parent, invokingState) {
  function LogicalNotContext (line 9190) | function LogicalNotContext(parser, ctx) {
  function BooleanDefaultContext (line 9229) | function BooleanDefaultContext(parser, ctx) {
  function LogicalBinaryContext (line 9264) | function LogicalBinaryContext(parser, ctx) {
  function PredicatedContext (line 9534) | function PredicatedContext(parser, parent, invokingState) {
  function PredicateContext (line 9614) | function PredicateContext(parser, parent, invokingState, value) {
  function ComparisonContext (line 9640) | function ComparisonContext(parser, ctx) {
  function LikeContext (line 9680) | function LikeContext(parser, ctx) {
  function InSubqueryContext (line 9736) | function InSubqueryContext(parser, ctx) {
  function DistinctFromContext (line 9779) | function DistinctFromContext(parser, ctx) {
  function InListContext (line 9831) | function InListContext(parser, ctx) {
  function NullPredicateContext (line 9881) | function NullPredicateContext(parser, ctx) {
  function BetweenContext (line 9924) | function BetweenContext(parser, ctx) {
  function QuantifiedComparisonContext (line 9980) | function QuantifiedComparisonContext(parser, ctx) {
  function ValueExpressionContext (line 10215) | function ValueExpressionContext(parser, parent, invokingState) {
  function ValueExpressionDefaultContext (line 10237) | function ValueExpressionDefaultContext(parser, ctx) {
  function ConcatenationContext (line 10272) | function ConcatenationContext(parser, ctx) {
  function ArithmeticBinaryContext (line 10320) | function ArithmeticBinaryContext(parser, ctx) {
  function ArithmeticUnaryContext (line 10385) | function ArithmeticUnaryContext(parser, ctx) {
  function AtTimeZoneContext (line 10429) | function AtTimeZoneContext(parser, ctx) {
  function PrimaryExpressionContext (line 10740) | function PrimaryExpressionContext(parser, parent, invokingState) {
  function DereferenceContext (line 10762) | function DereferenceContext(parser, ctx) {
  function TypeConstructorContext (line 10803) | function TypeConstructorContext(parser, ctx) {
  function SpecialDateTimeFunctionContext (line 10846) | function SpecialDateTimeFunctionContext(parser, ctx) {
  function SubstringContext (line 10903) | function SubstringContext(parser, ctx) {
  function CastContext (line 10957) | function CastContext(parser, ctx) {
  function LambdaContext (line 11008) | function LambdaContext(parser, ctx) {
  function ParameterContext (line 11054) | function ParameterContext(parser, ctx) {
  function NormalizeContext (line 11086) | function NormalizeContext(parser, ctx) {
  function IntervalLiteralContext (line 11129) | function IntervalLiteralContext(parser, ctx) {
  function NumericLiteralContext (line 11164) | function NumericLiteralContext(parser, ctx) {
  function BooleanLiteralContext (line 11199) | function BooleanLiteralContext(parser, ctx) {
  function ImplicitRowConstructorContext (line 11234) | function ImplicitRowConstructorContext(parser, ctx) {
  function SimpleCaseContext (line 11276) | function SimpleCaseContext(parser, ctx) {
  function ColumnReferenceContext (line 11339) | function ColumnReferenceContext(parser, ctx) {
  function NullLiteralContext (line 11374) | function NullLiteralContext(parser, ctx) {
  function RowConstructorContext (line 11409) | function RowConstructorContext(parser, ctx) {
  function SubscriptContext (line 11455) | function SubscriptContext(parser, ctx) {
  function SubqueryExpressionContext (line 11496) | function SubqueryExpressionContext(parser, ctx) {
  function BinaryLiteralContext (line 11531) | function BinaryLiteralContext(parser, ctx) {
  function ExtractContext (line 11566) | function ExtractContext(parser, ctx) {
  function StringLiteralContext (line 11613) | function StringLiteralContext(parser, ctx) {
  function ArrayConstructorContext (line 11648) | function ArrayConstructorContext(parser, ctx) {
  function FunctionCallContext (line 11694) | function FunctionCallContext(parser, ctx) {
  function ExistsContext (line 11756) | function ExistsContext(parser, ctx) {
  function PositionContext (line 11795) | function PositionContext(parser, ctx) {
  function SearchedCaseContext (line 11845) | function SearchedCaseContext(parser, ctx) {
  function TimeZoneSpecifierContext (line 12581) | function TimeZoneSpecifierContext(parser, parent, invokingState) {
  function TimeZoneIntervalContext (line 12604) | function TimeZoneIntervalContext(parser, ctx) {
  function TimeZoneStringContext (line 12647) | function TimeZoneStringContext(parser, ctx) {
  function ComparisonOperatorContext (line 12739) | function ComparisonOperatorContext(parser, parent, invokingState) {
  function ComparisonQuantifierContext (line 12834) | function ComparisonQuantifierContext(parser, parent, invokingState) {
  function BooleanValueContext (line 12917) | function BooleanValueContext(parser, parent, invokingState) {
  function IntervalContext (line 12996) | function IntervalContext(parser, parent, invokingState) {
  function IntervalFieldContext (line 13124) | function IntervalFieldContext(parser, parent, invokingState) {
  function TypeContext (line 13219) | function TypeContext(parser, parent, invokingState) {
  function TypeParameterContext (line 13444) | function TypeParameterContext(parser, parent, invokingState) {
  function BaseTypeContext (line 13626) | function BaseTypeContext(parser, parent, invokingState) {
  function WhenClauseContext (line 13823) | function WhenClauseContext(parser, parent, invokingState) {
  function FilterContext (line 13913) | function FilterContext(parser, parent, invokingState) {
  function OverContext (line 13996) | function OverContext(parser, parent, invokingState) {
  function WindowFrameContext (line 14174) | function WindowFrameContext(parser, parent, invokingState) {
  function FrameBoundContext (line 14313) | function FrameBoundContext(parser, parent, invokingState) {
  function BoundedFrameContext (line 14336) | function BoundedFrameContext(parser, ctx) {
  function UnboundedFrameContext (line 14380) | function UnboundedFrameContext(parser, ctx) {
  function CurrentRowBoundContext (line 14424) | function CurrentRowBoundContext(parser, ctx) {
  function ExplainOptionContext (line 14535) | function ExplainOptionContext(parser, parent, invokingState) {
  function ExplainFormatContext (line 14558) | function ExplainFormatContext(parser, ctx) {
  function ExplainTypeContext (line 14602) | function ExplainTypeContext(parser, ctx) {
  function TransactionModeContext (line 14707) | function TransactionModeContext(parser, parent, invokingState) {
  function TransactionAccessModeContext (line 14730) | function TransactionAccessModeContext(parser, ctx) {
  function IsolationLevelContext (line 14774) | function IsolationLevelContext(parser, ctx) {
  function LevelOfIsolationContext (line 14872) | function LevelOfIsolationContext(parser, parent, invokingState) {
  function ReadUncommittedContext (line 14895) | function ReadUncommittedContext(parser, ctx) {
  function SerializableContext (line 14934) | function SerializableContext(parser, ctx) {
  function ReadCommittedContext (line 14969) | function ReadCommittedContext(parser, ctx) {
  function RepeatableReadContext (line 15008) | function RepeatableReadContext(parser, ctx) {
  function CallArgumentContext (line 15108) | function CallArgumentContext(parser, parent, invokingState) {
  function PositionalArgumentContext (line 15131) | function PositionalArgumentContext(parser, ctx) {
  function NamedArgumentContext (line 15166) | function NamedArgumentContext(parser, ctx) {
  function PrivilegeContext (line 15250) | function PrivilegeContext(parser, parent, invokingState) {
  function QualifiedNameContext (line 15447) | function QualifiedNameContext(parser, parent, invokingState) {
  function IdentifierContext (line 15536) | function IdentifierContext(parser, parent, invokingState) {
  function BackQuotedIdentifierContext (line 15559) | function BackQuotedIdentifierContext(parser, ctx) {
  function QuotedIdentifierAlternativeContext (line 15594) | function QuotedIdentifierAlternativeContext(parser, ctx) {
  function DigitIdentifierContext (line 15629) | function DigitIdentifierContext(parser, ctx) {
  function UnquotedIdentifierContext (line 15664) | function UnquotedIdentifierContext(parser, ctx) {
  function QuotedIdentifierContext (line 15852) | function QuotedIdentifierContext(parser, parent, invokingState) {
  function NumberContext (line 15919) | function NumberContext(parser, parent, invokingState) {
  function DecimalLiteralContext (line 15942) | function DecimalLiteralContext(parser, ctx) {
  function IntegerLiteralContext (line 15977) | function IntegerLiteralContext(parser, ctx) {
  function NonReservedContext (line 16052) | function NonReservedContext(parser, parent, invokingState) {
  function NormalFormContext (line 16922) | function NormalFormContext(parser, parent, invokingState) {

FILE: quix-frontend/client/src/lib/language-parsers/python-grammar/lang/python/Python3Lexer.js
  function Python3Lexer (line 617) | function Python3Lexer(input) {

FILE: quix-frontend/client/src/lib/language-parsers/python-grammar/lang/python/Python3Listener.js
  function Python3Listener (line 6) | function Python3Listener() {

FILE: quix-frontend/client/src/lib/language-parsers/python-grammar/lang/python/Python3Parser.js
  function Python3Parser (line 779) | function Python3Parser (input) {
  function Single_inputContext (line 978) | function Single_inputContext(parser, parent, invokingState) {
  function File_inputContext (line 1113) | function File_inputContext(parser, parent, invokingState) {
  function Eval_inputContext (line 1267) | function Eval_inputContext(parser, parent, invokingState) {
  function DecoratorContext (line 1363) | function DecoratorContext(parser, parent, invokingState) {
  function DecoratorsContext (line 1461) | function DecoratorsContext(parser, parent, invokingState) {
  function DecoratedContext (line 1544) | function DecoratedContext(parser, parent, invokingState) {
  function FuncdefContext (line 1633) | function FuncdefContext(parser, parent, invokingState) {
  function ParametersContext (line 1735) | function ParametersContext(parser, parent, invokingState) {
  function TypedargslistContext (line 1813) | function TypedargslistContext(parser, parent, invokingState) {
  function TfpdefContext (line 2070) | function TfpdefContext(parser, parent, invokingState) {
  function VarargslistContext (line 2152) | function VarargslistContext(parser, parent, invokingState) {
  function VfpdefContext (line 2409) | function VfpdefContext(parser, parent, invokingState) {
  function StmtContext (line 2476) | function StmtContext(parser, parent, invokingState) {
  function Simple_stmtContext (line 2600) | function Simple_stmtContext(parser, parent, invokingState) {
  function Small_stmtContext (line 2704) | function Small_stmtContext(parser, parent, invokingState) {
  function Expr_stmtContext (line 2868) | function Expr_stmtContext(parser, parent, invokingState) {
  function Testlist_star_exprContext (line 3068) | function Testlist_star_exprContext(parser, parent, invokingState) {
  function AugassignContext (line 3203) | function AugassignContext(parser, parent, invokingState) {
  function Del_stmtContext (line 3275) | function Del_stmtContext(parser, parent, invokingState) {
  function Pass_stmtContext (line 3348) | function Pass_stmtContext(parser, parent, invokingState) {
  function Flow_stmtContext (line 3415) | function Flow_stmtContext(parser, parent, invokingState) {
  function Break_stmtContext (line 3526) | function Break_stmtContext(parser, parent, invokingState) {
  function Continue_stmtContext (line 3593) | function Continue_stmtContext(parser, parent, invokingState) {
  function Return_stmtContext (line 3660) | function Return_stmtContext(parser, parent, invokingState) {
  function Yield_stmtContext (line 3740) | function Yield_stmtContext(parser, parent, invokingState) {
  function Raise_stmtContext (line 3807) | function Raise_stmtContext(parser, parent, invokingState) {
  function Import_stmtContext (line 3908) | function Import_stmtContext(parser, parent, invokingState) {
  function Import_nameContext (line 3992) | function Import_nameContext(parser, parent, invokingState) {
  function Import_fromContext (line 4065) | function Import_fromContext(parser, parent, invokingState) {
  function Import_as_nameContext (line 4216) | function Import_as_nameContext(parser, parent, invokingState) {
  function Dotted_as_nameContext (line 4306) | function Dotted_as_nameContext(parser, parent, invokingState) {
  function Import_as_namesContext (line 4392) | function Import_as_namesContext(parser, parent, invokingState) {
  function Dotted_as_namesContext (line 4490) | function Dotted_as_namesContext(parser, parent, invokingState) {
  function Dotted_nameContext (line 4577) | function Dotted_nameContext(parser, parent, invokingState) {
  function Global_stmtContext (line 4665) | function Global_stmtContext(parser, parent, invokingState) {
  function Nonlocal_stmtContext (line 4759) | function Nonlocal_stmtContext(parser, parent, invokingState) {
  function Assert_stmtContext (line 4853) | function Assert_stmtContext(parser, parent, invokingState) {
  function Compound_stmtContext (line 4944) | function Compound_stmtContext(parser, parent, invokingState) {
  function If_stmtContext (line 5082) | function If_stmtContext(parser, parent, invokingState) {
  function While_stmtContext (line 5222) | function While_stmtContext(parser, parent, invokingState) {
  function For_stmtContext (line 5327) | function For_stmtContext(parser, parent, invokingState) {
  function Try_stmtContext (line 5444) | function Try_stmtContext(parser, parent, invokingState) {
  function With_stmtContext (line 5600) | function With_stmtContext(parser, parent, invokingState) {
  function With_itemContext (line 5701) | function With_itemContext(parser, parent, invokingState) {
  function Except_clauseContext (line 5787) | function Except_clauseContext(parser, parent, invokingState) {
  function SuiteContext (line 5885) | function SuiteContext(parser, parent, invokingState) {
  function TestContext (line 6036) | function TestContext(parser, parent, invokingState) {
  function Test_nocondContext (line 6174) | function Test_nocondContext(parser, parent, invokingState) {
  function LambdefContext (line 6278) | function LambdefContext(parser, parent, invokingState) {
  function Lambdef_nocondContext (line 6366) | function Lambdef_nocondContext(parser, parent, invokingState) {
  function Or_testContext (line 6454) | function Or_testContext(parser, parent, invokingState) {
  function And_testContext (line 6553) | function And_testContext(parser, parent, invokingState) {
  function Not_testContext (line 6652) | function Not_testContext(parser, parent, invokingState) {
  function ComparisonContext (line 6761) | function ComparisonContext(parser, parent, invokingState) {
  function Comp_opContext (line 6859) | function Comp_opContext(parser, parent, invokingState) {
  function Star_exprContext (line 7006) | function Star_exprContext(parser, parent, invokingState) {
  function ExprContext (line 7082) | function ExprContext(parser, parent, invokingState) {
  function Xor_exprContext (line 7169) | function Xor_exprContext(parser, parent, invokingState) {
  function And_exprContext (line 7256) | function And_exprContext(parser, parent, invokingState) {
  function Shift_exprContext (line 7343) | function Shift_exprContext(parser, parent, invokingState) {
  function Arith_exprContext (line 7444) | function Arith_exprContext(parser, parent, invokingState) {
  function TermContext (line 7545) | function TermContext(parser, parent, invokingState) {
  function FactorContext (line 7664) | function FactorContext(parser, parent, invokingState) {
  function PowerContext (line 7779) | function PowerContext(parser, parent, invokingState) {
  function AtomContext (line 7882) | function AtomContext(parser, parent, invokingState) {
  function Testlist_compContext (line 8115) | function Testlist_compContext(parser, parent, invokingState) {
  function TrailerContext (line 8231) | function TrailerContext(parser, parent, invokingState) {
  function SubscriptlistContext (line 8341) | function SubscriptlistContext(parser, parent, invokingState) {
  function SubscriptContext (line 8439) | function SubscriptContext(parser, parent, invokingState) {
  function SliceopContext (line 8556) | function SliceopContext(parser, parent, invokingState) {
  function ExprlistContext (line 8632) | function ExprlistContext(parser, parent, invokingState) {
  function TestlistContext (line 8730) | function TestlistContext(parser, parent, invokingState) {
  function DictorsetmakerContext (line 8828) | function DictorsetmakerContext(parser, parent, invokingState) {
  function ClassdefContext (line 9001) | function ClassdefContext(parser, parent, invokingState) {
  function ArglistContext (line 9105) | function ArglistContext(parser, parent, invokingState) {
  function ArgumentContext (line 9263) | function ArgumentContext(parser, parent, invokingState) {
  function Comp_iterContext (line 9368) | function Comp_iterContext(parser, parent, invokingState) {
  function Comp_forContext (line 9452) | function Comp_forContext(parser, parent, invokingState) {
  function Comp_ifContext (line 9550) | function Comp_ifContext(parser, parent, invokingState) {
  function Yield_exprContext (line 9636) | function Yield_exprContext(parser, parent, invokingState) {
  function Yield_argContext (line 9716) | function Yield_argContext(parser, parent, invokingState) {
  function StrContext (line 9827) | function StrContext(parser, parent, invokingState) {
  function NumberContext (line 9906) | function NumberContext(parser, parent, invokingState) {
  function IntegerContext (line 10002) | function IntegerContext(parser, parent, invokingState) {

FILE: quix-frontend/client/src/lib/language-parsers/python-grammar/lang/python/Python3Visitor.js
  function Python3Visitor (line 7) | function Python3Visitor() {

FILE: quix-frontend/client/src/lib/language-parsers/python-parser/parser/errors-listener.ts
  type IErrorAnnotation (line 3) | interface IErrorAnnotation {
  class PythonErrorListener (line 10) | class PythonErrorListener extends antlr4.error.ErrorListener {
    method syntaxError (line 15) | syntaxError(recognizer, offendingSymbol, line, column, msg, e) {

FILE: quix-frontend/client/src/lib/language-parsers/python-parser/parser/types.ts
  type ContextNode (line 1) | interface ContextNode {
  type Terminal (line 12) | interface Terminal {
  type CommonToken (line 18) | interface CommonToken {

FILE: quix-frontend/client/src/lib/language-parsers/python-parser/tokenizer/index.ts
  function tokenize (line 22) | function tokenize(input: string) {

FILE: quix-frontend/client/src/lib/language-parsers/python-parser/types/index.ts
  type TokensMap (line 1) | type TokensMap = number;
  type CommonToken (line 2) | interface CommonToken {

FILE: quix-frontend/client/src/lib/language-parsers/python-parser/web-worker/types.ts
  type WorkerRequest (line 4) | interface WorkerRequest {
  type WorkerResponse (line 8) | interface WorkerResponse {
  type RequestToResponseMap (line 12) | interface RequestToResponseMap {
  type WorkerRqstToResposneMapType (line 20) | type WorkerRqstToResposneMapType =
  type PythonWorkerFunctionsMap (line 23) | type PythonWorkerFunctionsMap =

FILE: quix-frontend/client/src/lib/language-parsers/python-parser/web-worker/web-worker-manager.ts
  class PythonWebWorkerMngr (line 8) | class PythonWebWorkerMngr extends TypedWorkerManager<WorkerRequest, Work...
    method getErrors (line 9) | getErrors(pythonCode: string) {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/parser/errors-listener.ts
  type IErrorAnnotation (line 3) | interface IErrorAnnotation {
  class PrestoErrorListener (line 10) | class PrestoErrorListener extends antlr4.error.ErrorListener {
    method syntaxError (line 15) | syntaxError(recognizer, offendingSymbol, line, column, msg, e) {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/parser/presto-listener.ts
  class PrestoListener (line 4) | class PrestoListener extends SqlBaseListener {
    method parseResults (line 13) | parseResults() {
    method enterStringLiteral (line 26) | enterStringLiteral(ctx: ContextNode & { children: [Terminal] }) {
    method enterTableName (line 30) | enterTableName(ctx: ContextNode) {
    method enterColumnReference (line 34) | enterColumnReference(ctx: ContextNode) {
    method enterDereference (line 40) | enterDereference(ctx: ContextNode) {
    method exitDereference (line 45) | exitDereference(ctx: ContextNode) {
    method enterNamedQuery (line 49) | enterNamedQuery(ctx: ContextNode) {
    method enterAliasedRelation (line 53) | enterAliasedRelation(ctx: any) {
    method enterSelectSingle (line 58) | enterSelectSingle(ctx: any) {
    method enterTypeConstructor (line 65) | enterTypeConstructor(ctx: any) {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/parser/types.ts
  type ContextNode (line 1) | interface ContextNode {
  type Terminal (line 12) | interface Terminal {
  type CommonToken (line 18) | interface CommonToken {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/tokenizer/index.ts
  function tokenize (line 22) | function tokenize(input: string) {
  type GetIdentifersResult (line 27) | interface GetIdentifersResult {
  function getIdentifiers (line 37) | function getIdentifiers(tokens: CommonToken[]): GetIdentifersResult {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/tokenizer/tokensMap.ts
  type TokensMap (line 1) | enum TokensMap {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/types/3rd-party.d.ts
  type SqlFormatterCfg (line 7) | interface SqlFormatterCfg {
  class StandardSqlFormatter (line 11) | class StandardSqlFormatter {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/types/index.ts
  type CommonToken (line 3) | interface CommonToken {

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/web-worker/types.ts
  type SqlRequest (line 4) | interface SqlRequest {
  type SqlResponse (line 11) | interface SqlResponse {
  type RequestToResponseMap (line 18) | interface RequestToResponseMap {
  type SqlRqstToResposneMapType (line 32) | type SqlRqstToResposneMapType =
  type SqlWorkerFunctionsMap (line 35) | type SqlWorkerFunctionsMap =

FILE: quix-frontend/client/src/lib/language-parsers/sql-parser/web-worker/web-worker-manager.ts
  type BiSqlWebWorkerMngrCtor (line 8) | type BiSqlWebWorkerMngrCtor = typeof BiSqlWebWorkerMngr;
  class BiSqlWebWorkerMngr (line 10) | class BiSqlWebWorkerMngr extends TypedWorkerManager<SqlRequest, SqlRespo...
    method getIdentifiers (line 12) | getIdentifiers(sqlQuery: string) {
    method getErrors (line 16) | getErrors(sqlQuery: string) {
    method parse (line 20) | parse(sqlQuery: string) {
    method autoFormat (line 24) | autoFormat(sqlQuery: string) {

FILE: quix-frontend/client/src/lib/runner/directives/python-runner/python-runner-init.ts
  function initConsoleEvents (line 6) | function initConsoleEvents(runner: Runner) {
  function initResultEvents (line 40) | function initResultEvents(runner: Runner) {
  function initRunnerComponent (line 55) | function initRunnerComponent(runner: Runner, runnerComponentDeferred: Pr...

FILE: quix-frontend/client/src/lib/runner/directives/python-runner/python-runner.ts
  function initEditorComponentInstance (line 12) | function initEditorComponentInstance(scope, editorComponentInstance: Cod...
  function initRunnerComponentInstance (line 44) | function initRunnerComponentInstance(scope, runnerComponentInstance: Run...
  function initRunner (line 59) | function initRunner(runner: Runner, runnerComponentDeferred, editorCompo...
  method pre (line 89) | pre(scope, element, attrs, ngModel) {

FILE: quix-frontend/client/src/lib/runner/directives/results/console/console-result-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class ConsoleResultTestkit (line 8) | class ConsoleResultTestkit extends Testkit {
    method getTimestampsCount (line 9) | async getTimestampsCount() {
    method getValueRowsCount (line 13) | async getValueRowsCount() {

FILE: quix-frontend/client/src/lib/runner/directives/results/console/console-result.ts
  method pre (line 13) | async pre(scope: IScope) {

FILE: quix-frontend/client/src/lib/runner/directives/results/console/console-types.ts
  type IScope (line 4) | interface IScope extends ngIScope {

FILE: quix-frontend/client/src/lib/runner/directives/runner/runner.ts
  function downloadFile (line 7) | function downloadFile(url, fileName) {
  function initRunner (line 22) | function initRunner(scope, instance: RunnerComponentInstance, mode = 'st...
  function destroyRunner (line 69) | function destroyRunner(scope) {
  function destroyResult (line 76) | function destroyResult(scope) {
  function destroy (line 81) | function destroy(scope) {
  function kill (line 86) | function kill(scope, notify = false) {
  function renderResult (line 98) | function renderResult(scope, queryScope, query, tableFormatter, transclu...
  class RunnerComponentInstance (line 127) | class RunnerComponentInstance extends srv.eventEmitter.EventEmitter {
    method constructor (line 134) | constructor(private readonly scope) {
    method run (line 138) | run(mode: 'stream' | 'download' = 'stream') {
    method getDataTransformer (line 142) | getDataTransformer() {
    method getResponseTransformer (line 146) | getResponseTransformer() {
    method getErrorTransformer (line 150) | getErrorTransformer() {
    method getExecuteBaseUrl (line 154) | getExecuteBaseUrl() {
    method setRequestTransformer (line 158) | setRequestTransformer(fn: (code) => typeof code) {
    method setResponseTransformer (line 162) | setResponseTransformer(fn: (response) => typeof response) {
    method setErrorTransformer (line 166) | setErrorTransformer(fn: (runner, query, error) => typeof error) {
    method setExecuteBaseUrl (line 170) | setExecuteBaseUrl(baseUrl: string) {
    method setCurrentQuery (line 174) | setCurrentQuery(query) {
    method getCurrentQuery (line 178) | getCurrentQuery() {
    method getUser (line 182) | getUser() {
    method setUser (line 186) | setUser(user) {
    method load (line 190) | load(runner) {
  method pre (line 225) | pre(scope, element, attrs, ctrl, transclude) {

FILE: quix-frontend/client/src/lib/runner/directives/sql-runner/sql-runner.ts
  function renderActions (line 14) | function renderActions(scope, editorComponentInstance, runnerComponentIn...
  method pre (line 62) | pre(scope, element, attrs, ngModel, transclude) {

FILE: quix-frontend/client/src/lib/runner/init.ts
  function toDirectiveName (line 4) | function toDirectiveName(name: string) {
  function init (line 8) | function init(ngApp: angular.IModule) {

FILE: quix-frontend/client/src/lib/runner/services/autocomplete/autocomplete-service.ts
  function setupCompleters (line 25) | async function setupCompleters(

FILE: quix-frontend/client/src/lib/runner/services/autocomplete/autocomplete-utils.ts
  function getSuggestions (line 48) | async function getSuggestions(queryContext, keywordsCompletions, sqlAuto...
  function isSearchInObject (line 63) | async function isSearchInObject(queryContext, sqlAutocompleter) {
  function createCaption (line 75) | function createCaption(str: string) {

FILE: quix-frontend/client/src/lib/runner/services/autocomplete/highlight-and-score.ts
  constant PERFECT_SCORE (line 10) | const PERFECT_SCORE = 10000;
  function highlightAndScore (line 12) | function highlightAndScore(
  function enrichCompletionItemAfterDotObject (line 23) | function enrichCompletionItemAfterDotObject(all: AceCompletion[]): AceCo...
  function enrichCompletionForObject (line 32) | function enrichCompletionForObject(prefix: string, autocompletionSuggest...
  function enrichCompletionItemInObjectSearch (line 38) | function enrichCompletionItemInObjectSearch(all: AceCompletion[], queryC...
  function enrichCompletionItem (line 53) | function enrichCompletionItem(all: AceCompletion[], lowerCasedPrefix: st...
  function updateCompletionItem (line 61) | function updateCompletionItem(
  function findLastDotIndex (line 78) | function findLastDotIndex(prefix: string): number {

FILE: quix-frontend/client/src/lib/runner/services/autocomplete/old-autocomplete-service.ts
  function getTablesCompletions (line 14) | async function getTablesCompletions(dbInfoService: DbInfo): Promise<AceC...
  function setupOldCompleter (line 21) | async function setupOldCompleter(editorInstance: CodeEditorInstance, typ...

FILE: quix-frontend/client/src/lib/runner/services/db/db-service.ts
  type IAutocomplete (line 5) | interface IAutocomplete {
  type IDbNode (line 10) | interface IDbNode {
  class DbInfo (line 16) | class DbInfo {
    method constructor (line 19) | constructor(private readonly type: string, private readonly apiBasePat...
    method fetchAllKeywords (line 21) | fetchAllKeywords(): Promise<IAutocomplete[]> {
    method fetchSchema (line 30) | fetchSchema(): Promise<IDbNode[]> {

FILE: quix-frontend/client/src/lib/runner/services/permissions/permissions-service.ts
  constant PERMISSION_ERROR_PATTERNS (line 4) | const PERMISSION_ERROR_PATTERNS = [

FILE: quix-frontend/client/src/lib/runner/services/runner-event.ts
  class RunnerEvent (line 1) | class RunnerEvent {
    method constructor (line 7) | constructor (private readonly name, private readonly options = {dontDi...
    method getName (line 9) | public getName() {
    method getOptions (line 13) | public getOptions() {
    method append (line 17) | public append(handler) {
    method prepend (line 21) | public prepend(handler) {
    method apply (line 25) | public apply(data, meta) {

FILE: quix-frontend/client/src/lib/runner/services/runner-events.ts
  class RunnerEvents (line 4) | class RunnerEvents {
    method constructor (line 7) | constructor(private readonly runner) {
    method register (line 11) | public register(eventName, handler, options = {dontDigest: false}) {
    method getRegisteredEvents (line 19) | public getRegisteredEvents(): RunnerEvent[] {
    method append (line 23) | public append(eventName, handler): RunnerEvents {
    method prepend (line 28) | public prepend(eventName, handler): RunnerEvents {
    method apply (line 33) | public apply(eventName, data, meta): RunnerEvents {

FILE: quix-frontend/client/src/lib/runner/services/runner-query.ts
  type IField (line 5) | interface IField {
  type IError (line 10) | interface IError {
  type ITime (line 15) | interface ITime {
  type IStatus (line 21) | interface IStatus {
  function getFieldName (line 29) | function getFieldName(field: string, fieldNames: Record<string, number>) {
  function startDurationCount (line 35) | function startDurationCount(): ITime {
  function stopDurationCount (line 50) | function stopDurationCount(time) {
  class RunnerQuery (line 54) | class RunnerQuery extends srv.eventEmitter.EventEmitter {
    method constructor (line 77) | constructor(private readonly id, private readonly index) {
    method meta (line 81) | public meta(name, value?) {
    method setDetails (line 89) | public setDetails(details) {
    method getDetails (line 94) | public getDetails() {
    method results (line 98) | public get results(): any {
    method fields (line 102) | public get fields(): IField[] {
    method running (line 106) | public get running(): boolean {
    method success (line 110) | public get success(): boolean {
    method finished (line 114) | public get finished(): boolean {
    method elapsedTime (line 118) | public get elapsedTime(): string {
    method startTime (line 122) | public get startTime(): number {
    method getId (line 126) | public getId(): string {
    method getIndex (line 130) | public getIndex(): number {
    method getResults (line 134) | public getResults(): any {
    method getFields (line 138) | public getFields(): IField[] {
    method getRawFields (line 142) | public getRawFields(): string[] {
    method getError (line 146) | public getError(): IError {
    method getTime (line 150) | public getTime(): ITime {
    method getTitle (line 154) | public getTitle() {
    method setTitle (line 158) | public setTitle(title: string): RunnerQuery {
    method setFields (line 163) | public setFields(fields: string[]): RunnerQuery {
    method addRow (line 176) | public addRow(row): Object {
    method setError (line 198) | public setError(error): RunnerQuery {
    method setErrorMessage (line 205) | public setErrorMessage(msg) {
    method getStats (line 209) | public getStats() {
    method setStats (line 213) | public setStats(stats: {[key: string]: any}) {
    method start (line 217) | public start(): RunnerQuery {
    method end (line 227) | public end(): RunnerQuery {

FILE: quix-frontend/client/src/lib/runner/services/runner-service.ts
  function initSocket (line 9) | function initSocket(socket: RunnerSocket, events: RunnerEvents, transfor...
  function sendSocketData (line 32) | function sendSocketData(socket, code, user, transformers, mode = 'stream...
  class Runner (line 49) | class Runner extends srv.eventEmitter.EventEmitter {
    method constructor (line 66) | constructor(private readonly type: RunnerType, private readonly scope,...
    method log (line 172) | protected log(value: boolean) {
    method start (line 176) | protected start() {
    method finish (line 187) | protected finish() {
    method getScope (line 206) | public getScope() {
    method getSocket (line 210) | public getSocket() {
    method getEvents (line 214) | public getEvents() {
    method getState (line 218) | public getState() {
    method getQueries (line 222) | public getQueries(): RunnerQuery[] {
    method getTotalNumOfQueries (line 226) | public getTotalNumOfQueries(): number {
    method getCurrentQuery (line 230) | public getCurrentQuery(): RunnerQuery {
    method getMode (line 234) | public getMode(): string {
    method error (line 238) | public get error() {
    method progress (line 242) | public get progress() {
    method elapsedTime (line 246) | public get elapsedTime() {
    method running (line 250) | public get running() {
    method getCode (line 254) | public getCode() {
    method transformRequest (line 258) | public transformRequest(transformer): Runner {
    method transformResponse (line 264) | public transformResponse(transformer): Runner {
    method run (line 270) | public run(code, user?): Runner {
    method kill (line 310) | public kill() {
    method getConnectionErrorMessage (line 320) | getConnectionErrorMessage(connectionId) {
  function create (line 336) | function create(type: RunnerType, scope, {

FILE: quix-frontend/client/src/lib/runner/services/runner-socket.ts
  function attachProtocol (line 4) | function attachProtocol(url: string) {
  function getEndpoint (line 14) | function getEndpoint(type: string, version: number) {
  class RunnerSocket (line 18) | class RunnerSocket extends srv.Socket {
    method constructor (line 23) | constructor (
    method send (line 36) | public send(payload): RunnerSocket {
    method transformResponse (line 41) | public transformResponse(transformer): RunnerSocket {

FILE: quix-frontend/client/src/lib/runner/services/runner-state.ts
  class State (line 7) | class State {
    method getId (line 27) | public getId(): string {
    method setId (line 31) | public setId(id): State {
    method getFields (line 36) | public getFields(): IField[] {
    method getResults (line 40) | public getResults() {
    method getError (line 44) | public getError() {
    method hasQueries (line 48) | public hasQueries(): boolean {
    method getQueries (line 52) | public getQueries(): RunnerQuery[] {
    method getCurrentQuery (line 56) | public getCurrentQuery(): RunnerQuery {
    method getQueryById (line 64) | public getQueryById(id): RunnerQuery {
    method startQuery (line 68) | public startQuery(id): State {
    method endQuery (line 73) | public endQuery(id): State {
    method getTotalNumOfQueries (line 78) | public getTotalNumOfQueries() {
    method setTotalNumOfQueries (line 82) | public setTotalNumOfQueries(num) {
    method getProgress (line 86) | public getProgress(): number {
    method setProgress (line 90) | public setProgress(progress): State {
    method getStatus (line 95) | public getStatus(): IStatus {
    method startDurationCount (line 99) | public startDurationCount() {
    method stopDurationCount (line 110) | public stopDurationCount() {
    method getTime (line 115) | public getTime(): ITime {
    method setRunningStatus (line 119) | public setRunningStatus(value: boolean): State {
    method setSuccessStatus (line 124) | public setSuccessStatus(value: boolean): State {
    method setFinishedStatus (line 129) | public setFinishedStatus(value: boolean): State {
    method setErrorStatus (line 134) | public setErrorStatus(value: boolean): State {
    method setKilledStatus (line 139) | public setKilledStatus(value: boolean): State {

FILE: quix-frontend/client/src/lib/runner/services/syntax-valdator/syntax-validator-service.ts
  type HasGetErrorsMethod (line 4) | interface HasGetErrorsMethod {
  function getParamsOffset (line 8) | function getParamsOffset(editorInstance: CodeEditorInstance) {

FILE: quix-frontend/client/src/lib/runner/typings/angular-promise.d.ts
  type IPromise (line 5) | interface IPromise<T> {

FILE: quix-frontend/client/src/lib/runner/typings/runner-types.ts
  type RunnerType (line 1) | type RunnerType = 'sql' | 'python' | 'native';

FILE: quix-frontend/client/src/lib/runner/typings/types.d.ts
  type DedicatedWorkerGlobalScope (line 3) | interface DedicatedWorkerGlobalScope {}
  type Promise (line 4) | interface Promise<T> {

FILE: quix-frontend/client/src/lib/sql-autocomplete/adapter/sql-autocomplete-adapter-utills.ts
  type ObjectChild (line 6) | interface ObjectChild {
  function getObjectChildren (line 11) | function getObjectChildren(obj: Record<string, any>, parentName = ''): O...
  function findColumnPathForPrefix (line 26) | function findColumnPathForPrefix(tables: TableInfo[], brokenPrefix: stri...
  function getAllChildrenOfTables (line 69) | function getAllChildrenOfTables(tables: TableInfo[]) {
  function getSearchCompletion (line 92) | function getSearchCompletion(tables: TableInfo[], prefix: string | undef...
  function byPrefix (line 110) | function byPrefix(relevantPartOfPrefix: string) {
  function getNextLevel (line 126) | function getNextLevel(tables: TableInfo[], prefix: string | undefined): ...
  function doesSubstringMatchInHierarchy (line 139) | function doesSubstringMatchInHierarchy(substringAfterFirstDot, searchPar...
  function extractPrefixUntilLastDot (line 145) | function extractPrefixUntilLastDot(inputString: string) {

FILE: quix-frontend/client/src/lib/sql-autocomplete/adapter/sql-autocomplete-adapter.ts
  type ComplexCompleterItem (line 15) | interface ComplexCompleterItem extends ICompleterItem {
  class SqlAutocompleter (line 19) | class SqlAutocompleter implements IAutocompleter {
    method constructor (line 23) | constructor(
    method getCompletionItemsFromQueryContext (line 37) | public async getCompletionItemsFromQueryContext(queryContext: QueryCon...
    method getCompletionItemsFromQueryContextColumn (line 58) | public async getCompletionItemsFromQueryContextColumn(queryContext: Qu...
    method translateAndGetQueryContextColumns (line 67) | public async translateAndGetQueryContextColumns(tables: TableInfo[], p...
    method extractColumnsFromTable (line 75) | private async extractColumnsFromTable(tables: TableInfo[]) {
    method getQueryContextTables (line 88) | private getQueryContextTables(tables: TableInfo[]) {
    method getQueryContextColumns (line 97) | private async getQueryContextColumns(tables: TableInfo[]) {
    method extractTableColumns (line 149) | private async extractTableColumns(table: TableInfo) {
    method createCompleterItem (line 170) | private createCompleterItem(value: string, meta: string): ICompleterIt...
    method getEntitiesCompletersFromDbBasedOnPrefix (line 174) | private async getEntitiesCompletersFromDbBasedOnPrefix(prefix: string) {
    method searchEntitiesFromDb (line 205) | private async searchEntitiesFromDb(

FILE: quix-frontend/client/src/lib/sql-autocomplete/adapter/tests/test-utils/mock-db-config.ts
  class MockDbInfoService (line 9) | class MockDbInfoService implements IDbInfoConfig {
    method preFetch (line 11) | preFetch() {
    method getColumnsByTable (line 15) | public async getColumnsByTable(
    method getTablesBySchema (line 26) | public async getTablesBySchema(catalog: string, schema: string) {
    method getSchemasByCatalog (line 33) | public async getSchemasByCatalog(catalog: string) {
    method getCatalogs (line 40) | public async getCatalogs() {
    method search (line 44) | public async search(type: string, prefix: string) {

FILE: quix-frontend/client/src/lib/sql-autocomplete/adapter/tests/test-utils/test-getCompletionItemsFromQueryContext.spec.ts
  function getCompletions (line 113) | async function getCompletions(queryContext: QueryContext , completer: Sq...

FILE: quix-frontend/client/src/lib/sql-autocomplete/adapter/trinoToJs.ts
  type StartingOptions (line 1) | const enum StartingOptions {
  type SpecialCharacters (line 7) | const enum SpecialCharacters {
  function trinoToJs (line 14) | function trinoToJs(trinoObjectAsString: string, index: number):  object|...
  function processRow (line 28) | function processRow(trinoObjectAsString: string, index: number): object {
  function findBeginningOfWord (line 81) | function findBeginningOfWord(str: string, index: number): number {
  function handleStartingOptions (line 88) | function handleStartingOptions(trinoObjectAsString: string, start: numbe...
  function validateKey (line 120) | function validateKey(key: string, indexInOriginalString: number) {
  function getOperator (line 128) | function getOperator(trinoObjectAsString: string, start: number , end: n...
  function findClosingParentheses (line 132) | function findClosingParentheses(trinoObjectAsString: string, counter: nu...

FILE: quix-frontend/client/src/lib/sql-autocomplete/adapter/types.ts
  type IContextEvaluator (line 3) | type IContextEvaluator = (input: string, position: number) => any;
  type IAutocompleter (line 5) | interface IAutocompleter {

FILE: quix-frontend/client/src/lib/sql-autocomplete/db-info/db-info-service.ts
  class DbInfoService (line 11) | class DbInfoService implements IDbInfoConfig {
    method constructor (line 14) | constructor(

FILE: quix-frontend/client/src/lib/sql-autocomplete/db-info/types.ts
  type BaseEntity (line 1) | interface BaseEntity {
  type Column (line 6) | interface Column extends BaseEntity {
  type NestedColumn (line 10) | interface NestedColumn extends Column {
  type Table (line 14) | interface Table extends BaseEntity {
  type Schema (line 18) | interface Schema extends BaseEntity {
  type Catalog (line 22) | interface Catalog extends BaseEntity {
  type CacheProps (line 26) | interface CacheProps {
  type IDbInfoConfig (line 31) | interface IDbInfoConfig {

FILE: quix-frontend/client/src/lib/sql-autocomplete/sql-context-evaluator/presto-context-listener.ts
  class PrestoContextListener (line 14) | class PrestoContextListener extends SqlBaseListener {
    method setIdentifier (line 23) | setIdentifier(value: string) {
    method getWithNodes (line 31) | getWithNodes(): any[] {
    method getNodeFound (line 38) | getNodeFound(): any {
    method getContextType (line 47) | getContextType(): ContextType {
    method getQuerySpecificationNode (line 57) | getQuerySpecificationNode(): any {
    method enterUnquotedIdentifier (line 80) | enterUnquotedIdentifier(ctx: any) {
    method enterColumnReference (line 90) | enterColumnReference(_ctx: any) {
    method exitColumnReference (line 96) | exitColumnReference(_ctx: any) {
    method enterSelectSingle (line 104) | enterSelectSingle(_ctx: any) {
    method exitSelectSingle (line 110) | exitSelectSingle(_ctx: any) {
    method enterJoinCriteria (line 116) | enterJoinCriteria(_ctx: any) {
    method exitJoinCriteria (line 122) | exitJoinCriteria(_ctx: any) {
    method enterJoinType (line 128) | enterJoinType(ctx: any) {
    method enterGroupBy (line 137) | enterGroupBy(ctx: any) {
    method enterSortItem (line 146) | enterSortItem(ctx: any) {
    method enterTableName (line 155) | enterTableName(_ctx: any) {
    method exitTableName (line 161) | exitTableName(_ctx: any) {
    method enterPresto_with (line 169) | enterPresto_with(_ctx: any) {
    method exitPresto_with (line 173) | exitPresto_with(_ctx: any) {
    method enterNamedQuery (line 177) | enterNamedQuery(ctx: any) {
    method missingChildrenExists (line 183) | missingChildrenExists(ctx: any, symbolType: any) {

FILE: quix-frontend/client/src/lib/sql-autocomplete/sql-context-evaluator/tests/queries-spec/utils.ts
  type TestCase (line 5) | interface TestCase {

FILE: quix-frontend/client/src/lib/sql-autocomplete/sql-context-evaluator/tests/result-options/utils.ts
  type BasicQueryContextOption (line 4) | type BasicQueryContextOption = {

FILE: quix-frontend/client/src/lib/sql-autocomplete/sql-context-evaluator/types.ts
  type TableType (line 3) | enum TableType {
  type QueryDetails (line 8) | interface QueryDetails {
  type TableInfo (line 14) | interface TableInfo {
  type ContextType (line 23) | enum ContextType {
  type QueryContext (line 29) | interface QueryContext {

FILE: quix-frontend/client/src/lib/sql-formatter/core/Formatter.ts
  type Cfg (line 9) | interface Cfg {
  class Formatter (line 13) | class Formatter {
    method constructor (line 28) | constructor(cfg, tokenizer) {
    method format (line 45) | format(query) {
    method getFormattedQueryFromTokens (line 52) | getFormattedQueryFromTokens() {
    method formatLineComment (line 94) | formatLineComment(token, query: string) {
    method formatBlockComment (line 98) | formatBlockComment(token, query: string) {
    method indentComment (line 102) | indentComment(comment) {
    method formatToplevelReservedWord (line 106) | formatToplevelReservedWord(token, query) {
    method formatNewlineReservedWord (line 117) | formatNewlineReservedWord(token, query) {
    method equalizeWhitespace (line 122) | equalizeWhitespace(string) {
    method formatOpeningParentheses (line 127) | formatOpeningParentheses(token, query) {
    method formatClosingParentheses (line 146) | formatClosingParentheses(token, query) {
    method formatPlaceholder (line 156) | formatPlaceholder(token, query) {
    method formatComma (line 161) | formatComma(token, query) {
    method formatWithSpaceAfter (line 173) | formatWithSpaceAfter(token, query) {
    method formatWithoutSpaces (line 177) | formatWithoutSpaces(token, query) {
    method formatWithSpaces (line 181) | formatWithSpaces(token, query) {
    method formatQuerySeparator (line 185) | formatQuerySeparator(token, query) {
    method addNewline (line 189) | addNewline(query) {
    method trimTrailingWhitespace (line 193) | trimTrailingWhitespace(query) {
    method previousNonWhitespaceToken (line 201) | previousNonWhitespaceToken() {
    method previousToken (line 209) | previousToken(offset = 1) {

FILE: quix-frontend/client/src/lib/sql-formatter/core/Indentation.ts
  constant INDENT_TYPE_TOP_LEVEL (line 4) | const INDENT_TYPE_TOP_LEVEL = 'top-level';
  constant INDENT_TYPE_BLOCK_LEVEL (line 5) | const INDENT_TYPE_BLOCK_LEVEL = 'block-level';
  class Indentation (line 15) | class Indentation {
    method constructor (line 21) | constructor(indent) {
    method getIndent (line 30) | getIndent() {
    method increaseToplevel (line 37) | increaseToplevel() {
    method increaseBlockLevel (line 44) | increaseBlockLevel() {
    method decreaseTopLevel (line 52) | decreaseTopLevel() {
    method decreaseBlockLevel (line 63) | decreaseBlockLevel() {

FILE: quix-frontend/client/src/lib/sql-formatter/core/InlineBlock.ts
  constant INLINE_MAX_LENGTH (line 3) | const INLINE_MAX_LENGTH = 50;
  class InlineBlock (line 12) | class InlineBlock {
    method constructor (line 14) | constructor() {
    method beginIfPossible (line 24) | beginIfPossible(tokens, index) {
    method end (line 38) | end() {
    method isActive (line 46) | isActive() {
    method isInlineBlock (line 52) | isInlineBlock(tokens, index) {
    method isForbiddenToken (line 83) | isForbiddenToken({type, value}) {

FILE: quix-frontend/client/src/lib/sql-formatter/core/Params.ts
  class Params (line 4) | class Params {
    method constructor (line 10) | constructor(params) {
    method get (line 22) | get({key, value}) {

FILE: quix-frontend/client/src/lib/sql-formatter/core/Tokenizer.ts
  class Tokenizer (line 5) | class Tokenizer {
    method constructor (line 38) | constructor(cfg: any) {
    method createLineCommentRegex (line 65) | createLineCommentRegex(lineCommentTypes) {
    method createReservedWordRegex (line 69) | createReservedWordRegex(reservedWords) {
    method createWordRegex (line 74) | createWordRegex(specialChars = []) {
    method createStringRegex (line 78) | createStringRegex(stringTypes) {
    method createStringPattern (line 88) | createStringPattern(stringTypes) {
    method createParenRegex (line 100) | createParenRegex(parens) {
    method escapeParen (line 104) | escapeParen(paren) {
    method createPlaceholderRegex (line 114) | createPlaceholderRegex(types, pattern) {
    method tokenize (line 132) | tokenize(input) {
    method getNextToken (line 148) | getNextToken(input, previousToken) {
    method getWhitespaceToken (line 163) | getWhitespaceToken(input) {
    method getCommentToken (line 171) | getCommentToken(input) {
    method getLineCommentToken (line 175) | getLineCommentToken(input) {
    method getBlockCommentToken (line 183) | getBlockCommentToken(input) {
    method getStringToken (line 191) | getStringToken(input) {
    method getOpenParenToken (line 199) | getOpenParenToken(input) {
    method getCloseParenToken (line 207) | getCloseParenToken(input) {
    method getPlaceholderToken (line 215) | getPlaceholderToken(input) {
    method getIdentNamedPlaceholderToken (line 223) | getIdentNamedPlaceholderToken(input) {
    method getStringNamedPlaceholderToken (line 231) | getStringNamedPlaceholderToken(input) {
    method getIndexedPlaceholderToken (line 239) | getIndexedPlaceholderToken(input) {
    method getPlaceholderTokenWithKey (line 247) | getPlaceholderTokenWithKey({input, regex, parseKey}) {
    method getEscapedPlaceholderKey (line 255) | getEscapedPlaceholderKey({key, quoteChar}) {
    method getNumberToken (line 260) | getNumberToken(input) {
    method getOperatorToken (line 269) | getOperatorToken(input) {
    method getReservedWordToken (line 277) | getReservedWordToken(input, previousToken) {
    method getToplevelReservedToken (line 288) | getToplevelReservedToken(input) {
    method getNewlineReservedToken (line 296) | getNewlineReservedToken(input) {
    method getPlainReservedToken (line 304) | getPlainReservedToken(input) {
    method getWordToken (line 312) | getWordToken(input) {
    method getTokenOnFirstMatch (line 320) | getTokenOnFirstMatch({input, type, regex}): any {

FILE: quix-frontend/client/src/lib/sql-formatter/languages/SqlWithQuixVarFormmater.ts
  class QuixSqlFormatter (line 129) | class QuixSqlFormatter {
    method constructor (line 135) | constructor(cfg = {}) {
    method format (line 145) | format(query) {

FILE: quix-frontend/client/src/lib/sql-formatter/languages/StandardSqlFormatter.ts
  class StandardSqlFormatter (line 338) | class StandardSqlFormatter {
    method constructor (line 343) | constructor(cfg) {
    method format (line 353) | format(query) {

FILE: quix-frontend/client/src/lib/sql-formatter/sqlFormatter.ts
  type Cfg (line 3) | interface Cfg {

FILE: quix-frontend/client/src/lib/store/services/store-cache.ts
  class Request (line 5) | class Request {
    method shouldHandleRequest (line 10) | private shouldHandleRequest(args: any[]) {
    method shouldHandleResponse (line 14) | private shouldHandleResponse(requestId) {
    method clear (line 18) | private clear() {
    method createRequest (line 22) | private createRequest(id: string, args, fetch: Function, onSuccess: Fu...
    method do (line 41) | do(args: any[], fetch: Function, onSuccess: Function, onError: Functio...
  class Cache (line 54) | class Cache<T> {
    method getCache (line 61) | protected getCache(...args) {
    method setCache (line 65) | protected setCache(...args) {
    method setError (line 69) | protected setError(...args) {
    method fetchAndSetCache (line 73) | private fetchAndSetCache(...args): ng.IPromise<T> {
    method cacheWith (line 77) | cacheWith(cacher: Function): Cache<T> {
    method getWith (line 82) | getWith(getter: Function): Cache<T> {
    method fetchWith (line 87) | fetchWith(fetcher: Function): Cache<T> {
    method catchWith (line 92) | catchWith(catcher: Function): Cache<T> {
    method get (line 100) | get(...args): ng.IPromise<T> {
    method fetch (line 107) | fetch(...args): ng.IPromise<T> {
  class StoreCache (line 112) | class StoreCache<T> extends Cache<T> {
    method constructor (line 113) | constructor(private readonly store: Store, private readonly branch: st...
    method getCache (line 117) | protected getCache(...args): T {
    method setCache (line 123) | protected setCache(...args): ng.IPromise<T> {
    method setError (line 133) | protected setError(...args): ng.IPromise<T> {

FILE: quix-frontend/client/src/lib/store/services/store-logger.ts
  function onError (line 6) | function onError(error) {
  type ServerFrameworkType (line 13) | type ServerFrameworkType = 'Scala' | 'Node';
  class StoreLogger (line 15) | class StoreLogger {
    method constructor (line 19) | constructor(endpoint, private readonly sessionId = null, server: Serve...
    method log (line 26) | log(eventName, data) {
    method bulk (line 30) | bulk() {

FILE: quix-frontend/client/src/lib/store/services/store.ts
  type IBranch (line 8) | type IBranch<T = any> = (
  type ReduxStore (line 11) | type ReduxStore<S> = Redux.Store<S>;
  type IBranches (line 12) | interface IBranches {
  function getLogParams (line 16) | function getLogParams({ type, ...action }) {
  function logAction (line 24) | function logAction(logger, action) {
  function logBulkAction (line 28) | function logBulkAction(logger, ...actions) {
  function resolveActions (line 40) | function resolveActions(
  function logMiddleware (line 93) | function logMiddleware(logger) {
  function promiseMiddleware (line 126) | function promiseMiddleware(biStore) {
  function functionMiddleware (line 161) | function functionMiddleware(biStore) {
  function initBranches (line 171) | function initBranches(branches: IBranches) {
  type StoreOptions (line 227) | interface StoreOptions {
  class Store (line 238) | class Store<S = any> {
    method constructor (line 243) | constructor(branches: IBranches, options: StoreOptions = {}) {
    method getState (line 298) | getState(branch?): S {
    method subscribe (line 315) | subscribe(branch: string, fn: (state, store?) => void, scope): Function {
    method getReduxStore (line 335) | getReduxStore() {
  function create (line 345) | function create(

FILE: quix-frontend/client/src/lib/ui/components/Highlighter.tsx
  type HighlighterProps (line 4) | interface HighlighterProps {

FILE: quix-frontend/client/src/lib/ui/components/autocomplete/autocomplete.hook.ts
  type AutocompleteProps (line 9) | interface AutocompleteProps {
  type StateData (line 35) | interface StateData {
  type Actions (line 46) | interface Actions {

FILE: quix-frontend/client/src/lib/ui/components/date-picker/date-picker.hook.ts
  type Range (line 13) | interface Range {
  type DateRanges (line 19) | type DateRanges = Record<string, any>;
  type DatePickerTypes (line 20) | type DatePickerTypes = 'Range';
  type OnChangeDatePickerProps (line 21) | interface OnChangeDatePickerProps {
  type DatePickerProps (line 27) | interface DatePickerProps {
  type StateData (line 43) | interface StateData {
  type DatePickerActions (line 50) | interface DatePickerActions {

FILE: quix-frontend/client/src/lib/ui/components/dropdown/Dropdown.tsx
  type DropdownProps (line 9) | interface DropdownProps {

FILE: quix-frontend/client/src/lib/ui/components/hoc/makePagination.tsx
  type InjectedPaginationProps (line 5) | interface InjectedPaginationProps {
  type MakePaginationProps (line 12) | interface MakePaginationProps {

FILE: quix-frontend/client/src/lib/ui/components/input/Input.tsx
  type InputProps (line 4) | interface InputProps

FILE: quix-frontend/client/src/lib/ui/components/panel/Panel.tsx
  type PanelProps (line 3) | interface PanelProps {

FILE: quix-frontend/client/src/lib/ui/components/table/Table.tsx
  type TableProps (line 6) | interface TableProps {

FILE: quix-frontend/client/src/lib/ui/components/table/TableRow.tsx
  type RowConfig (line 3) | interface RowConfig<T> {
  type HighlightedRowConfig (line 10) | interface HighlightedRowConfig<T> extends RowConfig<T> {
  type TableRowProps (line 19) | interface TableRowProps {

FILE: quix-frontend/client/src/lib/ui/components/table/table-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class TableTestkit (line 11) | class TableTestkit extends Testkit {

FILE: quix-frontend/client/src/lib/ui/directives/breadcrumbs/breadcrumbs.ts
  function directive (line 6) | function directive() {

FILE: quix-frontend/client/src/lib/ui/directives/common/dropdown-list.ts
  class DropdownList (line 14) | class DropdownList {
    method constructor (line 18) | constructor(
    method reset (line 175) | private reset() {
    method format (line 184) | private format(model: any) {
    method parse (line 194) | private parse(model: any[]) {
    method validate (line 212) | private validate() {
    method render (line 224) | private render(model: any[] = this.scope.model) {
    method applySearchText (line 237) | private applySearchText(text) {
    method setOptions (line 250) | private setOptions(collection: any[] = this.scope.vm.options.collectio...
    method initOptions (line 259) | private initOptions(collection: any[] = this.scope.vm.options.collecti...
    method search (line 300) | private search(collection: any[] = this.scope.vm.options.filtered) {
    method renderToggle (line 322) | public renderToggle() {
    method renderOption (line 371) | public renderOption(option: any) {

FILE: quix-frontend/client/src/lib/ui/directives/content-editable/content-editable.ts
  function selectText (line 4) | function selectText(element) {
  function updateNgModel (line 14) | function updateNgModel(scope, value, ngModel) {
  method pre (line 46) | pre(scope, element, attrs, [ngModel]) {

FILE: quix-frontend/client/src/lib/ui/directives/copy-to-clipboard/copy-to-clipboard.ts
  function directive (line 7) | function directive() {

FILE: quix-frontend/client/src/lib/ui/directives/date-picker/date-picker.ts
  function getRange (line 9) | function getRange(options) {
  function formatter (line 25) | function formatter(model, dateFormat) {
  function parser (line 31) | function parser(model, dateFormat) {
  function init (line 37) | function init(scope, element) {
  function renderer (line 69) | function renderer(element, model) {
  method pre (line 92) | pre(scope, element, attrs, [ngModel, errors]) {

FILE: quix-frontend/client/src/lib/ui/directives/draggable/draggable.ts
  method link (line 10) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/dropdown/dropdown.ts
  function setClasses (line 10) | function setClasses(element, popperActualPlacement) {
  function show (line 26) | function show(scope, element) {
  function hide (line 105) | function hide(scope, mute = false) {
  method pre (line 134) | pre(scope, element, attrs) {

FILE: quix-frontend/client/src/lib/ui/directives/droppable/droppable.ts
  method link (line 10) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/dual-action/dual-action.ts
  method pre (line 17) | pre(scope) {

FILE: quix-frontend/client/src/lib/ui/directives/editable/editable.ts
  function finish (line 8) | function finish(vm) {
  method link (line 27) | link(scope, element, attr, ngModel, transclude) {

FILE: quix-frontend/client/src/lib/ui/directives/filter/filter-items.ts
  method link (line 10) | link(scope, element, attrs, [ngModel, biFilter]) {

FILE: quix-frontend/client/src/lib/ui/directives/filter/filter-term.ts
  method link (line 9) | link(scope, element, attrs, [ngModel, biFilter]) {

FILE: quix-frontend/client/src/lib/ui/directives/filter/filter.ts
  class Controller (line 3) | class Controller extends srv.eventEmitter.EventEmitter {
    method constructor (line 8) | constructor(private readonly $scope) {
    method getTerms (line 12) | private getTerms() {
    method reset (line 16) | private reset() {
    method setItems (line 20) | public setItems(items) {
    method addTerm (line 25) | public addTerm(term: Function) {
    method filter (line 29) | public filter() {

FILE: quix-frontend/client/src/lib/ui/directives/focus/focus-if.ts
  method link (line 10) | link(scope, element, attr) {

FILE: quix-frontend/client/src/lib/ui/directives/focus/focus.ts
  method link (line 7) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/foldable/foldable.ts
  method link (line 18) | link(scope: ng.IScope, element: JQuery, attr: ng.IAttributes, ctrls, tra...

FILE: quix-frontend/client/src/lib/ui/directives/html/html.ts
  method link (line 13) | async link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/icon-badge/icon-badge.ts
  method link (line 10) | link(scope) {

FILE: quix-frontend/client/src/lib/ui/directives/infinite-scroll/infinite-scroll.ts
  method link (line 37) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/key-nav/key-nav.ts
  constant NAVIGATION_KEYS (line 5) | const NAVIGATION_KEYS = {
  function canScroll (line 15) | function canScroll(element) {
  function adjustScroll (line 19) | function adjustScroll(scope, element) {
  function setCurrentItemByIndex (line 33) | function setCurrentItemByIndex(scope, element, index) {
  function dispatchNavigationEvent (line 51) | function dispatchNavigationEvent(scope: any, key: any) {
  function isItemDisabled (line 61) | function isItemDisabled(scope, element,index) {
  function setupCollection (line 66) | function setupCollection(scope, element, collection) {
  function getElements (line 77) | function getElements(scope, element) {
  method post (line 97) | post(scope: ng.IScope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/maximizable/maximizable.ts
  method link (line 34) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/on-image-load/on-image-load.ts
  method link (line 10) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/progress-gauge/progress-gauge.ts
  method link (line 15) | link (scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/progress-line/progress-line.ts
  method link (line 15) | link (scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/resizable/resizable.ts
  method link (line 11) | link(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/scroll/scroll-to.ts
  constant OFFSET (line 3) | const OFFSET = -10;
  method link (line 9) | link(scope, element, attr) {

FILE: quix-frontend/client/src/lib/ui/directives/search/search.ts
  function directive (line 6) | function directive() {

FILE: quix-frontend/client/src/lib/ui/directives/simple-select/simple-select.ts
  type IScope (line 6) | interface IScope extends ng.IScope {
  function directive (line 10) | function directive() {

FILE: quix-frontend/client/src/lib/ui/directives/state-loader/state-loader.ts
  function getTargetDepth (line 5) | function getTargetDepth(state1: string, state2: string) {
  function setPrefix (line 28) | function setPrefix(p: string) {
  method link (line 37) | link(scope, element, attrs) {

FILE: quix-frontend/client/src/lib/ui/directives/table/header/table-header.ts
  method pre (line 19) | pre(scope) {

FILE: quix-frontend/client/src/lib/ui/directives/table/row/table-row.ts
  method pre (line 75) | pre(scope, element) {

FILE: quix-frontend/client/src/lib/ui/directives/table/table.ts
  method getSortValue (line 14) | getSortValue(scope, row) {
  function shouldFetchMore (line 21) | function shouldFetchMore(container) {
  function adjustHeaderPosition (line 29) | function adjustHeaderPosition(container, columns) {
  function initInfiniteScroll (line 34) | function initInfiniteScroll(scope, element, container, options) {
  function initStickyHeader (line 60) | function initStickyHeader(element, container, options) {
  function initEvents (line 80) | function initEvents(scope, element, container, options) {
  function initOrderBy (line 100) | function initOrderBy(scope) {
  function orderCollection (line 115) | function orderCollection(scope, element) {
  method pre (line 221) | pre(scope, element, attrs) {

FILE: quix-frontend/client/src/lib/ui/directives/tabs/tabs-router.ts
  type IBiTab (line 8) | interface IBiTab {
  type TabsRouterScope (line 15) | interface TabsRouterScope extends IScope {
  method link (line 31) | link(scope: TabsRouterScope, element: JQuery, attr: ng.IAttributes, ctrl...

FILE: quix-frontend/client/src/lib/ui/directives/tabs/tabs.ts
  type IBiTab (line 7) | interface IBiTab {
  type IScope (line 13) | interface IScope extends ngScope {
  method link (line 30) | link(scope: IScope, element: JQuery, attr: ng.IAttributes, ctrls, transc...

FILE: quix-frontend/client/src/lib/ui/directives/tags/tags.ts
  type IScope (line 6) | interface IScope extends ng.IScope {
  function renderTag (line 10) | function renderTag(transclude, biOptions, tag) {
  function directive (line 24) | function directive(): ng.IDirective {

FILE: quix-frontend/client/src/lib/ui/directives/tooltip/tooltip.ts
  method pre (line 19) | pre(scope) {

FILE: quix-frontend/client/src/lib/ui/filters/to-human-case.ts
  function capitalize (line 6) | function capitalize(input: string) {

FILE: quix-frontend/client/src/lib/ui/init.ts
  function toDirectiveName (line 7) | function toDirectiveName(name: string) {
  function init (line 15) | function init(ngApp: angular.IModule) {

FILE: quix-frontend/client/src/lib/ui/services/confirm.ts
  type IConfirmOptions (line 5) | interface IConfirmOptions extends IDialogOptions {
  function init (line 13) | function init(htmlOrOptions: string | IConfirmOptions, promise: any) {

FILE: quix-frontend/client/src/lib/ui/services/date.ts
  function getTimezoneOffset (line 24) | function getTimezoneOffset(date) {
  class DateService (line 28) | class DateService {
    method constructor (line 32) | constructor(date?: number | string) {
    method getRange (line 38) | static getRange(duration, {maxDate = null, format = false} = {}) {
    method fromUTC (line 56) | static fromUTC(date) {
    method fromUTC (line 60) | fromUTC() {
    method toUTC (line 64) | toUTC() {
    method asMoment (line 68) | asMoment() {
    method asDate (line 72) | asDate() {

FILE: quix-frontend/client/src/lib/ui/services/dialog-testkit.ts
  class DialogTestkit (line 3) | class DialogTestkit extends Testkit {
    method isShown (line 4) | async isShown() {

FILE: quix-frontend/client/src/lib/ui/services/dialog.ts
  type IDialog (line 8) | interface IDialog extends ng.IPromise<any> {
  type IDialogOptions (line 13) | interface IDialogOptions {
  function createScope (line 22) | function createScope(deferred, scope?, locals?) {
  function showDialog (line 52) | function showDialog(scope, htmlOrOptions: string | IDialogOptions) {
  function destroy (line 118) | function destroy({scope, dialog}) {

FILE: quix-frontend/client/src/lib/ui/services/toast.ts
  type Icons (line 6) | enum Icons {
  type IconClass (line 11) | enum IconClass {
  function createScope (line 19) | function createScope(deferred) {
  function show (line 33) | function show(scope, text, type, okText, cancelText) {
  function destroy (line 59) | function destroy() {
  function showToast (line 73) | function showToast({
  function hideToast (line 99) | function hideToast() {
  function updateText (line 103) | function updateText(text: string) {

FILE: quix-frontend/client/src/lib/ui/typings/globals.d.ts
  type Global (line 5) | interface Global {
  type Window (line 15) | interface Window {

FILE: quix-frontend/client/src/lib/ui/typings/turnerjs.d.ts
  class __TurnerComponentDriver__ (line 2) | class __TurnerComponentDriver__ extends TurnerComponentDriver {}
  class TurnerComponentDriver (line 4) | class TurnerComponentDriver extends __TurnerComponentDriver__ {}

FILE: quix-frontend/client/src/lib/viz/directives/chart/chart-renderer.ts
  function getXAxisType (line 6) | function getXAxisType(filter: IFilterData, meta: IMeta) {
  class ChartRenderer (line 14) | class ChartRenderer {
    method constructor (line 17) | constructor(private readonly container) {
    method error (line 21) | public error(e) {
    method draw (line 25) | public draw(data: any[], filteredMeta: IMeta, meta: IMeta, filter: IFi...
    method destroy (line 64) | public destroy() {

FILE: quix-frontend/client/src/lib/viz/directives/chart/chart.ts
  type IScope (line 9) | interface IScope extends angular.IScope {
  function createRenderer (line 21) | function createRenderer(scope: IScope, element) {
  function load (line 25) | function load(scope: IScope, element) {
  function loadAsync (line 34) | function loadAsync(scope, element) {
  method pre (line 51) | pre(scope: IScope, element) {

FILE: quix-frontend/client/src/lib/viz/directives/chart/filter/chart-filter.ts
  type IScope (line 7) | interface IScope {
  method pre (line 30) | pre(scope: IScope, element, attr, ngModel) {

FILE: quix-frontend/client/src/lib/viz/directives/picker/picker.ts
  function getVizTypes (line 9) | function getVizTypes({dimensions, values, all}: IFieldCategories, types:...
  method pre (line 39) | pre(scope, element) {

FILE: quix-frontend/client/src/lib/viz/directives/pie/filter/pie-filter.ts
  type IScope (line 7) | interface IScope {
  method pre (line 30) | pre(scope: IScope, element, attr, ngModel) {

FILE: quix-frontend/client/src/lib/viz/directives/pie/pie-renderer.ts
  class PieRenderer (line 5) | class PieRenderer {
    method constructor (line 8) | constructor(private readonly container) {
    method error (line 12) | public error(e) {
    method draw (line 16) | public draw(data: any[], filteredMeta: IMeta, meta: IMeta, filter: IFi...
    method destroy (line 48) | public destroy() {

FILE: quix-frontend/client/src/lib/viz/directives/pie/pie.ts
  type IScope (line 9) | interface IScope extends angular.IScope {
  function createRenderer (line 21) | function createRenderer(scope: IScope, element) {
  function load (line 25) | function load(scope: IScope, element) {
  function loadAsync (line 34) | function loadAsync(scope, element) {
  method pre (line 51) | pre(scope: IScope, element) {

FILE: quix-frontend/client/src/lib/viz/directives/table/table-renderer.ts
  class TableRenderer (line 4) | class TableRenderer {
    method constructor (line 5) | constructor(private readonly container) {
    method draw (line 9) | public draw(scope, data: BufferedCollection, fields: string[], formatt...

FILE: quix-frontend/client/src/lib/viz/directives/table/table.ts
  type IScope (line 9) | interface IScope extends angular.IScope {
  function load (line 20) | function load(scope: IScope, element) {
  function loadAsync (line 24) | function loadAsync(scope, element) {
  method pre (line 42) | pre(scope: IScope, element) {

FILE: quix-frontend/client/src/lib/viz/directives/viz.ts
  method $init (line 32) | $init() {
  method isVisible (line 39) | isVisible(type) {
  method select (line 42) | select(type) {
  method onSelect (line 50) | onSelect(type) {

FILE: quix-frontend/client/src/lib/viz/init.ts
  function toDirectiveName (line 4) | function toDirectiveName(name: string) {
  function init (line 8) | function init(ngApp: angular.IModule) {

FILE: quix-frontend/client/src/lib/viz/services/chart/chart-conf.ts
  type IData (line 3) | type IData = IInputItem[];
  type IMeta (line 4) | interface IMeta extends IFieldCategories {}
  type IFilterMeta (line 6) | interface IFilterMeta extends IMeta {
  type IFilterData (line 12) | interface IFilterData {
  type IFieldCategories (line 19) | interface IFieldCategories {
  type IRendererData (line 26) | interface IRendererData {

FILE: quix-frontend/client/src/lib/viz/services/chart/chart-data-service.ts
  class ChartData (line 9) | class ChartData extends VizData<IInputItem, IMeta, IData, IFilterData> {
    method constructor (line 10) | constructor(input: IInputItem[], customTransducers?) {
    method filterData (line 17) | filterData(filter: IFilterData) {

FILE: quix-frontend/client/src/lib/viz/services/chart/chart-filter-service.ts
  function getDefaults (line 5) | function getDefaults(filterMeta: IFilterMeta, fields: string[]): IFilter...
  class ChartFilter (line 28) | class ChartFilter extends VizFilter<IMeta, IFilterMeta, IFilterData> {
    method constructor (line 29) | constructor(private readonly fields: string[], private readonly xMeta:...
    method createMeta (line 33) | protected createMeta(meta: IMeta, filteredMeta: IMeta): IFilterMeta {
    method createData (line 45) | protected createData(filterMeta: IFilterMeta): IFilterData {

FILE: quix-frontend/client/src/lib/viz/services/chart/chart-viz-service.ts
  class ChartViz (line 7) | class ChartViz extends Viz<IInputItem, IMeta, IData, IMeta, IFilterData> {
    method constructor (line 8) | constructor (data: IInputItem[], renderer: IRenderer<IMeta, IData, IFi...

FILE: quix-frontend/client/src/lib/viz/services/viz-conf.ts
  type IInputItem (line 1) | interface IInputItem {
  type IRenderer (line 5) | interface IRenderer<Meta, Data, FilterData> {

FILE: quix-frontend/client/src/lib/viz/services/viz-data-service.ts
  type ITransducers (line 4) | interface ITransducers<Input, Data, Meta, FilterData> {
  type ICustomTransducers (line 11) | interface ICustomTransducers<Meta> {
  function transduce (line 16) | function transduce<Input, Data, Meta, FilterData>(
  class VizData (line 38) | class VizData<Input, Meta, Data, FilterData> {
    method constructor (line 45) | constructor(
    method getMeta (line 80) | public getMeta(): Meta {
    method getFilteredMeta (line 84) | public getFilteredMeta(): Meta {
    method getFilteredData (line 88) | public getFilteredData(): Data {
    method filterInput (line 92) | public filterInput(filter: FilterData, customInputFilterTransducer: (f...
    method filterData (line 102) | public filterData(filter: FilterData, dataFilter?: (data: Data, filter...

FILE: quix-frontend/client/src/lib/viz/services/viz-filter-service.ts
  method init (line 10) | init(meta: Meta, filteredMeta: Meta): VizFilter<Meta, FilterMeta, Filter...
  method getMeta (line 17) | getMeta(): FilterMeta {
  method getData (line 21) | getData(): FilterData {

FILE: quix-frontend/client/src/lib/viz/services/viz-service.ts
  class Viz (line 5) | class Viz<InputItem, Meta, Data, FilterMeta, FilterData> {
    method constructor (line 6) | constructor (
    method initFilter (line 12) | private initFilter() {
    method getFilter (line 16) | getFilter() {
    method filterInput (line 20) | filterInput(filterTransducer?: (filter: FilterData, meta: Meta) => any...
    method filterData (line 26) | filterData(dataFilter?: (data: Data, filter: FilterData, meta: Meta) =...
    method filter (line 32) | filter(): Viz<InputItem, Meta, Data, FilterMeta, FilterData> {
    method draw (line 42) | draw(): Viz<InputItem, Meta, Data, FilterMeta, FilterData> {
    method destroy (line 48) | destroy() {

FILE: quix-frontend/client/src/lib/viz/transducers/chart/chart-input-filter-transducer.ts
  function sortByContext (line 9) | function sortByContext(filter: IFilterData, meta: IMeta) {

FILE: quix-frontend/client/src/lib/viz/transducers/chart/chart-meta-transducer.ts
  class Meta (line 5) | class Meta {
    method constructor (line 15) | constructor(private readonly xform) {
    method '@@transducer/result' (line 19) | '@@transducer/result'() {
    method '@@transducer/step' (line 23) | '@@transducer/step'(res, input: IInputItem, index) {

FILE: quix-frontend/client/src/lib/viz/transducers/parse-dates-transducer.ts
  class ParseDates (line 4) | class ParseDates {
    method constructor (line 5) | constructor(private readonly fields: string[], private readonly xform) {
    method '@@transducer/result' (line 9) | '@@transducer/result'(v) {
    method '@@transducer/step' (line 13) | '@@transducer/step'(res, input: IInputItem) {

FILE: quix-frontend/client/src/lib/viz/transducers/parse-floats-transducer.ts
  class ParseFloats (line 3) | class ParseFloats {
    method constructor (line 4) | constructor(private readonly fields: string[], private readonly xform) {
    method '@@transducer/result' (line 8) | '@@transducer/result'(v) {
    method '@@transducer/step' (line 12) | '@@transducer/step'(res, input: IInputItem) {

FILE: quix-frontend/client/src/lib/viz/transducers/sort-transducer.ts
  class Sort (line 4) | class Sort {
    method constructor (line 5) | constructor(private readonly fn, private readonly xform) {
    method '@@transducer/result' (line 9) | '@@transducer/result'(v) {
    method '@@transducer/step' (line 13) | '@@transducer/step'(res, input: IInputItem) {

FILE: quix-frontend/client/src/lib/viz/transducers/ungroup-transducer.ts
  type IUngroupConf (line 4) | interface IUngroupConf {
  class Ungroup (line 10) | class Ungroup {
    method constructor (line 14) | constructor(private readonly conf: IUngroupConf, private readonly xfor...
    method '@@transducer/result' (line 18) | '@@transducer/result'(v) {
    method '@@transducer/step' (line 22) | '@@transducer/step'(res, input: IInputItem) {

FILE: quix-frontend/client/src/lib/viz/utils/utils.ts
  function percentage (line 1) | function percentage(what: number, of: number): number {
  function normalize (line 5) | function normalize(value, maxValue, min, max): number {

FILE: quix-frontend/client/src/lib/web-worker-infra/types.ts
  type RQRSConstraint (line 2) | interface RQRSConstraint {
  type RqtoRSConstraint (line 5) | type RqtoRSConstraint<RQ, RS> = {[K in keyof RQ]: keyof RS};
  type RequestMsgTypes (line 8) | type RequestMsgTypes<RQ> = keyof RQ;
  type ResponseMsgTypes (line 9) | type ResponseMsgTypes<RS> = keyof RS;
  type AllMsgTypes (line 10) | type AllMsgTypes<RQ, RS> = keyof RQ | keyof RS;
  type RequestTypeToResponseTypeMap (line 11) | type RequestTypeToResponseTypeMap<RQ, RS, RQtoRs extends RqtoRSConstrain...
  type WorkerFunctionsMap (line 15) | type WorkerFunctionsMap<RQ, RS, RQtoRs extends RqtoRSConstraint<RQ, RS>>...
  type WorkerMsgT (line 22) | interface WorkerMsgT<RQ, RS, T extends RequestMsgTypes<RQ> | ResponseMsg...
  type WorkerResponse (line 35) | type WorkerResponse<RQ, RS> = {
  type WorkerResponseData (line 39) | type WorkerResponseData<RQ, RS> = RS[keyof RS];
  type WorkerRequest (line 41) | type WorkerRequest<RQ, RS> = {
  type WorkerResponseDataT (line 46) | type WorkerResponseDataT<
  type WorkerRequestT (line 53) | type WorkerRequestT<RQ, RS, T extends RequestMsgTypes<RQ>> = WorkerMsgT<...
  type WorkerResponseT (line 54) | type WorkerResponseT<RQ, RS, T extends ResponseMsgTypes<RS>> = WorkerMsg...
  type WorkerClientMessageEvent (line 57) | interface WorkerClientMessageEvent<RQ, RS> extends MessageEvent {
  type WorkerClient (line 60) | interface WorkerClient<RQ, RS> extends Worker {
  type WorkerMessageEvent (line 66) | interface WorkerMessageEvent<RQ, RS> extends MessageEvent {
  type TypedWorker (line 70) | interface TypedWorker<RQ, RS> extends DedicatedWorkerGlobalScope {

FILE: quix-frontend/client/src/lib/web-worker-infra/web-worker-manager/index.ts
  function XHRWorker (line 13) | function XHRWorker(url, maxAge?): Promise<Worker> {
  type Omit (line 30) | type Omit<T, K> = Pick<T, Exclude<keyof T, K>>;
  class TypedWorkerManager (line 32) | class TypedWorkerManager<
    method constructor (line 40) | constructor(private readonly worker: WorkerClient<RQ, RS>) {
    method sendMsg (line 53) | protected sendMsg<T extends RequestMsgTypes<RQ>>(
    method createFromUrl (line 63) | static async createFromUrl<

FILE: quix-frontend/client/src/lib/web-worker-infra/web-worker/index.ts
  function TypedWorkerFactory (line 12) | function TypedWorkerFactory<

FILE: quix-frontend/client/src/plugins/db/athena-db-plugin.ts
  class AthenaDbPlugin (line 8) | class AthenaDbPlugin extends DbPlugin {
    method constructor (line 9) | constructor(app: App, name: string, hooks: any) {
    method getSampleQuery (line 13) | getSampleQuery(table: IFile) {

FILE: quix-frontend/client/src/plugins/db/bigquery-db-plugin.ts
  class BigQueryDbPlugin (line 6) | class BigQueryDbPlugin extends DbPlugin {
    method constructor (line 7) | constructor(app: App, name: string, hooks: any) {
    method getSampleQuery (line 11) | getSampleQuery(table: IFile) {

FILE: quix-frontend/client/src/plugins/db/jdbc-db-plugin.ts
  class JdbcDbPlugin (line 7) | class JdbcDbPlugin extends DbPlugin {
    method constructor (line 8) | constructor(app: App, name: string, hooks: any) {
    method getSampleQuery (line 12) | getSampleQuery(table: IFile) {

FILE: quix-frontend/client/src/plugins/db/presto-db-plugin.ts
  class PrestoDbPlugin (line 7) | class PrestoDbPlugin extends DbPlugin {
    method constructor (line 8) | constructor(app: App, name: string, hooks: any) {
    method getSampleQuery (line 12) | getSampleQuery(table: IFile) {

FILE: quix-frontend/client/src/plugins/note/athena-note-plugin.ts
  class AthenaNotePlugin (line 5) | class AthenaNotePlugin extends NotePlugin {
    method constructor (line 6) | constructor(app: App, name: string, hooks: any) {

FILE: quix-frontend/client/src/plugins/note/bigquery-note-plugin.ts
  class BigQueryNotePlugin (line 6) | class BigQueryNotePlugin extends NotePlugin {
    method constructor (line 7) | constructor(app: App, name: string, hooks: any) {
    method formatStats (line 15) | formatStats(stats: {[key: string]: any}) {

FILE: quix-frontend/client/src/plugins/note/default-note-plugin.ts
  class DefaultNotePlugin (line 4) | class DefaultNotePlugin extends NotePlugin {
    method constructor (line 5) | constructor(app) {

FILE: quix-frontend/client/src/plugins/note/jdbc-note-plugin.ts
  class JdbcNotePlugin (line 5) | class JdbcNotePlugin extends NotePlugin {
    method constructor (line 6) | constructor(app: App, name: string, hooks: any) {

FILE: quix-frontend/client/src/plugins/note/presto-note-plugin.ts
  class PrestoNotePlugin (line 5) | class PrestoNotePlugin extends NotePlugin {
    method constructor (line 6) | constructor(app: App, name: string, hooks: any) {

FILE: quix-frontend/client/src/plugins/note/python-note-plugin.ts
  class PythonNotePlugin (line 5) | class PythonNotePlugin extends NotePlugin {
    method constructor (line 6) | constructor(app: App, name: string, hooks: any) {
    method renderRunner (line 13) | renderRunner() {

FILE: quix-frontend/client/src/plugins/plugin-factory.ts
  method db (line 7) | db(app: App, store: Store, id: string, engine: string, noteHooks: any) {
  method note (line 22) | note(app: App, store: Store, id: string, engine: string, noteHooks: any) {

FILE: quix-frontend/client/src/react-components/file-explorer/FileExplorerComponent.tsx
  constant EXPAND_ALL_NODES_LIMIT (line 7) | const EXPAND_ALL_NODES_LIMIT = 3000;
  type MenuOptionProps (line 9) | interface MenuOptionProps {
  type FileExplorerProps (line 14) | interface FileExplorerProps {
  type Tree (line 25) | interface Tree {

FILE: quix-frontend/client/src/react-components/file-explorer/TreeItem.tsx
  type Node (line 6) | interface Node {
  type TreeItemProps (line 18) | interface TreeItemProps {
  function TreeItemPropsAreEqual (line 171) | function TreeItemPropsAreEqual(prevProps, nextProps) {

FILE: quix-frontend/client/src/react-components/file-explorer/TreeItemMenu.tsx
  type TreeItemMenuProps (line 4) | interface TreeItemMenuProps {

FILE: quix-frontend/client/src/react-components/file-explorer/file-explorer-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class FileExplorerTestkit (line 12) | class FileExplorerTestkit extends Testkit {
    method toggleFileExplorerTab (line 13) | async toggleFileExplorerTab() {
    method numOfTreeItems (line 17) | async numOfTreeItems() {
    method numOfLoadingTreeItems (line 21) | async numOfLoadingTreeItems() {
    method numOfOpenedTreeItems (line 25) | async numOfOpenedTreeItems() {
    method numOfClosedTreeItems (line 29) | async numOfClosedTreeItems() {
    method clickOnTreeItemByPosition (line 33) | async clickOnTreeItemByPosition(position: number) {
    method getTreeItemIndexByName (line 37) | async getTreeItemIndexByName(name: string) {
    method isTreeItemExistsByName (line 46) | async isTreeItemExistsByName(name: string) {
    method clickOnItemByName (line 51) | async clickOnItemByName(name: string) {
    method search (line 56) | async search(query: string) {

FILE: quix-frontend/client/src/services/dialog.ts
  function contextText (line 5) | function contextText(context: any, type: string) {
  function confirmActionTitle (line 13) | function confirmActionTitle(action: string, type: string): string {
  function actionText (line 24) | function actionText(action: string) {
  function confirmHtml (line 35) | function confirmHtml(

FILE: quix-frontend/client/src/services/hooks/use-view-state.ts
  type ViewStateActions (line 3) | interface ViewStateActions<S, D> {

FILE: quix-frontend/client/src/services/notifications.ts
  type INotificationTemplate (line 3) | interface INotificationTemplate {
  class BrowserNotificationsManager (line 13) | class BrowserNotificationsManager {
    method constructor (line 18) | constructor() {
    method fixUrl (line 24) | private fixUrl(url: string) {
    method setStaticsBaseUrl (line 28) | setStaticsBaseUrl(staticsBaseUrl: string) {
    method register (line 32) | register(template: INotificationTemplate) {
    method notify (line 36) | notify(templateName: string, ...args: any[]) {

FILE: quix-frontend/client/src/services/permissions.ts
  type IPermissions (line 5) | interface IPermissions {
  type IFolderPermissions (line 15) | interface IFolderPermissions extends IPermissions{
  type INotebookPermissions (line 20) | interface INotebookPermissions extends IPermissions{

FILE: quix-frontend/client/src/services/plugins/plugin-manager.ts
  class PluginManager (line 6) | class PluginManager<H> {
    method constructor (line 9) | constructor(private readonly pluginFactory: any, public readonly hooks...
    method getPluginById (line 11) | private getPluginById<T extends TModuleComponentType>(
    method getPluginsByType (line 22) | private getPluginsByType<T extends TModuleComponentType>(
    method module (line 30) | module<T extends TModuleComponentType>(type: T) {

FILE: quix-frontend/client/src/services/plugins/plugin-types.ts
  type CustomAction (line 6) | interface CustomAction {
  class Plugin (line 21) | class Plugin {
    method constructor (line 22) | constructor(
    method getId (line 29) | public getId() {
    method getEngine (line 33) | public getEngine() {
  class NotePlugin (line 38) | class NotePlugin extends Plugin {
    method constructor (line 39) | constructor(
    method getConfig (line 56) | getConfig() {
    method formatStats (line 60) | formatStats(stats: {[key: string]: any}) {
    method renderRunner (line 64) | renderRunner() {
    method getCustomActions (line 103) | getCustomActions(): CustomAction[] {
  class DbPlugin (line 123) | class DbPlugin extends Plugin {
    method constructor (line 124) | constructor(app: App, id: string, engine: ModuleEngineType, hooks: any) {
    method getSampleQuery (line 128) | getSampleQuery(table: IFile): string {
  type TPluginMap (line 138) | type TPluginMap = {

FILE: quix-frontend/client/src/services/popup.ts
  method onLoad (line 21) | onLoad(instance) {
  method onToggle (line 24) | onToggle(maximized: boolean) {

FILE: quix-frontend/client/src/services/scope.ts
  function initEvents (line 4) | function initEvents(scope, conf, app, store: Store, events) {

FILE: quix-frontend/client/src/services/state.ts
  class State (line 6) | class State {
    method constructor (line 7) | constructor(public index: number = -1) {}
  class StateManager (line 10) | class StateManager<E> {
    method constructor (line 14) | constructor(private readonly states: E) {
    method is (line 18) | is(state: keyof E) {
    method before (line 22) | before(state: keyof E) {
    method after (line 26) | after(state: keyof E) {
    method get (line 30) | get() {
    method set (line 34) | set(state: keyof E, condition: boolean | Function = true, value: Recor...
    method force (line 45) | force(state: keyof E, condition: boolean | Function = true, value: Rec...
    method value (line 56) | value(val?: Record<string, any> | Function) {
    method then (line 66) | then(fn: Function) {
    method else (line 71) | else(fn: Function) {
  class NullStateManager (line 76) | class NullStateManager {
    method is (line 77) | is() {
    method before (line 80) | before() {
    method after (line 83) | after() {
    method set (line 86) | set() {
    method value (line 89) | value() {
    method then (line 92) | then() {
    method else (line 95) | else(fn: Function) {

FILE: quix-frontend/client/src/state-components/embed/embed.ts
  method onEnter (line 16) | onEnter() {

FILE: quix-frontend/client/src/state-components/embed/note/embed-note-reactions.ts
  function setError (line 3) | function setError(scope: ng.IScope, error: any) {
  function setNote (line 7) | function setNote(scope: ng.IScope, note: INote) {

FILE: quix-frontend/client/src/state-components/embed/note/embed-note-vm.ts
  type States (line 4) | enum States {
  method $init (line 11) | $init() {

FILE: quix-frontend/client/src/state-components/favorites/FavoritesComponent.tsx
  type FavoritesProps (line 9) | interface FavoritesProps {
  function Favorites (line 24) | function Favorites(props: FavoritesProps) {

FILE: quix-frontend/client/src/state-components/favorites/favorites-table-fields.tsx
  method filter (line 11) | filter(_, file: IFile) {
  method filter (line 23) | filter(_, file: IFile) {
  method filter (line 30) | filter(_, file: IFile) {

FILE: quix-frontend/client/src/state-components/favorites/favorites-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class FavoritesTestkit (line 7) | class FavoritesTestkit extends TableTestkit {

FILE: quix-frontend/client/src/state-components/files/files-reactions.ts
  function setFolder (line 5) | function setFolder(scope: IScope, folder: IFolder) {
  function setFiles (line 18) | function setFiles(scope: IScope, files: IFile[]) {
  function setError (line 25) | function setError(scope: IScope, error: any) {
  function setMarkedMap (line 29) | function setMarkedMap(scope: IScope, markedMap: Record<string, IFile>) {
  function setMarkedList (line 33) | function setMarkedList(scope: IScope, markedList: IFile[]) {

FILE: quix-frontend/client/src/state-components/files/files-table-fields.ts
  method filter (line 11) | filter(_, file, index, compile) {
  method sort (line 36) | sort(_, file) {
  method filter (line 39) | filter(_, file: IFile, index, compile) {
  method filter (line 59) | filter(_, file: IFile, index, compile) {
  method filter (line 66) | filter(_, file: IFile, index, compile) {

FILE: quix-frontend/client/src/state-components/files/files-testkit.ts
  type Hooks (line 5) | const enum Hooks {
  class FilesTestkit (line 13) | class FilesTestkit extends Testkit {
    method getBreadcrumbsTestkit (line 14) | async getBreadcrumbsTestkit() {
    method getActionsTestkit (line 18) | async getActionsTestkit() {
    method hasEmptyState (line 22) | async hasEmptyState() {
    method hasErrorState (line 26) | async hasErrorState() {
    method hasContent (line 30) | async hasContent() {
    method clickAddFolder (line 34) | async clickAddFolder() {
    method clickAddNotebook (line 38) | async clickAddNotebook() {
    method clickFile (line 42) | async clickFile(index) {
    method numOfFiles (line 46) | async numOfFiles() {
    method isAddFolderEnabled (line 50) | async isAddFolderEnabled() {
    method isAddNotebookEnabled (line 54) | async isAddNotebookEnabled() {
    method isBulkSelectEnabled (line 58) | async isBulkSelectEnabled() {

FILE: quix-frontend/client/src/state-components/files/files-types.ts
  type IScope (line 1) | interface IScope extends angular.IScope {

FILE: quix-frontend/client/src/state-components/files/files-vm.ts
  type States (line 3) | enum States {
  method $init (line 14) | $init() {

FILE: quix-frontend/client/src/state-components/history/HistoryComponent.tsx
  type HistoryProps (line 16) | interface HistoryProps {
  constant CHUNK_SIZE (line 24) | const CHUNK_SIZE = 100;
  function History (line 40) | function History(props: HistoryProps) {

FILE: quix-frontend/client/src/state-components/history/history-table-fields.tsx
  method filter (line 12) | filter(_, history: IHistory, index, highlight) {
  method filter (line 19) | filter(_, history: IHistory, index, highlight) {
  method filter (line 33) | filter(_, history: IHistory, index, highlight) {
  method filter (line 44) | filter(_, history: IHistory, index) {

FILE: quix-frontend/client/src/state-components/history/history-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class HistoryTestkit (line 10) | class HistoryTestkit extends TableTestkit {

FILE: quix-frontend/client/src/state-components/home/HomeComponent.tsx
  type HomeProps (line 4) | interface HomeProps {
  function Home (line 13) | function Home(props: HomeProps) {

FILE: quix-frontend/client/src/state-components/home/home-testkit.ts
  class HomeTestkit (line 3) | class HomeTestkit extends Testkit {
    method hasNotebooksAction (line 4) | async hasNotebooksAction() {
    method hasAddNotebookAction (line 8) | async hasAddNotebookAction() {
    method clickNotebooks (line 12) | async clickNotebooks() {
    method clickExamples (line 16) | async clickExamples() {
    method clickAddNotebook (line 20) | async clickAddNotebook() {

FILE: quix-frontend/client/src/state-components/home/home.ts
  method onNotebooksClick (line 23) | onNotebooksClick() {
  method onNotebookAdd (line 26) | onNotebookAdd() {
  method onExamplesClick (line 30) | onExamplesClick() {

FILE: quix-frontend/client/src/state-components/notebook/notebook-reactions.ts
  function setNotebook (line 4) | function setNotebook(scope: IScope, notebook: INotebook) {
  function setError (line 19) | function setError(scope: IScope, error: any) {
  function setNotes (line 23) | function setNotes(scope: IScope, notes: INote[]) {
  function setHasChanges (line 33) | function setHasChanges(scope: IScope, hasChanges: boolean) {
  function setSaving (line 37) | function setSaving(scope: IScope, saving: boolean) {
  function setMarkedMap (line 41) | function setMarkedMap(scope: IScope, markedMap: Record<string, INote>) {
  function setMarkedList (line 45) | function setMarkedList(scope: IScope, markedList: INote[]) {
  function setNote (line 50) | function setNote(scope: IScope, note: INote) {

FILE: quix-frontend/client/src/state-components/notebook/notebook-testkit.ts
  type Hooks (line 6) | const enum Hooks {
  class NotebookTestkit (line 15) | class NotebookTestkit extends Testkit {
    method getBreadcrumbsTestkit (line 16) | async getBreadcrumbsTestkit() {
    method getActionsTestkit (line 20) | async getActionsTestkit() {
    method getNoteTestkit (line 24) | async getNoteTestkit(index: number) {
    method hasEmptyState (line 28) | async hasEmptyState() {
    method hasErrorState (line 32) | async hasErrorState() {
    method hasNotes (line 37) | async hasNotes() {
    method clickAddNote (line 41) | async clickAddNote() {
    method clickAddNoteDropdown (line 45) | async clickAddNoteDropdown() {
    method numOfNotes (line 49) | async numOfNotes() {
    method isAddNoteEnabled (line 53) | async isAddNoteEnabled() {

FILE: quix-frontend/client/src/state-components/notebook/notebook-types.ts
  type IScope (line 3) | interface IScope extends angular.IScope {

FILE: quix-frontend/client/src/state-components/notebook/notebook-vm.ts
  type States (line 5) | enum States {
  method $init (line 20) | $init() {

FILE: quix-frontend/client/src/state-components/trash-bin/TrashBinComponent.tsx
  type TrashBinProps (line 12) | interface TrashBinProps {

FILE: quix-frontend/client/src/state-components/trash-bin/trash-bin-events.ts
  function successToast (line 60) | function successToast(text: string) {

FILE: quix-frontend/client/src/state-components/trash-bin/trash-bin-table-fields.tsx
  method filter (line 15) | filter(_, deletedNotebook: IDeletedNotebook) {
  method filter (line 27) | filter(_, deletedNotebook: IDeletedNotebook) {
  method filter (line 39) | filter(_, deletedNotebook: IDeletedNotebook) {

FILE: quix-frontend/client/src/state-components/users/UsersComponent.tsx
  type UsersProps (line 14) | interface UsersProps {
  constant CHUNK_SIZE (line 20) | const CHUNK_SIZE = 100;
  function Users (line 38) | function Users(props: UsersProps) {

FILE: quix-frontend/client/src/state-components/users/users-table-fields.tsx
  method filter (line 11) | filter(_, user: IUser, index) {
  method filter (line 18) | filter(_, user: IUser, index, highlight) {
  method filter (line 29) | filter(_, user: IUser, index) {
  method filter (line 40) | filter(_, user: IUser, index) {

FILE: quix-frontend/client/src/state-components/users/users-testkit.ts
  type Hooks (line 3) | const enum Hooks {
  class UsersTestkit (line 8) | class UsersTestkit extends TableTestkit {

FILE: quix-frontend/client/src/store/app/app-branch.ts
  type IApp (line 8) | interface IApp {

FILE: quix-frontend/client/src/store/db/db-branch.ts
  function db (line 6) | function db(state: any[] = null, action) {

FILE: quix-frontend/client/src/store/files/files-branch.ts
  type IPermissions (line 10) | interface IPermissions {

FILE: quix-frontend/client/src/store/folder/folder-branch.ts
  type IView (line 17) | interface IView {

FILE: quix-frontend/client/src/store/notebook/notebook-branch.ts
  type IQueue (line 16) | interface IQueue {
  type IView (line 21) | interface IView {

FILE: quix-frontend/client/test/dev/server.ts
  function start (line 11) | function start(port = process.env.PORT || '3000') {

FILE: quix-frontend/client/test/dev/vm.ts
  function loadData (line 4) | function loadData(file) {
  function renderVM (line 12) | function renderVM(template, data) {

FILE: quix-frontend/client/test/e2e/dbExplorer.e2e.ts
  constant COMPONENT_ANIMATION_TIME (line 7) | const COMPONENT_ANIMATION_TIME = 350;

FILE: quix-frontend/client/test/e2e/driver.ts
  constant WAIT_TIMEOUT (line 6) | const WAIT_TIMEOUT = 5000;
  class Driver (line 40) | class Driver {
    method init (line 50) | async init() {
    method goto (line 64) | goto(state: string) {
    method sleep (line 68) | sleep(ms: number) {
    method execute (line 72) | execute(fn: Function) {
    method createTestkit (line 76) | createTestkit<T extends Class<any>>(TestkitCtor: T): InstanceType<T> {
  class Mock (line 81) | class Mock {
    method constructor (line 82) | constructor () {}
    method http (line 84) | async http(pattern: string, payload: any, options?: {}) {
    method reset (line 94) | async reset() {
    method wsBroadcast (line 98) | async wsBroadcast(message: any) {
  class URL (line 111) | class URL {
    method constructor (line 112) | constructor (private readonly page: Page) {}
    method matches (line 114) | async matches(pattern: string) {
  class Query (line 126) | class Query {
    method constructor (line 127) | constructor (private readonly page: Page) {}
    method hook (line 129) | async hook(hook: string, pseudoClass: string = '') {
    method hooks (line 133) | async hooks(hook: string, pseudoClass: string = '') {
    method attr (line 137) | async attr(attr: string, pseudoClass: string = '') {
    method attrs (line 141) | async attrs(attr: string, pseudoClass: string = '') {
    method $ (line 145) | async $(selector: string) {
    method $$ (line 149) | async $$(selector: string) {
  class Click (line 154) | class Click {
    method constructor (line 155) | constructor (private readonly page: Page) {}
    method hook (line 157) | async hook(hook: string, pseudoClass: string = '') {
    method attr (line 165) | async attr(attr: string, pseudoClass: string = '') {
    method $ (line 173) | async $(selector: string) {
  class Evaluate (line 182) | class Evaluate {
    method constructor (line 183) | constructor (private readonly page: Page) {}
    method hook (line 185) | async hook(hook: string, fn: (element: Element) => any) {
    method hooks (line 189) | async hooks(hook: string, fn: (element: Element[], args) => any, args ...
    method attr (line 193) | async attr(attr: string, fn: (element: Element) => any) {
    method attrs (line 197) | async attrs(attr: string, fn: (element: Element[]) => any) {
    method $ (line 201) | async $(selector: string, fn: (element: Element) => any) {
    method $$ (line 205) | async $$(selector: string, fn: (element: Element[]) => any) {
  class Log (line 210) | class Log {
    method constructor (line 211) | constructor (private readonly page: Page) {}
    method url (line 213) | async url() {
    method html (line 218) | async html() {
  class Keyboard (line 223) | class Keyboard {
    method constructor (line 224) | constructor (private readonly page: Page) {}
    method type (line 226) | type(hook: string, value: string) {
  class Testkit (line 231) | class Testkit {
    method constructor (line 237) | constructor(pageOrElement: Page | ElementHandle) {

FILE: quix-frontend/service/scripts/helpers/copy-statics.ts
  function buildAndCopyStatics (line 4) | function buildAndCopyStatics(projectDir: string, clientDir: string) {

FILE: quix-frontend/service/scripts/start.ts
  function main (line 5) | async function main() {

FILE: quix-frontend/service/scripts/update-statics.ts
  function main (line 4) | function main() {

FILE: quix-frontend/service/src/app.controller.spec.ts
  function preTest (line 16) | async function preTest(mocked?: ValueProvider) {

FILE: quix-frontend/service/src/app.controller.ts
  class AppController (line 16) | class AppController implements OnApplicationShutdown {
    method constructor (line 20) | constructor(
    method onApplicationShutdown (line 31) | onApplicationShutdown() {
    method fetchClientConfig (line 35) | private fetchClientConfig() {
    method getIndex (line 41) | getIndex() {
    method healthCheck (line 57) | async healthCheck(@Res() response: Response) {

FILE: quix-frontend/service/src/app.module.ts
  class AppModule (line 37) | class AppModule {}

FILE: quix-frontend/service/src/base.module.ts
  class BaseModule (line 46) | class BaseModule { }

FILE: quix-frontend/service/src/common/demo-mode-interceptor.ts
  class DemoModeInterceptor (line 16) | class DemoModeInterceptor implements NestInterceptor {
    method constructor (line 18) | constructor(private configService: ConfigService) {
    method intercept (line 21) | intercept(context: ExecutionContext, next: CallHandler): Observable<an...
  function removeOwnerNested (line 30) | function removeOwnerNested(user: string, item: any): any {

FILE: quix-frontend/service/src/common/entity-type.enum.ts
  type EntityType (line 1) | enum EntityType {

FILE: quix-frontend/service/src/config/config.module.ts
  class ConfigModule (line 21) | class ConfigModule {
    method create (line 22) | static create(overrides: Partial<EnvSettings> = {}): DynamicModule {

FILE: quix-frontend/service/src/config/config.service.ts
  type DbTypes (line 7) | type DbTypes = 'mysql' | 'sqlite';
  method constructor (line 14) | constructor(
  method getEnvSettings (line 23) | getEnvSettings(): EnvSettings {
  method getDbType (line 27) | getDbType(): DbTypes {
  method getDbConnection (line 32) | getDbConnection(entities: any[]): ConnectionOptions {
  method getClientConfig (line 42) | getClientConfig() {
  class DefaultConfigService (line 78) | class DefaultConfigService extends ConfigService {}

FILE: quix-frontend/service/src/config/db-conf.ts
  type DbColumnConf (line 9) | interface DbColumnConf {
  method fullTextSearch (line 76) | fullTextSearch(columnName, contentSearchList) {
  method fullTextSearch (line 161) | fullTextSearch(columnName, contentSearchList) {

FILE: quix-frontend/service/src/config/db-connection.ts
  type ClassConstructor (line 5) | type ClassConstructor = new (...args: any[]) => any;

FILE: quix-frontend/service/src/config/env/types.ts
  type StaticSettings (line 4) | type StaticSettings = typeof envSettingsDefaults;
  type ComputedSettings (line 5) | interface ComputedSettings {
  type EnvSettings (line 16) | type EnvSettings = StaticSettings & ComputedSettings;

FILE: quix-frontend/service/src/config/utils.ts
  function isJestTest (line 1) | function isJestTest() {
  function isTsNode (line 5) | function isTsNode() {

FILE: quix-frontend/service/src/consts.ts
  constant QUIX_SCHEMA (line 1) | const QUIX_SCHEMA = `QUIX_SCHEMA`;
  constant CURRENT_QUIX_SCHEMA_VERSION (line 2) | const CURRENT_QUIX_SCHEMA_VERSION = 5;

FILE: quix-frontend/service/src/entities/deleted-notebook/dbdeleted-notebook.entity.ts
  class DbDeletedNotebook (line 19) | class DbDeletedNotebook {
    method constructor (line 51) | constructor(base?: DbDeletedNotebook) {

FILE: quix-frontend/service/src/entities/deleted-notebook/deleted-notebook.repository.ts
  class DeletedNotebookRepository (line 5) | class DeletedNotebookRepository extends Repository<DbDeletedNotebook> {}

FILE: quix-frontend/service/src/entities/favorites/favorites.entity.ts
  class DbFavorites (line 7) | class DbFavorites {

FILE: quix-frontend/service/src/entities/filenode/filenode.entity.ts
  class DbFileTreeNode (line 19) | class DbFileTreeNode {
    method constructor (line 20) | constructor(id?: string, rest: Partial<DbFileTreeNode> = {}) {

FILE: quix-frontend/service/src/entities/filenode/filenode.repository.ts
  class FileTreeRepository (line 20) | class FileTreeRepository extends Repository<DbFileTreeNode> {
    method save (line 33) | async save(
    method getParentPath (line 50) | private async getParentPath(item: DeepPartial<DbFileTreeNode>) {
    method setMpathByParent (line 71) | private async setMpathByParent(item: DeepPartial<DbFileTreeNode>) {
    method getNamesByIds (line 80) | getNamesByIds(ids: string[]) {
    method getChildren (line 99) | async getChildren(rootId: string) {
    method getDeepChildren (line 111) | async getDeepChildren(root: DbFileTreeNode, entityManager?: EntityMana...
    method moveTree (line 124) | async moveTree(root: DbFileTreeNode, newParentNode: DbFileTreeNode) {
    method deleteTree (line 156) | async deleteTree(root: DbFileTreeNode) {
  function getParentId (line 200) | function getParentId(node: DeepPartial<DbFileTreeNode>) {

FILE: quix-frontend/service/src/entities/folder/folder.entity.ts
  class DbFolder (line 11) | class DbFolder {

FILE: quix-frontend/service/src/entities/note/dbnote.entity.ts
  class DbNote (line 15) | class DbNote {
    method constructor (line 58) | constructor(base?: DbNote) {

FILE: quix-frontend/service/src/entities/note/note.repository.ts
  class NoteRepository (line 5) | class NoteRepository extends Repository<DbNote> {
    method insertNewWithRank (line 6) | async insertNewWithRank(note: DbNote) {
    method deleteOneAndOrderRank (line 12) | async deleteOneAndOrderRank(item: string | DbNote) {
    method reorder (line 30) | async reorder(note: DbNote, to: number) {

FILE: quix-frontend/service/src/entities/notebook/dbnotebook.entity.ts
  class DbNotebook (line 20) | class DbNotebook {
    method constructor (line 51) | constructor(base?: DbNotebook) {

FILE: quix-frontend/service/src/entities/notebook/notebook.repository.ts
  class NotebookRepository (line 5) | class NotebookRepository extends Repository<DbNotebook> {}

FILE: quix-frontend/service/src/entities/user/user.entity.ts
  class DbUser (line 12) | class DbUser {
    method constructor (line 34) | constructor(base: Partial<DbUser>) {

FILE: quix-frontend/service/src/entities/utils.ts
  type IMaybeHasOwnerDetails (line 14) | interface IMaybeHasOwnerDetails {

FILE: quix-frontend/service/src/entities/version-metadata.entity.ts
  class DbMetadata (line 5) | class DbMetadata {
    method constructor (line 18) | constructor(name: string, version: number, jsonContent = {}) {

FILE: quix-frontend/service/src/errors/exceptions.ts
  type Ctor (line 1) | type Ctor = new (...args: any[]) => any;
  class ItemNotFoundT (line 3) | class ItemNotFoundT extends Error {
    method constructor (line 5) | constructor(type: Ctor | string, private id: string) {
  class BadActionT (line 20) | class BadActionT extends Error {
    method constructor (line 21) | constructor(type: string, customMsg: string) {

FILE: quix-frontend/service/src/main.ts
  function bootstrap (line 20) | async function bootstrap() {

FILE: quix-frontend/service/src/migrations/1558528771647-v1.ts
  class v11558528771647 (line 4) | class v11558528771647 implements MigrationInterface {
    method up (line 6) | public async up(queryRunner: QueryRunner): Promise<any> {
    method down (line 21) | public async down(queryRunner: QueryRunner): Promise<any> {

FILE: quix-frontend/service/src/migrations/1558528771648-v1-metadata.ts
  constant PREVIOUS_QUIX_SCHEMA (line 4) | const PREVIOUS_QUIX_SCHEMA = 0;
  constant CURRENT_QUIX_SCHEMA_VERSION (line 5) | const CURRENT_QUIX_SCHEMA_VERSION = 1;
  class VersionMetadata1558528771648 (line 7) | class VersionMetadata1558528771648 implements MigrationInterface {
    method up (line 8) | public async up(queryRunner: QueryRunner): Promise<any> {
    method down (line 14) | public async down(queryRunner: QueryRunner): Promise<any> {

FILE: quix-frontend/service/src/migrations/1562174176877-v2.ts
  constant PREVIOUS_QUIX_SCHEMA (line 4) | const PREVIOUS_QUIX_SCHEMA = 1;
  constant CURRENT_QUIX_SCHEMA_VERSION (line 5) | const CURRENT_QUIX_SCHEMA_VERSION = 2;
  class v21562174176877 (line 7) | class v21562174176877 implements MigrationInterface {
    method up (line 8) | public async up(queryRunner: QueryRunner): Promise<any> {
    method down (line 31) | public async down(queryRunner: QueryRunner): Promise<any> {

FILE: quix-frontend/service/src/migrations/1614173960671-v3.ts
  constant PREVIOUS_QUIX_SCHEMA (line 4) | const PREVIOUS_QUIX_SCHEMA = 2;
  constant CURRENT_QUIX_SCHEMA_VERSION (line 5) | const CURRENT_QUIX_SCHEMA_VERSION = 3;
  class v31614173960671 (line 7) | class v31614173960671 implements MigrationInterface {
    method up (line 10) | public async up(queryRunner: QueryRunner): Promise<void> {
    method down (line 36) | public async down(queryRunner: QueryRunner): Promise<void> {

FILE: quix-frontend/service/src/migrations/1614712161318-v4.ts
  constant PREVIOUS_QUIX_SCHEMA (line 4) | const PREVIOUS_QUIX_SCHEMA = 3;
  constant CURRENT_QUIX_SCHEMA_VERSION (line 5) | const CURRENT_QUIX_SCHEMA_VERSION = 4;
  class v41614712161318 (line 7) | class v41614712161318 implements MigrationInterface {
    method up (line 10) | public async up(queryRunner: QueryRunner): Promise<void> {
    method down (line 28) | public async down(queryRunner: QueryRunner): Promise<void> {

FILE: quix-frontend/service/src/migrations/1634023683491-v5.ts
  constant PREVIOUS_QUIX_SCHEMA (line 4) | const PREVIOUS_QUIX_SCHEMA = 4;
  constant CURRENT_QUIX_SCHEMA_VERSION (line 5) | const CURRENT_QUIX_SCHEMA_VERSION = 5;
  class v51634023683491 (line 6) | class v51634023683491 implements MigrationInterface {
    method up (line 9) | public async up(queryRunner: QueryRunner): Promise<void> {
    method down (line 26) | public async down(queryRunner: QueryRunner): Promise<void> {

FILE: quix-frontend/service/src/modules/auth/auth.controller.ts
  class AuthController (line 19) | class AuthController {
    method constructor (line 21) | constructor(
    method getUser (line 29) | async getUser(@User() user: IExternalUser) {
    method doAuth (line 43) | async doAuth(

FILE: quix-frontend/service/src/modules/auth/auth.module.ts
  class AuthModuleConfiguration (line 24) | class AuthModuleConfiguration {
    method createAsync (line 25) | static createAsync(authAsyncOptions: AuthAsyncOptions): DynamicModule {
    method create (line 40) | static create(authOption: AuthOptions): DynamicModule {
  class AuthModule (line 86) | class AuthModule {
    method create (line 87) | static create(): DynamicModule {

FILE: quix-frontend/service/src/modules/auth/login.service.ts
  class FakeLoginService (line 26) | class FakeLoginService extends LoginService {
    method constructor (line 27) | constructor(
    method verify (line 33) | verify(token: string) {
    method login (line 37) | login(
  class CustomLoginService (line 55) | class CustomLoginService extends LoginService {
    method constructor (line 56) | constructor(
    method verify (line 62) | verify(token: string) {
    method login (line 66) | login(
  class GoogleLoginService (line 75) | class GoogleLoginService extends LoginService {
    method constructor (line 76) | constructor(
    method verify (line 83) | verify(token: string) {
    method login (line 87) | async login(

FILE: quix-frontend/service/src/modules/auth/types.ts
  type IExternalUser (line 10) | interface IExternalUser {
  type CustomAuth (line 17) | interface CustomAuth {
  type AuthTypes (line 27) | enum AuthTypes {
  type FakeAuthOptions (line 33) | type FakeAuthOptions = {
  type GoogleAuthOptions (line 37) | type GoogleAuthOptions = {
  type CustomAuthOptions (line 46) | type CustomAuthOptions = {
  type AuthOptions (line 52) | type AuthOptions =
  type AuthAsyncOptions (line 60) | interface AuthAsyncOptions extends Pick<ModuleMetadata, 'imports'> {

FILE: quix-frontend/service/src/modules/auth/user-decorator.ts
  class AuthGuard (line 18) | class AuthGuard implements CanActivate {
    method constructor (line 21) | constructor(
    method canActivate (line 34) | canActivate(context: ExecutionContext): boolean | Promise<boolean> {
  type Request (line 44) | interface Request {

FILE: quix-frontend/service/src/modules/auth/users.service.ts
  class UsersService (line 13) | class UsersService {
    method constructor (line 16) | constructor(
    method doUserLogin (line 21) | async doUserLogin(userFromLogin: IExternalUser) {
    method doFirstTimeLogin (line 30) | private async doFirstTimeLogin(userFromLogin: IExternalUser) {
    method doLogin (line 48) | private async doLogin(userFromLogin: IExternalUser, dbUser: DbUser) {
    method createRootFolder (line 68) | private async createRootFolder(user: string) {
    method getListOfUsers (line 81) | async getListOfUsers() {

FILE: quix-frontend/service/src/modules/event-sourcing/base-action-validation.ts
  class BaseActionValidation (line 13) | class BaseActionValidation implements PipeTransform {
    method transform (line 14) | transform(action: any, metadata: ArgumentMetadata) {

FILE: quix-frontend/service/src/modules/event-sourcing/event-sourcing.module.ts
  class EventSourcingModule (line 62) | class EventSourcingModule {}

FILE: quix-frontend/service/src/modules/event-sourcing/events.service.ts
  class EventsService (line 6) | class EventsService {
    method logEvent (line 10) | logEvent(action: IAction) {
    method getEventStream (line 14) | getEventStream(sessionId: string, userId: string): Observable<IAction> {
    method closeEventStream (line 21) | closeEventStream(sessionId: string, userId: string) {
    method associateSessionIdWithUserId (line 39) | associateSessionIdWithUserId(sessionId: string, userId: string) {
    method sendMessage (line 46) | sendMessage(data: IAction) {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/action-store/action-store.ts
  class DbActionStore (line 26) | class DbActionStore implements IActionStore {
    method constructor (line 27) | constructor(@InjectRepository(DbAction) private repo: Repository<DbAct...
    method pushAction (line 29) | async pushAction(action: IAction | IAction[]) {
    method get (line 45) | async get(aggId?: string | string[], orderBy?: string) {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/action-store/entities/db-action.entity.ts
  class DbAction (line 8) | class DbAction<T = IEventData, N extends string = string>
    method constructor (line 27) | constructor(base?: IAction<T, N>) {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/action-store/types.ts
  type IDBAction (line 6) | interface IDBAction<T = IEventData, N extends string = string> {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/event-bus/api.ts
  class RegisterApi (line 13) | class RegisterApi {
    method constructor (line 14) | constructor(private descriptor: PluginDescriptor) {}
    method setPluginOptions (line 24) | setPluginOptions(options: PluginOptions) {
    method setEventFilter (line 28) | setEventFilter(fn: EventFilter) {
  class MiddlewareApi (line 33) | class MiddlewareApi implements IMiddlewareApi {
    method constructor (line 37) | constructor(
    method getLoggedActions (line 44) | getLoggedActions() {
    method pushLoggedActions (line 48) | pushLoggedActions(actions: IAction[]) {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/event-bus/context.ts
  class ContextFactory (line 1) | class ContextFactory {
    method constructor (line 3) | constructor(private base: object = {}) {}
    method setExtra (line 5) | setExtra(extra?: object) {
    method create (line 12) | create() {
  class Context (line 17) | class Context {
    method constructor (line 18) | constructor(private base: object, private extra: object) {}
    method set (line 20) | set(data: object) {
    method get (line 24) | get(): any {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/event-bus/event-bus-builder.ts
  type AddPluginOptions (line 13) | interface AddPluginOptions {
  class EventBusBuilderT (line 22) | class EventBusBuilderT {
    method addPlugin (line 32) | addPlugin(
    method addMiddleware (line 59) | addMiddleware(
    method computeMiddlewarePriority (line 70) | private computeMiddlewarePriority(priority?: number) {
    method build (line 83) | build(options: {timeout: number} = {timeout: 30000}) {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/event-bus/event-bus.ts
  class EventBus (line 26) | class EventBus {
    method constructor (line 29) | constructor(
    method emit (line 40) | emit<A extends IAction = IAction>(action: A) {
    method on (line 92) | on(type: string, handler: (...args: any[]) => any) {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/event-bus/types.ts
  type EventBusMiddleware (line 5) | type EventBusMiddleware = <A extends IAction = IAction>(
  type EventBusNextFn (line 10) | type EventBusNextFn = <A extends IAction = IAction>(
  type EventBusPluginFn (line 13) | type EventBusPluginFn = (api: RegisterApi) => void;
  type EventBusPlugin (line 14) | interface EventBusPlugin {
  type EventBusMiddlewareDescriptor (line 20) | interface EventBusMiddlewareDescriptor {
  type EventFilter (line 26) | type EventFilter = (type: string) => boolean;
  type PluginDescriptor (line 28) | interface PluginDescriptor {
  type PluginOptions (line 43) | interface PluginOptions {
  type Plugins (line 47) | type Plugins = Map<string, PluginDescriptor>;
  type IPluginApi (line 50) | interface IPluginApi {
  type HookFn (line 61) | type HookFn<A extends IAction = IAction> = (
  type Hook (line 66) | interface Hook<A extends IAction = IAction> {
  type HookApi (line 71) | interface HookApi {

FILE: quix-frontend/service/src/modules/event-sourcing/infrastructure/types.ts
  type IEventData (line 2) | interface IEventData {
  type HasId (line 6) | interface HasId {
  type ServerFields (line 10) | interface ServerFields {
  type IAction (line 17) | type IAction<T = IEventData, N extends string = string> = BaseAction & {

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/deleted-notebook-plugin.ts
  class DeletedNotebookPlugin (line 20) | class DeletedNotebookPlugin implements EventBusPlugin {
    method constructor (line 23) | constructor(@InjectEntityManager() private em: EntityManager) {}
    method projectDeletedNotebook (line 58) | private async projectDeletedNotebook(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/events-plugin.ts
  class EventsPlugin (line 8) | class EventsPlugin implements EventBusPlugin {
    method constructor (line 11) | constructor(@Inject(EventsService) private eventsService: EventsServic...

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/favorites-plugin.ts
  class FavoritesPlugin (line 15) | class FavoritesPlugin implements EventBusPlugin {
    method constructor (line 18) | constructor(@InjectEntityManager() private em: EntityManager) {}
    method projectFavorites (line 43) | private async projectFavorites(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/file-tree-plugin.ts
  class FileTreePlugin (line 27) | class FileTreePlugin implements EventBusPlugin {
    method constructor (line 30) | constructor(
  function assertNodeNotNotebook (line 175) | function assertNodeNotNotebook(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/note-plugin.ts
  class NotePlugin (line 22) | class NotePlugin implements EventBusPlugin {
    method constructor (line 25) | constructor(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/notebook-plugin.ts
  class NotebookPlugin (line 28) | class NotebookPlugin implements EventBusPlugin {
    method constructor (line 31) | constructor(@InjectEntityManager() private em: EntityManager) {}
    method projectNotebook (line 71) | private async projectNotebook(
    method projectNote (line 91) | async projectNote(
    method projectFileTree (line 103) | private async projectFileTree(
    method projectFavorites (line 126) | private async projectFavorites(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/trash-bin-plugin.ts
  class TrashBinPlugin (line 28) | class TrashBinPlugin implements EventBusPlugin {
    method constructor (line 31) | constructor(
    method restoreNotebookReactions (line 64) | private async restoreNotebookReactions(
    method addNotebookReactions (line 100) | private async addNotebookReactions(
    method addNotebook (line 106) | private async addNotebook(notebookId: string, user: string, userId?: s...
    method addFolderReactions (line 126) | async addFolderReactions(
    method permanentlyDeleteReactions (line 147) | private async permanentlyDeleteReactions(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/user-plugin.ts
  class UserPlugin (line 12) | class UserPlugin implements EventBusPlugin {
    method constructor (line 15) | constructor(

FILE: quix-frontend/service/src/modules/event-sourcing/plugins/utils.ts
  function lastAndAssertExist (line 17) | function lastAndAssertExist<T>(
  function assertOwner (line 29) | function assertOwner<T extends {owner: string}>(
  function assert (line 42) | function assert<T, A extends IAction>(
  function asUser (line 53) | function asUser(reAction: any, user: string, userId?: string) {

FILE: quix-frontend/service/src/modules/event-sourcing/quix-event-bus.driver.ts
  class QuixEventBusDriver (line 29) | class QuixEventBusDriver {
    method constructor (line 32) | constructor(
    method create (line 50) | static async create(defaultUserId: string) {
    method clearDb (line 113) | async clearDb() {
    method getNotebook (line 124) | getNotebook(id: string) {
    method getDeletedNotebook (line 141) | getDeletedNotebook(id: string) {
    method getFavorite (line 160) | getFavorite(owner: string, entityId: string, entityType: EntityType) {
    method getNotebookWithNotes (line 189) | async getNotebookWithNotes(id: string) {
    method getNote (line 196) | async getNote(id: string) {
    method getNotesForNotebook (line 200) | async getNotesForNotebook(notebookId: string) {
    method getUsers (line 204) | async getUsers() {
    method getUserFileTree (line 208) | async getUserFileTree(user: string) {
    method clearEvents (line 218) | clearEvents() {
    method clearNotes (line 222) | async clearNotes() {
    method clearNotebooks (line 226) | async clearNotebooks() {
    method clearDeletedNotebooks (line 229) | async clearDeletedNotebooks() {
    method clearFavorites (line 233) | async clearFavorites() {
    method emitAsUser (line 237) | emitAsUser(
    method clearFolders (line 245) | async clearFolders() {

FILE: quix-frontend/service/src/modules/event-sourcing/quix-event-bus.spec.ts
  function reorderPos (line 923) | function reorderPos<T>(items: T[], from: number, to: number) {

FILE: quix-frontend/service/src/modules/event-sourcing/quix-event-bus.ts
  class QuixEventBus (line 22) | class QuixEventBus<A extends IAction = IAction> {
    method constructor (line 26) | constructor(
    method emit (line 90) | async emit(action: A | A[]) {
    method on (line 103) | on<T extends string>(type: T, handler: (action: A & {type: T}) => any) {

FILE: quix-frontend/service/src/modules/event-sourcing/types.ts
  type QuixHookNames (line 1) | enum QuixHookNames {

FILE: quix-frontend/service/src/modules/logger/logger.module.ts
  class LoggerModule (line 8) | class LoggerModule {}

FILE: quix-frontend/service/src/modules/logger/logger.service.ts
  class Logger (line 3) | class Logger extends BaseLogger {}

FILE: quix-frontend/service/src/modules/proxy-backend/proxy-backend.module.ts
  class ProxyDbApiBackend (line 10) | class ProxyDbApiBackend implements NestModule {
    method constructor (line 11) | constructor(private configService: ConfigService) {}
    method configure (line 13) | configure(consumer: MiddlewareConsumer) {

FILE: quix-frontend/service/src/modules/search/search.module.ts
  class SearchModule (line 14) | class SearchModule {}

FILE: quix-frontend/service/src/modules/search/search.ts
  class SearchService (line 12) | class SearchService implements ISearch {
    method constructor (line 13) | constr
Condensed preview — 1185 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,589K chars).
[
  {
    "path": ".dockerignore",
    "chars": 21,
    "preview": "*/node_modules\n*.log\n"
  },
  {
    "path": ".github/workflows/quix-backend-build.yml",
    "chars": 1242,
    "preview": "name: Quix Backend Build\non:\n  pull_request:\n    paths:\n    - 'quix-backend/**'  \n  push:\n    paths:\n    - 'quix-backend"
  },
  {
    "path": ".github/workflows/quix-documentation-publish.yml",
    "chars": 904,
    "preview": "# This Workflow will publish Documentation on any push to master branch into \n# the documentation folder.\nname: Quix Doc"
  },
  {
    "path": ".github/workflows/quix-frontend-publish.yml",
    "chars": 1178,
    "preview": "# Build on each branch and Publish to NPM on master if version bumped\nname: Quix Frontend Build & Publish\non:\n  workflow"
  },
  {
    "path": ".github/workflows/quix-frontend-release.yml",
    "chars": 1509,
    "preview": "name: Quix Frontend Release DockerHub\n\non:\n  workflow_dispatch:\n    inputs:\n      comment:\n        description: 'Comment"
  },
  {
    "path": ".gitignore",
    "chars": 1497,
    "preview": "# Created by https://www.gitignore.io/api/maven,scala,jetbrains\n\n### Maven ###\ntarget/\npom.xml.tag\npom.xml.releaseBackup"
  },
  {
    "path": ".travis.yml",
    "chars": 711,
    "preview": "jobs:\n  include:\n    - stage: test\n      name: \"Frontend\"\n      language: node_js\n      dist: bionic\n      node_js: 14\n "
  },
  {
    "path": "LICENSE",
    "chars": 1070,
    "preview": "MIT License\n\nCopyright (c) 2019 Wix Incubator\n\nPermission is hereby granted, free of charge, to any person obtaining a c"
  },
  {
    "path": "README.md",
    "chars": 3088,
    "preview": "# Quix\n![Support](https://img.shields.io/npm/l/@wix/quix-client) [![Maven Central](https://maven-badges.herokuapp.com/ma"
  },
  {
    "path": "build-selector.sh",
    "chars": 384,
    "preview": "#!/usr/bin/env bash\n\nif [ -z $2 ]; then\n  GIT_RANGE=\"HEAD^1\"\n  BUILD_TYPE=$1\nelse\n  GIT_RANGE=\"$1\"\n  BUILD_TYPE=\"$2\"\nfi\n"
  },
  {
    "path": "docker-compose.prebuilt.yml",
    "chars": 1025,
    "preview": "version: '3'\nservices:\n  backend:\n    image: wixquix/quix-backend:latest\n    ports:\n      - \"8081:8081\"\n    depends_on:\n"
  },
  {
    "path": "docker-compose.yml",
    "chars": 1106,
    "preview": "version: \"3\"\nservices:\n  backend:\n    build: ./quix-backend/\n    ports:\n      - \"8081:8081\"\n    depends_on:\n      - pres"
  },
  {
    "path": "documentation/docs/about.md",
    "chars": 1525,
    "preview": "---\nid: about\ntitle: About\nsidebar_label: About\n---\n\nQuix is an easy-to-use notebook manager with support for [Presto](/"
  },
  {
    "path": "documentation/docs/architecture.md",
    "chars": 525,
    "preview": "---\nid: architecture\ntitle: Architecture\nsidebar_label: Architecture\n---\n\n![](assets/architecture.png)\n\nQuix consists of"
  },
  {
    "path": "documentation/docs/athena.md",
    "chars": 2026,
    "preview": "---\nid: athena\ntitle: Amazon Athena\nsidebar_label: Athena\n---\n## Features\nWork with Amazon Athena tables straight from Q"
  },
  {
    "path": "documentation/docs/bigquery.md",
    "chars": 1443,
    "preview": "---\nid: bigquery\ntitle: Google BigQuery\nsidebar_label: BigQuery\n---\n## Features\nWork with Google bigquery tables straigh"
  },
  {
    "path": "documentation/docs/clickhouse.md",
    "chars": 1409,
    "preview": "---\nid: clickhouse\ntitle: ClickHouse\nsidebar_label: ClickHouse\n---\n\n## Features\nUsing jdbc note you can use quix to quer"
  },
  {
    "path": "documentation/docs/installation.md",
    "chars": 4239,
    "preview": "---\nid: installation\ntitle: Installation\nsidebar_label: Installation\n---\n\n## Requirements\n* [Docker](https://www.docker."
  },
  {
    "path": "documentation/docs/jdbc.md",
    "chars": 3239,
    "preview": "---\nid: jdbc\ntitle: Jdbc\nsidebar_label: Jdbc\n---\n\n## Features\nUsing jdbc note you can use quix to query \n[MySQL](mysql.m"
  },
  {
    "path": "documentation/docs/mariadb.md",
    "chars": 1304,
    "preview": "---\nid: mariadb\ntitle: MariaDB\nsidebar_label: MariaDB\n---\n\n## Features\nWork with MariaDB tables straight from Quix, exec"
  },
  {
    "path": "documentation/docs/mysql.md",
    "chars": 1279,
    "preview": "---\nid: mysql\ntitle: MySQL\nsidebar_label: MySQL\n---\n\n## Features\nWork with MySQL tables straight from Quix, execute mult"
  },
  {
    "path": "documentation/docs/oracle.md",
    "chars": 1323,
    "preview": "---\nid: oracle\ntitle: Oracle\nsidebar_label: Oracle\n---\n\n## Features\nWork with Oracle straight from Quix, execute multipl"
  },
  {
    "path": "documentation/docs/postgresql.md",
    "chars": 1310,
    "preview": "---\nid: postgresql\ntitle: PostgreSQL\nsidebar_label: PostgreSQL\n---\n\n## Features\nWork with PostgreSQL straight from Quix,"
  },
  {
    "path": "documentation/docs/presto.md",
    "chars": 1188,
    "preview": "---\nid: presto\ntitle: Presto\nsidebar_label: Presto\n---\n## Features\nQuix is a great tool for querying Presto. You can exe"
  },
  {
    "path": "documentation/docs/python.md",
    "chars": 1930,
    "preview": "---\nid: python\ntitle: Python\nsidebar_label: Python\n---\n## Features\n* Execute lightweight Python scripts straight from Qu"
  },
  {
    "path": "documentation/docs/redshift.md",
    "chars": 2397,
    "preview": "---\nid: redshift\ntitle: Amazon Redshift\nsidebar_label: Redshift\n---\n\n## Features\nQuery Amazon Redshift data warehouse st"
  },
  {
    "path": "documentation/website/README.md",
    "chars": 4066,
    "preview": "This website was created with [Docusaurus](https://docusaurus.io/).\n\n# What's In This Document\n\n* [Get Started in 5 Minu"
  },
  {
    "path": "documentation/website/blog/2019-11-25-first-release.md",
    "chars": 2035,
    "preview": "---\ntitle: First release\nauthor: Quix Team\n---\nQuix is a notebook manager that focuses on ease of use and shareability. "
  },
  {
    "path": "documentation/website/core/Footer.js",
    "chars": 2156,
    "preview": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "documentation/website/i18n/en.json",
    "chars": 2070,
    "preview": "{\n  \"_comment\": \"This file is auto-generated by write-translations.js\",\n  \"localized-strings\": {\n    \"next\": \"Next\",\n   "
  },
  {
    "path": "documentation/website/package.json",
    "chars": 376,
    "preview": "{\n  \"scripts\": {\n    \"examples\": \"docusaurus-examples\",\n    \"start\": \"docusaurus-start\",\n    \"build\": \"docusaurus-build\""
  },
  {
    "path": "documentation/website/pages/en/help.js",
    "chars": 1530,
    "preview": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "documentation/website/pages/en/index.js",
    "chars": 5472,
    "preview": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "documentation/website/pages/en/users.js",
    "chars": 1346,
    "preview": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "documentation/website/sidebars.json",
    "chars": 258,
    "preview": "{\n  \"docs\": {\n    \"Introduction\": [\"about\", \"architecture\"],\n    \"Getting Started\": [\"installation\"],\n    \"Supported dat"
  },
  {
    "path": "documentation/website/siteConfig.js",
    "chars": 3076,
    "preview": "/**\n * Copyright (c) 2017-present, Facebook, Inc.\n *\n * This source code is licensed under the MIT license found in the\n"
  },
  {
    "path": "documentation/website/static/css/custom.css",
    "chars": 959,
    "preview": "/* your custom css */\n\n@media only screen and (min-device-width: 360px) and (max-device-width: 736px) {\n}\n\n@media only s"
  },
  {
    "path": "env-example",
    "chars": 1106,
    "preview": "#MODULES=presto,athena,prod,bq\nMODULES=presto\n\n\nMODULES_PRESTO_ENGINE=presto\nMODULES_PRESTO_API=http://presto:8080/v1\nMO"
  },
  {
    "path": "quix-backend/Dockerfile",
    "chars": 2998,
    "preview": "FROM maven:alpine as maven\n\n# Install sbt\nRUN \\\n    curl -L --silent \"https://raw.githubusercontent.com/sbt/sbt/v1.5.1/s"
  },
  {
    "path": "quix-backend/README.md",
    "chars": 1244,
    "preview": "# Quix Backend\nQuix backend is based on SpringBoot and Scala, and is built with sbt and Maven.\n \n## Installation\n\n### Re"
  },
  {
    "path": "quix-backend/build.sbt",
    "chars": 6485,
    "preview": "lazy val publishSettings = Seq(\n  publishTo := {\n    val nexus = \"https://oss.sonatype.org/\"\n    if (version.value.trim."
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/db/Db.scala",
    "chars": 2325,
    "preview": "package quix.api.v1.db\n\nimport monix.eval.Task\n\nsealed case class Catalog(name: String,\n                          childr"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/execute/Api.scala",
    "chars": 395,
    "preview": "package quix.api.v1.execute\n\nimport java.io.IOException\n\nimport monix.eval.Task\nimport quix.api.v1.users.User\n\n/** End c"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/execute/Batch.scala",
    "chars": 1467,
    "preview": "package quix.api.v1.execute\n\ncase class BatchColumn(name: String)\n\ncase class BatchError(message: String)\n\n/** Used in ["
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/execute/ExecutionEngine.scala",
    "chars": 2402,
    "preview": "package quix.api.v1.execute\n\nimport monix.eval.Task\nimport quix.api.v1.users.User\n\n\ncase class ActiveQuery[Code](id: Str"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/execute/ExecutionProtocol.scala",
    "chars": 3014,
    "preview": "package quix.api.v1.execute\n\nsealed trait EventData\n\n/**\n * Event used to communicate changes\n *\n * @param event event n"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/module/ExecutionModule.scala",
    "chars": 1151,
    "preview": "package quix.api.v1.module\n\nimport monix.eval.Task\nimport quix.api.v1.db.Db\nimport quix.api.v1.execute.{Builder, StartCo"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v1/users/Users.scala",
    "chars": 422,
    "preview": "package quix.api.v1.users\n\nsealed case class User(email: String, id: String = \"\")\n\ntrait Users {\n  @throws[RequestNotAut"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v2/execute/Builder.scala",
    "chars": 1296,
    "preview": "package quix.api.v2.execute\n\nimport monix.eval.Task\nimport quix.api.v1.execute.Batch\n\n/**\n * Builder is used to propagat"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v2/execute/ExecutionModule.scala",
    "chars": 1075,
    "preview": "package quix.api.v2.execute\n\nimport monix.eval.Task\nimport quix.api.v1.db.Db\nimport quix.api.v1.execute.StartCommand\nimp"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v2/execute/Executor.scala",
    "chars": 208,
    "preview": "package quix.api.v2.execute\n\nimport monix.eval.Task\n\n/** Used to execute single query and stream the results back to Bui"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v2/execute/Session.scala",
    "chars": 740,
    "preview": "package quix.api.v2.execute\n\ntrait Session {\n  def put(key: String, value: String)\n\n  def remove(key: String)\n\n  def get"
  },
  {
    "path": "quix-backend/quix-api/src/main/scala/quix/api/v2/execute/SubQuery.scala",
    "chars": 735,
    "preview": "package quix.api.v2.execute\n\nimport java.util.UUID\n\nimport monix.execution.atomic.Atomic\nimport quix.api.v1.users.User\n\n"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/db/DbOps.scala",
    "chars": 2360,
    "preview": "package quix.core.db\n\nimport com.typesafe.scalalogging.LazyLogging\nimport quix.api.v1.db.Catalog\n\nobject DbOps extends L"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/db/RefreshableAutocomplete.scala",
    "chars": 1398,
    "preview": "package quix.core.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.Autocomplete\n\nimport scala.concurrent.duration._\n\ncla"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/db/RefreshableCatalogs.scala",
    "chars": 1341,
    "preview": "package quix.core.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Catalog, Catalogs}\n\nimport scala.concurrent.duration"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/db/RefreshableDb.scala",
    "chars": 612,
    "preview": "package quix.core.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Catalog, Db, Table, Tables}\n\nclass RefreshableDb(cat"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/db/State.scala",
    "chars": 72,
    "preview": "package quix.core.db\n\ncase class State[T](data: T, expirationDate: Long)"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/download/DownloadConfig.scala",
    "chars": 3572,
    "preview": "package quix.core.download\n\nimport java.io.InputStream\nimport java.nio.file.{Files, Path, Paths}\nimport java.util.zip.GZ"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/download/DownloadableBuilder.scala",
    "chars": 3590,
    "preview": "package quix.core.download\n\nimport com.opencsv.CSVWriter\nimport monix.eval.Task\nimport quix.api.v1.execute.{Builder => _"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/executions/DelegatingBuilder.scala",
    "chars": 1066,
    "preview": "package quix.core.executions\n\nimport quix.api.v1.execute.Batch\nimport quix.api.v2.execute._\n\nabstract class DelegatingBu"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/executions/SingleQueryExecutor.scala",
    "chars": 1562,
    "preview": "package quix.core.executions\n\nimport monix.eval.Task\nimport quix.api.v1.users.User\nimport quix.api.v2.execute.{Executor,"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/executions/SqlModule.scala",
    "chars": 893,
    "preview": "package quix.core.executions\n\nimport monix.eval.Task\nimport quix.api.v1.db.Db\nimport quix.api.v1.execute.StartCommand\nim"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/history/Execution.scala",
    "chars": 554,
    "preview": "package quix.core.history\n\nimport java.time.Instant\n\nimport quix.api.v1.users.User\n\ncase class Execution(id: String,\n   "
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/history/HistoryBuilder.scala",
    "chars": 1534,
    "preview": "package quix.core.history\n\nimport monix.eval.Task\nimport quix.api.v1.execute.Batch\nimport quix.api.v2.execute.{Builder, "
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/history/dao/HistoryReadDao.scala",
    "chars": 1965,
    "preview": "package quix.core.history.dao\n\nimport monix.eval.Task\nimport quix.core.history.{Execution, ExecutionStatus}\n\nimport scal"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/history/dao/HistoryWriteDao.scala",
    "chars": 307,
    "preview": "package quix.core.history.dao\n\nimport monix.eval.Task\nimport quix.api.v2.execute.Query\n\ntrait HistoryWriteDao {\n  def ex"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/history/dao/InMemoryHistoryDao.scala",
    "chars": 2634,
    "preview": "package quix.core.history.dao\n\nimport java.time.Clock\n\nimport cats.effect.concurrent.Ref\nimport monix.eval.Task\nimport q"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/history/dao/MySqlHistoryDao.scala",
    "chars": 5428,
    "preview": "package quix.core.history.dao\n\nimport java.sql.{Connection, DriverManager, PreparedStatement, ResultSet}\nimport java.tim"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/results/MultiBuilder.scala",
    "chars": 3629,
    "preview": "package quix.core.results\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.eval.Task\nimport quix.api.v1.execut"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/results/SingleBuilder.scala",
    "chars": 2610,
    "preview": "package quix.core.results\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.eval.Task\nimport quix.api.v1.execut"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/sql/PrestoSqlOps.scala",
    "chars": 1435,
    "preview": "package quix.core.sql\n\nimport io.prestosql.sql.parser.StatementSplitter\n\nimport scala.collection.JavaConverters._\n\nobjec"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/sql/SqlSplitter.scala",
    "chars": 1432,
    "preview": "package quix.core.sql\n\nimport monix.execution.atomic.Atomic\nimport quix.api.v1.execute.StartCommand\nimport quix.api.v1.u"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/utils/Chores.scala",
    "chars": 1448,
    "preview": "package quix.core.utils\n\nimport java.util.concurrent.{Executors, ScheduledExecutorService, ThreadFactory}\n\nimport com.ty"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/utils/JsonOps.scala",
    "chars": 2408,
    "preview": "package quix.core.utils\n\nimport java.lang.reflect.{ParameterizedType, Type}\nimport java.util.TimeZone\n\nimport com.faster"
  },
  {
    "path": "quix-backend/quix-core/src/main/scala/quix/core/utils/TaskOps.scala",
    "chars": 881,
    "preview": "package quix.core.utils\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.eval.Task\n\nimport scala.concurrent.du"
  },
  {
    "path": "quix-backend/quix-core/src/test/resources/db/001_init.sql",
    "chars": 534,
    "preview": "CREATE TABLE executions_history (\n    id CHAR(36) NOT NULL PRIMARY KEY,\n    query_type VARCHAR(64) NOT NULL,\n    stateme"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/db/DbOpsTest.scala",
    "chars": 3587,
    "preview": "package quix.core.db\n\nimport org.specs2.matcher.MustMatchers\nimport org.specs2.mutable.SpecWithJUnit\nimport quix.api.v1."
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/db/DbQueryTest.scala",
    "chars": 537,
    "preview": "package quix.core.db\n\nimport org.specs2.mutable.SpecWithJUnit\n\nclass DbQueryTest extends SpecWithJUnit {\n\n  \"DbQuery.app"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/executions/SqlModuleTest.scala",
    "chars": 1234,
    "preview": "package quix.core.executions\n\nimport monix.eval.Task\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/ExecutionMatchers.scala",
    "chars": 344,
    "preview": "package quix.core.history\n\nimport org.specs2.matcher.Matcher\nimport org.specs2.matcher.Matchers._\n\nobject ExecutionMatch"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/FakeBuilder.scala",
    "chars": 3798,
    "preview": "package quix.core.history\n\nimport cats.effect.concurrent.Ref\nimport monix.eval.Task\nimport monix.execution.Scheduler.Imp"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/FakeClock.scala",
    "chars": 642,
    "preview": "package quix.core.history\n\nimport java.time.{Clock, Instant, ZoneId, ZoneOffset}\nimport java.util.concurrent.atomic.Atom"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/HistoryBuilderTest.scala",
    "chars": 3173,
    "preview": "package quix.core.history\n\nimport java.time.{Clock, Instant, ZoneOffset}\n\nimport monix.execution.Scheduler.Implicits.glo"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/dao/HistoryDaoContractTest.scala",
    "chars": 11103,
    "preview": "package quix.core.history.dao\n\nimport java.time.{Clock, Instant, ZoneOffset}\n\nimport cats.effect.Resource\nimport monix.e"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/dao/InMemoryHistoryDaoTest.scala",
    "chars": 318,
    "preview": "package quix.core.history.dao\n\nimport java.time.Clock\n\nimport cats.effect.Resource\nimport monix.eval.Task\n\nclass InMemor"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/history/dao/MySqlHistoryDaoTest.scala",
    "chars": 2595,
    "preview": "package quix.core.history.dao\n\nimport java.time.Clock\n\nimport cats.effect.Resource\nimport com.typesafe.scalalogging.Lazy"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/results/MultiBuilderTest.scala",
    "chars": 8592,
    "preview": "package quix.core.results\n\nimport java.util.UUID\n\nimport monix.eval.Task\nimport monix.execution.Scheduler\nimport org.spe"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/sql/PrestoSqlOpsTest.scala",
    "chars": 1593,
    "preview": "package quix.core.sql\n\nimport org.specs2.mutable.SpecWithJUnit\nimport quix.core.sql.PrestoSqlOps.{splitToStatements => s"
  },
  {
    "path": "quix-backend/quix-core/src/test/scala/quix/core/sql/StopWordsSplitterTest.scala",
    "chars": 889,
    "preview": "package quix.core.sql\n\nimport org.specs2.mutable.SpecWithJUnit\n\nclass StopWordsSplitterTest extends SpecWithJUnit {\n\n  \""
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaAutocomplete.scala",
    "chars": 619,
    "preview": "package quix.athena\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Autocomplete, Catalog, Catalogs}\n\nclass AthenaAutocom"
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaCatalogs.scala",
    "chars": 1019,
    "preview": "package quix.athena\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Catalog, Catalogs, Schema, Table}\nimport quix.api.v2."
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaClient.scala",
    "chars": 479,
    "preview": "package quix.athena\n\nimport com.amazonaws.services.athena.model.{GetQueryExecutionResult, GetQueryResultsResult, StartQu"
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaConfig.scala",
    "chars": 470,
    "preview": "package quix.athena\n\ncase class AthenaConfig(output: String,\n                        region: String,\n                   "
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaQueryExecutor.scala",
    "chars": 10818,
    "preview": "package quix.athena\n\nimport java.net.{ConnectException, SocketException, SocketTimeoutException}\n\nimport com.amazonaws.S"
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AthenaTables.scala",
    "chars": 770,
    "preview": "package quix.athena\n\nimport monix.eval.Task\nimport quix.api.v1.db._\nimport quix.api.v2.execute.Executor\nimport quix.core"
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/AwsAthenaClient.scala",
    "chars": 1652,
    "preview": "package quix.athena\n\nimport com.amazonaws.services.athena.AmazonAthena\nimport com.amazonaws.services.athena.model._\nimpo"
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/main/scala/quix/athena/TryAthena.scala",
    "chars": 1092,
    "preview": "package quix.athena\n\nimport com.amazonaws.auth.DefaultAWSCredentialsProviderChain\nimport com.amazonaws.regions.Regions\ni"
  },
  {
    "path": "quix-backend/quix-modules/quix-athena-module/src/test/scala/quix/athena/AthenaQueryExecutorTest.scala",
    "chars": 5992,
    "preview": "package quix.athena\n\nimport com.amazonaws.services.athena.model._\nimport monix.eval.Task\nimport monix.execution.Schedule"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/BigQueryClient.scala",
    "chars": 225,
    "preview": "package quix.bigquery\n\nimport com.google.cloud.bigquery.Job\nimport monix.eval.Task\nimport quix.api.v2.execute.SubQuery\n\n"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/BigQueryConfig.scala",
    "chars": 182,
    "preview": "package quix.bigquery\n\ncase class BigQueryConfig(credentialBytes: Array[Byte],\n                          firstEmptyState"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/BigQueryQueryExecutor.scala",
    "chars": 4953,
    "preview": "package quix.bigquery\n\nimport java.io.ByteArrayInputStream\n\nimport com.google.api.client.googleapis.json.GoogleJsonRespo"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/BigQueryTestQueryExecutor.scala",
    "chars": 1660,
    "preview": "package quix.bigquery\n\nimport monix.eval.Task\nimport quix.api.v2.execute.{Builder, Executor, SubQuery}\n\nimport scala.col"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/GoogleBigQueryClient.scala",
    "chars": 811,
    "preview": "package quix.bigquery\n\nimport com.google.cloud.bigquery._\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.eval"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/TryBigQuery.scala",
    "chars": 847,
    "preview": "package quix.bigquery\n\nimport java.nio.file.{Files, Paths}\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.ex"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/db/BigQueryAutocomplete.scala",
    "chars": 730,
    "preview": "package quix.bigquery.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Autocomplete, Catalog, Catalogs}\nimport quix.api"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/db/BigQueryCatalogs.scala",
    "chars": 1215,
    "preview": "package quix.bigquery.db\n\nimport com.google.cloud.bigquery.{BigQuery, DatasetId}\nimport monix.eval.Task\nimport quix.api."
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/main/scala/quix/bigquery/db/BigQueryTables.scala",
    "chars": 951,
    "preview": "package quix.bigquery.db\n\nimport monix.eval.Task\nimport quix.api.v1.db._\nimport quix.api.v2.execute.Executor\nimport quix"
  },
  {
    "path": "quix-backend/quix-modules/quix-bigquery-module/src/test/scala/quix/bigquery/BigQueryQueryExecutorTest.scala",
    "chars": 1127,
    "preview": "package quix.bigquery\n\nimport monix.eval.Task\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.matche"
  },
  {
    "path": "quix-backend/quix-modules/quix-dummy-module/src/main/scala/quix/dummy/DummyQueryExecutor.scala",
    "chars": 2410,
    "preview": "package quix.dummy\n\nimport monix.eval.Task\nimport quix.api.v1.execute.{Batch, BatchColumn, BatchError}\nimport quix.api.v"
  },
  {
    "path": "quix-backend/quix-modules/quix-dummy-module/src/test/scala/quix/dummy/DummyQueryExecutorTest.scala",
    "chars": 820,
    "preview": "package quix.dummy\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.matcher.MustMatchers\nimport org."
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/it/resources/db/001_init.sql",
    "chars": 661,
    "preview": "create table empty_table\n(\n    col1 INTEGER NOT NULL\n);\n\ncreate table small_table\n(\n    col1 INTEGER NOT NULL\n);\n\nINSERT"
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/it/scala/quix/jdbc/EmbeddedMysqlDb.scala",
    "chars": 966,
    "preview": "package quix.jdbc\n\nimport com.typesafe.scalalogging.LazyLogging\nimport com.wix.mysql.EmbeddedMysql\nimport com.wix.mysql."
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/it/scala/quix/jdbc/MysqlJdbcIntegrationTest.scala",
    "chars": 1494,
    "preview": "package quix.jdbc\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.mutable.SpecWithJUnit\nimport org."
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/it/scala/quix/jdbc/MysqlJdbcQueryExecutorIntegrationTest.scala",
    "chars": 4353,
    "preview": "package quix.jdbc\n\nimport monix.execution.Scheduler.Implicits.global\nimport monix.execution.atomic.Atomic\nimport org.spe"
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/it/scala/quix/jdbc/MysqlJdbcTablesIntegrationTest.scala",
    "chars": 1510,
    "preview": "package quix.jdbc\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.mutable.SpecWithJUnit\nimport org."
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/main/scala/quix/jdbc/JdbcAutocomplete.scala",
    "chars": 632,
    "preview": "package quix.jdbc\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Autocomplete, Catalog}\n\nclass JdbcAutocomplete(val cata"
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/main/scala/quix/jdbc/JdbcCatalogs.scala",
    "chars": 2212,
    "preview": "package quix.jdbc\n\nimport java.sql.{Connection, DriverManager, ResultSet}\n\nimport monix.eval.Task\nimport quix.api.v1.db."
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/main/scala/quix/jdbc/JdbcQueryExecutor.scala",
    "chars": 2680,
    "preview": "package quix.jdbc\n\nimport java.sql.{Connection, DriverManager, ResultSet}\n\nimport com.typesafe.scalalogging.LazyLogging\n"
  },
  {
    "path": "quix-backend/quix-modules/quix-jdbc-module/src/main/scala/quix/jdbc/JdbcTables.scala",
    "chars": 1778,
    "preview": "package quix.jdbc\n\nimport java.sql.{Connection, DatabaseMetaData, DriverManager, ResultSet}\n\nimport monix.eval.Task\nimpo"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/PrestoConfig.scala",
    "chars": 328,
    "preview": "package quix.presto\n\ncase class PrestoConfig(statementsApi: String,\n                        healthApi: String,\n         "
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/QueryExecutor.scala",
    "chars": 3466,
    "preview": "package quix.presto\n\nimport java.net.{ConnectException, SocketException, SocketTimeoutException}\n\nimport monix.eval.Task"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/TestQueryExecutor.scala",
    "chars": 3805,
    "preview": "package quix.presto\n\nimport monix.eval.Task\nimport quix.api.v2.execute.{Builder, Executor, SubQuery}\nimport quix.presto."
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/TryPresto.scala",
    "chars": 1430,
    "preview": "package quix.presto\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.eval.Task\nimport monix.execution.Schedule"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/db/PrestoAutocomplete.scala",
    "chars": 1113,
    "preview": "package quix.presto.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Autocomplete, Catalog, Catalogs}\nimport quix.api.v"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/db/PrestoCatalogs.scala",
    "chars": 4555,
    "preview": "package quix.presto.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Catalog, Catalogs, Schema, Table}\nimport quix.api."
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/db/PrestoTables.scala",
    "chars": 891,
    "preview": "package quix.presto.db\n\nimport monix.eval.Task\nimport quix.api.v1.db.{Kolumn, Table, Tables}\nimport quix.api.v2.execute."
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/rest/PrestoRestApi.scala",
    "chars": 4017,
    "preview": "package quix.presto.rest\n\nimport com.fasterxml.jackson.annotation.{JsonIgnoreProperties, JsonProperty}\nimport quix.api.v"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/rest/PrestoStateClient.scala",
    "chars": 396,
    "preview": "package quix.presto.rest\n\nimport monix.eval.Task\nimport quix.api.v2.execute.SubQuery\n\ntrait PrestoStateClient {\n\n  def i"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/rest/ScalaJPrestoOps.scala",
    "chars": 1193,
    "preview": "package quix.presto.rest\n\nimport java.net.URLEncoder\n\nimport quix.api.v2.execute.SubQuery\nimport quix.presto.PrestoConfi"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/main/scala/quix/presto/rest/ScalaJPrestoStateClient.scala",
    "chars": 3601,
    "preview": "package quix.presto.rest\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.eval.Task\nimport quix.api.v1.execute"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/test/scala/quix/presto/QueryExecutorTest.scala",
    "chars": 10991,
    "preview": "package quix.presto\n\n\nimport java.util.UUID\n\nimport monix.eval.Task\nimport monix.execution.Scheduler\nimport monix.execut"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/test/scala/quix/presto/db/PrestoAutocompleteTest.scala",
    "chars": 1577,
    "preview": "package quix.presto.db\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.matcher.MustMatchers\nimport "
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/test/scala/quix/presto/db/PrestoCatalogsTest.scala",
    "chars": 2202,
    "preview": "package quix.presto.db\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.matcher.MustMatchers\nimport "
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/test/scala/quix/presto/db/PrestoTablesTest.scala",
    "chars": 766,
    "preview": "package quix.presto.db\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.matcher.MustMatchers\nimport "
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/test/scala/quix/presto/rest/ScalaJPrestoOpsTest.scala",
    "chars": 2103,
    "preview": "package quix.presto.rest\n\nimport org.specs2.matcher.MustMatchers\nimport org.specs2.mutable.SpecWithJUnit\nimport org.spec"
  },
  {
    "path": "quix-backend/quix-modules/quix-presto-module/src/test/scala/quix/presto/rest/ScalaJPrestoStateClientTest.scala",
    "chars": 1995,
    "preview": "package quix.presto.rest\n\n\nimport monix.eval.Task\nimport monix.execution.Scheduler.Implicits.traced\nimport org.specs2.ma"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/resources/activator.py",
    "chars": 1624,
    "preview": "\"\"\"\ntaken from https://raw.githubusercontent.com/pypa/virtualenv/master/virtualenv_embedded/activate_this.py\n\nActivate v"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/resources/packages.py",
    "chars": 4054,
    "preview": "class Packages:\n\n    def __init__(self, dir, index_url, extra_url):\n        self.dir = dir\n        self.index_url = inde"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/resources/quix.py",
    "chars": 1091,
    "preview": "class Quix:\n\n    def __init__(self):\n        import sys\n        from py4j.java_gateway import JavaGateway\n        from p"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonApi.scala",
    "chars": 735,
    "preview": "package quix.python\n\nsealed trait PythonMessage\n\ncase class ProcessStartSuccess(jobId: String) extends PythonMessage\n\nca"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonBridge.scala",
    "chars": 1851,
    "preview": "package quix.python\n\nimport monix.reactive.observers.Subscriber\n\n/** Python Bridge is py4j bridge to connect between met"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonConfig.scala",
    "chars": 873,
    "preview": "package quix.python\n\n\n/** Python configuration populated via .env or applications.properties of spring\n *\n * @param inde"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonExecutor.scala",
    "chars": 5493,
    "preview": "package quix.python\n\nimport java.nio.file.{Files, Path, Paths}\n\nimport com.google.common.io.Resources\nimport com.typesaf"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonModule.scala",
    "chars": 734,
    "preview": "package quix.python\n\nimport monix.eval.Task\nimport quix.api.v1.db.Db\nimport quix.api.v1.execute.StartCommand\nimport quix"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonProcessHandler.scala",
    "chars": 2038,
    "preview": "package quix.python\n\nimport java.nio.ByteBuffer\n\nimport com.google.common.base.Charsets\nimport com.typesafe.scalalogging"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/PythonRunningProcess.scala",
    "chars": 1997,
    "preview": "package quix.python\n\nimport java.nio.file.{Files, Path, Paths}\n\nimport com.typesafe.scalalogging.LazyLogging\nimport com."
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/main/scala/quix/python/TryPython.scala",
    "chars": 1995,
    "preview": "package quix.python\n\nimport java.util.UUID\n\nimport quix.api.v1.execute.ActiveQuery\nimport quix.api.v1.users.User\nimport "
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/test/scala/quix/python/PythonBridgeTest.scala",
    "chars": 1038,
    "preview": "package quix.python\n\nimport java.util\n\nimport com.google.common.collect.Lists\nimport org.specs2.matcher.MustMatchers\nimp"
  },
  {
    "path": "quix-backend/quix-modules/quix-python-module/src/test/scala/quix/python/PythonExecutorTest.scala",
    "chars": 3218,
    "preview": "package quix.python\n\nimport java.util.UUID\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.specs2.matcher."
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/pom.xml",
    "chars": 9267,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/resources/application.properties",
    "chars": 129,
    "preview": "server.port=8081\n\nlogging.level.org.springframework.web=ERROR\nlogging.level.org.hibernate=ERROR\npresto.api=http://presto"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/resources/logback-spring.xml",
    "chars": 1494,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\n    <property name=\"LOGS\" value=\"./logs\"/>\n\n    <appender name=\""
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/Server.scala",
    "chars": 317,
    "preview": "package quix.web\n\nimport com.typesafe.scalalogging.LazyLogging\nimport org.springframework.boot._\nimport quix.web.spring."
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/auth/DemoUsers.scala",
    "chars": 354,
    "preview": "package quix.web.auth\n\nimport quix.api.v1.users.{User, Users}\n\nclass DemoUsers(users : Users) extends Users  {\n  overrid"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/auth/JwtUsers.scala",
    "chars": 729,
    "preview": "package quix.web.auth\n\nimport pdi.jwt.{Jwt, JwtAlgorithm}\nimport quix.api.v1.users.{RequestNotAuthenticated, User, Users"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/controllers/DbController.scala",
    "chars": 3066,
    "preview": "package quix.web.controllers\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.springframework.stereotype.Co"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/controllers/DownloadController.scala",
    "chars": 1770,
    "preview": "package quix.web.controllers\n\nimport java.io.{Closeable, OutputStream}\n\nimport com.google.common.io.ByteStreams\nimport c"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/controllers/HealthController.scala",
    "chars": 363,
    "preview": "package quix.web.controllers\n\nimport org.springframework.stereotype.Controller\nimport org.springframework.web.bind.annot"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/controllers/HistoryController.scala",
    "chars": 1566,
    "preview": "package quix.web.controllers\n\nimport monix.execution.Scheduler.Implicits.global\nimport org.springframework.stereotype.Co"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/controllers/SqlStreamingController.scala",
    "chars": 6351,
    "preview": "package quix.web.controllers\n\nimport java.util.concurrent.ConcurrentHashMap\n\nimport com.typesafe.scalalogging.LazyLoggin"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/spring/HistoryDaoConfig.scala",
    "chars": 506,
    "preview": "package quix.web.spring\n\nimport java.time.Clock\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.execution.Sch"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/spring/SpringConfig.scala",
    "chars": 14706,
    "preview": "package quix.web.spring\n\nimport java.io.ByteArrayInputStream\nimport java.nio.file.{Files, Paths}\nimport java.util.Base64"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/main/scala/quix/web/spring/WebsocketsConfig.scala",
    "chars": 3417,
    "preview": "package quix.web.spring\n\nimport java.util\n\nimport com.typesafe.scalalogging.LazyLogging\nimport monix.execution.Scheduler"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/resources/db/001_init.sql",
    "chars": 352,
    "preview": "create table empty_table\n(\n    col1 INTEGER NOT NULL\n);\n\ncreate table small_table\n(\n    col1 INTEGER NOT NULL\n);\n\nINSERT"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/resources/logback-test.xml",
    "chars": 472,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<configuration>\n\n    <appender name=\"Console\"\n              class=\"ch.qos.logback"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/resources/test.properties",
    "chars": 1261,
    "preview": "modules=presto-prod,presto-dev,athena-prod,prod,dev,snake\n\nmodules.presto-prod.engine=presto\nmodules.presto-prod.api=htt"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/E2EContext.scala",
    "chars": 2837,
    "preview": "package quix.web\n\n\nimport org.asynchttpclient.Dsl.asyncHttpClient\nimport org.asynchttpclient.ws.{WebSocket, WebSocketLis"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/SpringConfigWithTestExecutor.scala",
    "chars": 1446,
    "preview": "package quix.web\n\nimport org.springframework.context.annotation.{Bean, Configuration, Import, Primary}\nimport quix.api.v"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/auth/DemoUsersTest.scala",
    "chars": 527,
    "preview": "package quix.web.auth\n\nimport org.specs2.mutable.SpecWithJUnit\nimport org.specs2.specification.Scope\nimport pdi.jwt.{Jwt"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/auth/JwtUsersTest.scala",
    "chars": 1143,
    "preview": "package quix.web.auth\n\nimport org.specs2.mutable.SpecWithJUnit\nimport org.specs2.specification.Scope\nimport pdi.jwt.{Jwt"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/DownloadControllerTest.scala",
    "chars": 3526,
    "preview": "package quix.web.controllers\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.Matchers\nimport org.junit"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/EmbeddedMySql.scala",
    "chars": 765,
    "preview": "package quix.web.controllers\n\nimport com.wix.mysql.EmbeddedMysql\nimport com.wix.mysql.EmbeddedMysql.anEmbeddedMysql\nimpo"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/ExecutionEventTest.scala",
    "chars": 1439,
    "preview": "package quix.web.controllers\n\nimport org.specs2.mutable.SpecWithJUnit\nimport quix.api.v1.execute.{Empty, StartCommand}\n\n"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/HealthControllerTest.scala",
    "chars": 1115,
    "preview": "package quix.web.controllers\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.Matchers\nimport org.junit"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/HistoryControllerTest.scala",
    "chars": 1509,
    "preview": "package quix.web.controllers\n\nimport com.typesafe.scalalogging.LazyLogging\nimport com.wix.mysql.ScriptResolver.classPath"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/JdbcSqlStreamingControllerTest.scala",
    "chars": 3683,
    "preview": "package quix.web.controllers\n\nimport com.typesafe.scalalogging.LazyLogging\nimport com.wix.mysql.ScriptResolver.classPath"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/PrestoDbControllerTest.scala",
    "chars": 7126,
    "preview": "package quix.web.controllers\n\nimport org.hamcrest.MatcherAssert.assertThat\nimport org.hamcrest.Matchers\nimport org.junit"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/PythonStreamingControllerTest.scala",
    "chars": 2002,
    "preview": "package quix.web.controllers\n\nimport com.typesafe.scalalogging.LazyLogging\nimport org.hamcrest.MatcherAssert.assertThat\n"
  },
  {
    "path": "quix-backend/quix-webapps/quix-web-spring/src/test/scala/quix/web/controllers/SqlStreamingControllerTest.scala",
    "chars": 4777,
    "preview": "package quix.web.controllers\n\nimport com.typesafe.scalalogging.LazyLogging\nimport org.hamcrest.MatcherAssert.assertThat\n"
  },
  {
    "path": "quix-backend/version.sbt",
    "chars": 40,
    "preview": "ThisBuild / version := \"1.0.12-SNAPSHOT\""
  },
  {
    "path": "quix-frontend/.dockerignore",
    "chars": 77,
    "preview": "**/node_modules/*\n**/dist*\nservice/statics*\n.dockerignore\nDockerfile\n.vscode\n"
  },
  {
    "path": "quix-frontend/.nvmrc",
    "chars": 2,
    "preview": "14"
  },
  {
    "path": "quix-frontend/Dockerfile",
    "chars": 727,
    "preview": "FROM node:14-buster as build\n\nRUN useradd -ms /bin/bash builduser\nUSER builduser\nCOPY --chown=builduser ./ /app\nWORKDIR "
  },
  {
    "path": "quix-frontend/README.md",
    "chars": 1002,
    "preview": "# Quix Frontend\nQuix frontend serves the UI.\n\n\n## Requirements\n* NodeJS\n* MySQL 5.7\n\n## Setup\nYou can set up your DB eit"
  },
  {
    "path": "quix-frontend/client/.dockerignore",
    "chars": 17,
    "preview": "package-lock.json"
  },
  {
    "path": "quix-frontend/client/.gitignore",
    "chars": 134,
    "preview": "node_modules\ndist\ntarget\ncoverage\nmaven\nvelocity.private.data.js\ntest/e2e/screenshots\n*npm-debug.log\n.history\n.idea\n*.im"
  },
  {
    "path": "quix-frontend/client/.npmignore",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "quix-frontend/client/.npmrc",
    "chars": 36,
    "preview": "registry=https://registry.npmjs.org\n"
  },
  {
    "path": "quix-frontend/client/.nvmrc",
    "chars": 3,
    "preview": "14\n"
  },
  {
    "path": "quix-frontend/client/README.md",
    "chars": 206,
    "preview": "## Installation\n\n```bash\n$ npm i\n$ cd ../shared\n$ npm i\n$ cd ../client\n```\n\n## Running the app\nServe a local instance of"
  },
  {
    "path": "quix-frontend/client/index.js",
    "chars": 85,
    "preview": "require('ts-node/register');\nconst {start} = require('./test/dev/server');\n\nstart();\n"
  },
  {
    "path": "quix-frontend/client/package.json",
    "chars": 3131,
    "preview": "{\n  \"name\": \"@wix/quix-client\",\n  \"version\": \"1.0.138\",\n  \"license\": \"MIT\",\n  \"description\": \"Presto-based notebook mana"
  },
  {
    "path": "quix-frontend/client/src/app.scss",
    "chars": 2004,
    "preview": "@import './lib/ui/assets/css/def/colors.def';\n@import './lib/ui/assets/css/def/defaults.def';\n@import './lib/ui/assets/c"
  },
  {
    "path": "quix-frontend/client/src/app.ts",
    "chars": 4569,
    "preview": "import { isArray } from 'lodash';\nimport { setupNotifications } from './bootstrap';\nimport create, { App } from './lib/a"
  },
  {
    "path": "quix-frontend/client/src/bootstrap.ts",
    "chars": 1353,
    "preview": "import './lib/ui/bootstrap';\nimport './lib/app';\nimport './lib/file-explorer';\nimport UrlPattern from 'url-pattern';\n\nim"
  },
  {
    "path": "quix-frontend/client/src/components/User/UserAvatar.tsx",
    "chars": 335,
    "preview": "import React from 'react';\nimport {IUser} from '@wix/quix-shared';\n\ninterface Props {\n  user: IUser;\n}\n\nexport const Use"
  },
  {
    "path": "quix-frontend/client/src/components/User/UserAvatarAndName.tsx",
    "chars": 334,
    "preview": "import React from 'react';\nimport {IUser} from '@wix/quix-shared';\nimport {UserAvatar} from './UserAvatar';\n\ninterface P"
  },
  {
    "path": "quix-frontend/client/src/components/actions/actions-testkit.ts",
    "chars": 263,
    "preview": "import {Testkit} from '../../../test/e2e/driver';\n\nconst enum Hooks {\n  Menu = 'actions-menu',\n  Delete = 'actions-delet"
  },
  {
    "path": "quix-frontend/client/src/components/actions/actions-types.ts",
    "chars": 161,
    "preview": "import {IScope as ngIscope} from 'angular';\nimport {IEntity} from '@wix/quix-shared';\n\nexport interface IScope extends n"
  }
]

// ... and 985 more files (download for full content)

About this extraction

This page contains the full source code of the wix/quix GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1185 files (3.1 MB), approximately 900.3k tokens, and a symbol index with 2476 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!