diff --git a/.github/workflows/build-app-pro-beta.yaml b/.github/workflows/build-app-pro-beta.yaml index e9013a810..7b2681c28 100644 --- a/.github/workflows/build-app-pro-beta.yaml +++ b/.github/workflows/build-app-pro-beta.yaml @@ -39,7 +39,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 458d8843318c2f65aae6524bbea30513d88f4bf6 + ref: 8a4dc2732a7097b5c4c48b4feb62609111cdf3e0 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-app-pro.yaml b/.github/workflows/build-app-pro.yaml index 372b277f3..e16d302d5 100644 --- a/.github/workflows/build-app-pro.yaml +++ b/.github/workflows/build-app-pro.yaml @@ -39,7 +39,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 458d8843318c2f65aae6524bbea30513d88f4bf6 + ref: 8a4dc2732a7097b5c4c48b4feb62609111cdf3e0 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-cloud-pro.yaml b/.github/workflows/build-cloud-pro.yaml index 881460a45..66a624fca 100644 --- a/.github/workflows/build-cloud-pro.yaml +++ b/.github/workflows/build-cloud-pro.yaml @@ -39,7 +39,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 458d8843318c2f65aae6524bbea30513d88f4bf6 + ref: 8a4dc2732a7097b5c4c48b4feb62609111cdf3e0 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-docker-pro.yaml b/.github/workflows/build-docker-pro.yaml index 20a978f75..cf7c7644d 100644 --- a/.github/workflows/build-docker-pro.yaml +++ b/.github/workflows/build-docker-pro.yaml @@ -44,7 +44,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 458d8843318c2f65aae6524bbea30513d88f4bf6 + ref: 8a4dc2732a7097b5c4c48b4feb62609111cdf3e0 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.github/workflows/build-npm-pro.yaml b/.github/workflows/build-npm-pro.yaml index c2fdaf337..de8f2fbc2 100644 --- a/.github/workflows/build-npm-pro.yaml +++ b/.github/workflows/build-npm-pro.yaml @@ -32,7 +32,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 458d8843318c2f65aae6524bbea30513d88f4bf6 + ref: 8a4dc2732a7097b5c4c48b4feb62609111cdf3e0 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro @@ -98,3 +98,8 @@ jobs: cd .. cd dbgate-merged/plugins/dbgate-plugin-cosmosdb npm publish + - name: Publish dbgate-plugin-firestore + run: | + cd .. + cd dbgate-merged/plugins/dbgate-plugin-firestore + npm publish diff --git a/.github/workflows/e2e-pro.yaml b/.github/workflows/e2e-pro.yaml index e159e4547..bc731b80b 100644 --- a/.github/workflows/e2e-pro.yaml +++ b/.github/workflows/e2e-pro.yaml @@ -26,7 +26,7 @@ jobs: repository: dbgate/dbgate-pro token: ${{ secrets.GH_TOKEN }} path: dbgate-pro - ref: 458d8843318c2f65aae6524bbea30513d88f4bf6 + ref: 8a4dc2732a7097b5c4c48b4feb62609111cdf3e0 - name: Merge dbgate/dbgate-pro run: | mkdir ../dbgate-pro diff --git a/.vscode/launch.json b/.vscode/launch.json index 020229cbc..4c512c537 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,20 +1,41 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "type": "node", - "request": "launch", - "name": "Launch API", - "skipFiles": [ - "/**" - ], - "program": "${workspaceFolder}/packages/api/src/index.js", - "outFiles": [ - "${workspaceFolder}/**/*.js" - ] - } - ] -} \ No newline at end of file + "version": "0.2.0", + "configurations": [ + { + "name": "Debug App", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/packages/api/src/index.js", + "envFile": "${workspaceFolder}/packages/api/.env", + "args": ["--listen-api"], + "console": "integratedTerminal", + "restart": true, + "runtimeExecutable": "node", + "skipFiles": ["/**"] + }, + { + "name": "Debug App (Break on Start)", + "type": "node", + "request": "launch", + "program": "${workspaceFolder}/packages/api/src/index.js", + "args": ["--listen-api"], + "envFile": "${workspaceFolder}/.env", + "console": "integratedTerminal", + "restart": true, + "runtimeExecutable": "node", + "skipFiles": ["/**"], + "stopOnEntry": true + }, + { + "name": "Attach to Process", + "type": "node", + "request": "attach", + "port": 9229, + "restart": true, + "localRoot": "${workspaceFolder}", + "remoteRoot": "${workspaceFolder}", + "skipFiles": ["/**"] + } + ] +} + diff --git a/e2e-tests/cypress/e2e/browse-data.cy.js b/e2e-tests/cypress/e2e/browse-data.cy.js index ded03fd8f..8f9914b7a 100644 --- a/e2e-tests/cypress/e2e/browse-data.cy.js +++ b/e2e-tests/cypress/e2e/browse-data.cy.js @@ -303,7 +303,8 @@ describe('Data browser data', () => { }); it('Plugin tab', () => { - cy.testid('WidgetIconPanel_plugins').click(); + cy.testid('WidgetIconPanel_settings').click(); + cy.contains('Manage plugins').click(); cy.contains('dbgate-plugin-theme-total-white').click(); // text from plugin markdown cy.contains('Total white theme'); @@ -380,20 +381,25 @@ describe('Data browser data', () => { cy.themeshot('compare-database-settings'); }); - it('Query editor - AI assistant', () => { + it('Database chat', () => { cy.contains('MySql-connection').click(); cy.contains('MyChinook').click(); cy.testid('TabsPanel_buttonNewObject').click(); - cy.testid('NewObjectModal_query').click(); - cy.testid('QueryTab_switchAiAssistantButton').click(); - cy.testid('QueryAiAssistant_allowSendToAiServiceButton').click(); - cy.testid('ConfirmModal_okButton').click(); - cy.testid('QueryAiAssistant_promptInput').type('album names'); - cy.testid('QueryAiAssistant_queryFromQuestionButton').click(); - cy.contains('Use this', { timeout: 10000 }).click(); - cy.testid('QueryTab_executeButton').click(); - cy.contains('Balls to the Wall'); - cy.themeshot('ai-assistant'); + cy.testid('NewObjectModal_databaseChat').click(); + cy.wait(1000); + cy.get('body').realType('find most popular artist'); + cy.get('body').realPress('{enter}'); + cy.testid('DatabaseChatTab_executeAllQueries', { timeout: 20000 }).click(); + cy.wait(4000); + // cy.contains('Iron Maiden'); + cy.themeshot('database-chat'); + + // cy.testid('DatabaseChatTab_promptInput').click(); + // cy.get('body').realType('I need top 10 songs with the biggest income'); + // cy.get('body').realPress('{enter}'); + // cy.contains('Hot Girl', { timeout: 20000 }); + // cy.wait(1000); + // cy.themeshot('database-chat'); }); it('Modify data', () => { diff --git a/package.json b/package.json index f1cd414a5..81122113c 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "private": true, - "version": "6.5.6", + "version": "6.5.7-premium-beta.3", "name": "dbgate-all", "workspaces": [ "packages/*", diff --git a/packages/api/.env b/packages/api/.env index d07e42182..9ab8fc3d2 100644 --- a/packages/api/.env +++ b/packages/api/.env @@ -2,6 +2,8 @@ DEVMODE=1 SHELL_SCRIPTING=1 ALLOW_DBGATE_PRIVATE_CLOUD=1 DEVWEB=1 +# LOCAL_AI_GATEWAY=true + # REDIRECT_TO_DBGATE_CLOUD_LOGIN=1 # PROD_DBGATE_CLOUD=1 # PROD_DBGATE_IDENTITY=1 @@ -14,7 +16,6 @@ DEVWEB=1 # DISABLE_SHELL=1 # HIDE_APP_EDITOR=1 - # DEVWEB=1 # LOGINS=admin,test diff --git a/packages/api/package.json b/packages/api/package.json index 9352b5b73..bedb46ace 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -68,6 +68,7 @@ }, "scripts": { "start": "env-cmd -f .env node src/index.js --listen-api", + "start:debug": "env-cmd -f .env node --inspect src/index.js --listen-api", "start:portal": "env-cmd -f env/portal/.env node src/index.js --listen-api", "start:singledb": "env-cmd -f env/singledb/.env node src/index.js --listen-api", "start:auth": "env-cmd -f env/auth/.env node src/index.js --listen-api", diff --git a/packages/api/src/controllers/cloud.js b/packages/api/src/controllers/cloud.js index 8dae42c00..61a3a9003 100644 --- a/packages/api/src/controllers/cloud.js +++ b/packages/api/src/controllers/cloud.js @@ -16,6 +16,7 @@ const { getConnectionLabel, getLogger, extractErrorLogData } = require('dbgate-t const logger = getLogger('cloud'); const _ = require('lodash'); const fs = require('fs-extra'); +const { getAiGatewayServer } = require('../utility/authProxy'); module.exports = { publicFiles_meta: true, @@ -276,4 +277,17 @@ module.exports = { const resp = await callCloudApiPost(`content-folders/remove-user/${folid}`, { email }); return resp; }, + + getAiGateway_meta: true, + async getAiGateway() { + return getAiGatewayServer(); + }, + + // chatStream_meta: { + // raw: true, + // method: 'post', + // }, + // chatStream(req, res) { + // callChatStream(req.body, res); + // }, }; diff --git a/packages/api/src/utility/authProxy.js b/packages/api/src/utility/authProxy.js index 060cc7f74..71803fc3a 100644 --- a/packages/api/src/utility/authProxy.js +++ b/packages/api/src/utility/authProxy.js @@ -46,6 +46,10 @@ async function tryToGetRefreshedLicense(oldLicenseKey) { }; } +function getAiGatewayServer() { + return {}; +} + module.exports = { isAuthProxySupported, authProxyGetRedirectUrl, @@ -59,4 +63,5 @@ module.exports = { callRefactorSqlQueryApi, getLicenseHttpHeaders, tryToGetRefreshedLicense, + getAiGatewayServer, }; diff --git a/packages/datalib/src/CollectionGridDisplay.ts b/packages/datalib/src/CollectionGridDisplay.ts index 823d9508c..796294866 100644 --- a/packages/datalib/src/CollectionGridDisplay.ts +++ b/packages/datalib/src/CollectionGridDisplay.ts @@ -70,6 +70,7 @@ function getDisplayColumn(basePath, columnName, display: CollectionGridDisplay) isPartitionKey: !!display?.collection?.partitionKey?.find(x => x.columnName == uniqueName), isClusterKey: !!display?.collection?.clusterKey?.find(x => x.columnName == uniqueName), isUniqueKey: !!display?.collection?.uniqueKey?.find(x => x.columnName == uniqueName), + hasAutoValue: !!display?.collection?.autoValueColumns?.find(x => x.columnName == uniqueName), }; } diff --git a/packages/filterparser/src/parseFilter.ts b/packages/filterparser/src/parseFilter.ts index 144b40f28..8b24c6cc9 100644 --- a/packages/filterparser/src/parseFilter.ts +++ b/packages/filterparser/src/parseFilter.ts @@ -6,11 +6,13 @@ import { hexStringToArray, parseNumberSafe } from 'dbgate-tools'; import { FilterBehaviour, TransformType } from 'dbgate-types'; const binaryCondition = - (operator, numberDualTesting = false) => + (operator, filterBehaviour: FilterBehaviour = {}) => value => { + const { passNumbers, allowNumberDualTesting } = filterBehaviour; const numValue = parseNumberSafe(value); + if ( - numberDualTesting && + allowNumberDualTesting && // @ts-ignore !isNaN(numValue) ) { @@ -43,6 +45,21 @@ const binaryCondition = }; } + // @ts-ignore + if (passNumbers && !isNaN(numValue)) { + return { + conditionType: 'binary', + operator, + left: { + exprType: 'placeholder', + }, + right: { + exprType: 'value', + value: numValue, + }, + }; + } + return { conditionType: 'binary', operator, @@ -462,18 +479,18 @@ const createParser = (filterBehaviour: FilterBehaviour) => { null: () => word('NULL').map(unaryCondition('isNull')), isEmpty: r => r.empty.map(unaryCondition('isEmpty')), isNotEmpty: r => r.not.then(r.empty).map(unaryCondition('isNotEmpty')), - true: () => P.regexp(/true/i).map(binaryFixedValueCondition('1')), - false: () => P.regexp(/false/i).map(binaryFixedValueCondition('0')), + true: () => P.regexp(/true/i).map(binaryFixedValueCondition(filterBehaviour.passBooleans ? true : '1')), + false: () => P.regexp(/false/i).map(binaryFixedValueCondition(filterBehaviour.passBooleans ? false : '0')), trueNum: () => word('1').map(binaryFixedValueCondition('1')), falseNum: () => word('0').map(binaryFixedValueCondition('0')), - eq: r => word('=').then(r.value).map(binaryCondition('=', filterBehaviour.allowNumberDualTesting)), - ne: r => word('!=').then(r.value).map(binaryCondition('<>', filterBehaviour.allowNumberDualTesting)), - ne2: r => word('<>').then(r.value).map(binaryCondition('<>', filterBehaviour.allowNumberDualTesting)), - le: r => word('<=').then(r.value).map(binaryCondition('<=', filterBehaviour.allowNumberDualTesting)), - ge: r => word('>=').then(r.value).map(binaryCondition('>=', filterBehaviour.allowNumberDualTesting)), - lt: r => word('<').then(r.value).map(binaryCondition('<', filterBehaviour.allowNumberDualTesting)), - gt: r => word('>').then(r.value).map(binaryCondition('>', filterBehaviour.allowNumberDualTesting)), + eq: r => word('=').then(r.value).map(binaryCondition('=', filterBehaviour)), + ne: r => word('!=').then(r.value).map(binaryCondition('<>', filterBehaviour)), + ne2: r => word('<>').then(r.value).map(binaryCondition('<>', filterBehaviour)), + le: r => word('<=').then(r.value).map(binaryCondition('<=', filterBehaviour)), + ge: r => word('>=').then(r.value).map(binaryCondition('>=', filterBehaviour)), + lt: r => word('<').then(r.value).map(binaryCondition('<', filterBehaviour)), + gt: r => word('>').then(r.value).map(binaryCondition('>', filterBehaviour)), startsWith: r => word('^').then(r.value).map(likeCondition('like', '#VALUE#%')), endsWith: r => word('$').then(r.value).map(likeCondition('like', '%#VALUE#')), contains: r => word('+').then(r.value).map(likeCondition('like', '%#VALUE#%')), @@ -526,8 +543,12 @@ const createParser = (filterBehaviour: FilterBehaviour) => { allowedElements.push('exists', 'notExists'); } - if (filterBehaviour.supportArrayTesting) { - allowedElements.push('emptyArray', 'notEmptyArray'); + if (filterBehaviour.supportEmptyArrayTesting) { + allowedElements.push('emptyArray'); + } + + if (filterBehaviour.supportNotEmptyArrayTesting) { + allowedElements.push('notEmptyArray'); } if (filterBehaviour.supportNullTesting) { diff --git a/packages/tools/src/DatabaseAnalyser.ts b/packages/tools/src/DatabaseAnalyser.ts index a7750241d..2c37d0293 100644 --- a/packages/tools/src/DatabaseAnalyser.ts +++ b/packages/tools/src/DatabaseAnalyser.ts @@ -42,8 +42,7 @@ function areDifferentRowCounts(db1: DatabaseInfo, db2: DatabaseInfo) { } return false; } - -export class DatabaseAnalyser { +export class DatabaseAnalyser { structure: DatabaseInfo; modifications: DatabaseModification[]; singleObjectFilter: any; @@ -51,7 +50,7 @@ export class DatabaseAnalyser { dialect: SqlDialect; logger: Logger; - constructor(public dbhan: DatabaseHandle, public driver: EngineDriver, version) { + constructor(public dbhan: DatabaseHandle, public driver: EngineDriver, version) { this.dialect = (driver?.dialectByVersion && driver?.dialectByVersion(version)) || driver?.dialect; this.logger = logger; } diff --git a/packages/tools/src/filterBehaviours.ts b/packages/tools/src/filterBehaviours.ts index f600c2e3c..61ebdf5a6 100644 --- a/packages/tools/src/filterBehaviours.ts +++ b/packages/tools/src/filterBehaviours.ts @@ -24,6 +24,7 @@ export const stringFilterBehaviour: FilterBehaviour = { export const logicalFilterBehaviour: FilterBehaviour = { supportBooleanValues: true, supportNullTesting: true, + supportBooleanOrNull: true, supportSqlCondition: true, }; @@ -36,7 +37,8 @@ export const datetimeFilterBehaviour: FilterBehaviour = { export const mongoFilterBehaviour: FilterBehaviour = { supportEquals: true, - supportArrayTesting: true, + supportEmptyArrayTesting: true, + supportNotEmptyArrayTesting: true, supportNumberLikeComparison: true, supportStringInclusion: true, supportBooleanValues: true, @@ -57,11 +59,38 @@ export const evalFilterBehaviour: FilterBehaviour = { allowStringToken: true, }; +export const firestoreFilterBehaviours: FilterBehaviour = { + supportEquals: true, + supportEmpty: false, + supportNumberLikeComparison: true, + supportDatetimeComparison: false, + supportNullTesting: true, + supportBooleanValues: true, + supportEmptyArrayTesting: true, + + supportStringInclusion: false, + supportDatetimeSymbols: false, + supportExistsTesting: false, + supportSqlCondition: false, + + allowStringToken: true, + allowNumberToken: true, + allowHexString: true, + allowNumberDualTesting: false, + allowObjectIdTesting: false, + + passBooleans: true, + passNumbers: true, + + disableOr: true, +}; + export const standardFilterBehaviours: { [id: string]: FilterBehaviour } = { numberFilterBehaviour, stringFilterBehaviour, logicalFilterBehaviour, datetimeFilterBehaviour, mongoFilterBehaviour, + firestoreFilterBehaviours, evalFilterBehaviour, }; diff --git a/packages/tools/src/stringTools.ts b/packages/tools/src/stringTools.ts index 18317d13b..3f8675a8a 100644 --- a/packages/tools/src/stringTools.ts +++ b/packages/tools/src/stringTools.ts @@ -75,6 +75,37 @@ export function parseCellValue(value, editorTypes?: DataEditorTypesBehaviour) { } } + if (editorTypes?.parseGeopointAsDollar) { + const m = value.match(/^([\d\.]+)\s*°\s*([NS]),\s*([\d\.]+)\s*°\s*([EW])$/i); + if (m) { + let latitude = parseFloat(m[1]); + const latDir = m[2].toUpperCase(); + let longitude = parseFloat(m[3]); + const lonDir = m[4].toUpperCase(); + + if (latDir === 'S') latitude = -latitude; + if (lonDir === 'W') longitude = -longitude; + + return { + $geoPoint: { + latitude, + longitude, + }, + }; + } + } + + if (editorTypes?.parseFsDocumentRefAsDollar) { + const trimmedValue = value.replace(/\s/g, ''); + if (trimmedValue.startsWith('$ref:')) { + return { + $fsDocumentRef: { + documentPath: trimmedValue.slice(5), + }, + }; + } + } + if (editorTypes?.parseJsonNull) { if (value == 'null') return null; } @@ -246,6 +277,32 @@ export function stringifyCellValue( } } + if (editorTypes?.parseGeopointAsDollar) { + if (value?.$geoPoint) { + const { latitude, longitude } = value.$geoPoint; + if (_isNumber(latitude) && _isNumber(longitude)) { + const latAbs = Math.abs(latitude); + const lonAbs = Math.abs(longitude); + const latDir = latitude >= 0 ? 'N' : 'S'; + const lonDir = longitude >= 0 ? 'E' : 'W'; + + return { + value: `${latAbs}° ${latDir}, ${lonAbs}° ${lonDir}`, + gridStyle: 'valueCellStyle', + }; + } + } + } + + if (editorTypes?.parseFsDocumentRefAsDollar) { + if (value?.$fsDocumentRef) { + return { + value: `$ref: ${value.$fsDocumentRef.documentPath ?? ''}`, + gridStyle: 'valueCellStyle', + }; + } + } + if (_isArray(value)) { switch (intent) { case 'gridCellIntent': diff --git a/packages/types/dbinfo.d.ts b/packages/types/dbinfo.d.ts index 0089db292..ba4d33a4c 100644 --- a/packages/types/dbinfo.d.ts +++ b/packages/types/dbinfo.d.ts @@ -108,6 +108,8 @@ export interface CollectionInfo extends DatabaseObjectInfo { // unique combination of columns (should be contatenation of partitionKey and clusterKey) uniqueKey?: ColumnReference[]; + autoValueColumns?: ColumnReference[]; + // partition key columns partitionKey?: ColumnReference[]; diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 9a99625a1..c74010947 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -23,6 +23,28 @@ export interface StreamOptions { info?: (info) => void; } +export type CollectionOperationInfo = + | { + type: 'createCollection'; + collection: { + name: string; + }; + } + | { + type: 'dropCollection'; + collection: string; + } + | { + type: 'renameCollection'; + collection: string; + newName: string; + } + | { + type: 'cloneCollection'; + collection: string; + newName: string; + }; + export interface RunScriptOptions { useTransaction: boolean; logScriptItems?: boolean; @@ -120,6 +142,8 @@ export interface DataEditorTypesBehaviour { parseHexAsBuffer?: boolean; parseObjectIdAsDollar?: boolean; parseDateAsDollar?: boolean; + parseGeopointAsDollar?: boolean; + parseFsDocumentRefAsDollar?: boolean; explicitDataType?: boolean; supportNumberType?: boolean; @@ -217,7 +241,7 @@ export interface EngineDriver extends FilterBehaviourProvider { defaultSocketPath?: string; authTypeLabel?: string; importExportArgs?: any[]; - connect({ server, port, user, password, database }): Promise>; + connect({ server, port, user, password, database, certificateJson }): Promise>; close(dbhan: DatabaseHandle): Promise; query(dbhan: DatabaseHandle, sql: string, options?: QueryOptions): Promise; stream(dbhan: DatabaseHandle, sql: string, options: StreamOptions); @@ -264,7 +288,7 @@ export interface EngineDriver extends FilterBehaviourProvider { dropDatabase(dbhan: DatabaseHandle, name: string): Promise; getQuerySplitterOptions(usage: 'stream' | 'script' | 'editor' | 'import'): any; script(dbhan: DatabaseHandle, sql: string, options?: RunScriptOptions): Promise; - operation(dbhan: DatabaseHandle, operation: {}, options?: RunScriptOptions): Promise; + operation(dbhan: DatabaseHandle, operation: CollectionOperationInfo, options?: RunScriptOptions): Promise; getNewObjectTemplates(): NewObjectTemplate[]; // direct call of dbhan.client method, only some methods could be supported, on only some drivers callMethod(dbhan: DatabaseHandle, method, args); diff --git a/packages/types/filter-type.d.ts b/packages/types/filter-type.d.ts index d3fd5dde7..c8b6a8897 100644 --- a/packages/types/filter-type.d.ts +++ b/packages/types/filter-type.d.ts @@ -9,11 +9,18 @@ export interface FilterBehaviour { supportExistsTesting?: boolean; supportBooleanValues?: boolean; supportSqlCondition?: boolean; - supportArrayTesting?: boolean; + supportEmptyArrayTesting?: boolean; + supportNotEmptyArrayTesting?: boolean; + supportBooleanOrNull?: boolean; allowStringToken?: boolean; allowNumberToken?: boolean; allowHexString?: boolean; allowNumberDualTesting?: boolean; allowObjectIdTesting?: boolean; + + passBooleans?: boolean; + passNumbers?: boolean; + + disableOr?: boolean; } diff --git a/packages/types/query.d.ts b/packages/types/query.d.ts index 633c1b01d..94836298f 100644 --- a/packages/types/query.d.ts +++ b/packages/types/query.d.ts @@ -15,3 +15,92 @@ export interface QueryResult { columns?: QueryResultColumn[]; rowsAffected?: number; } + +export type LeftOperand = { + exprType: 'placeholder' | 'column'; + columnName?: string; +}; + +export type RightOperand = { + exprType: 'value'; + value: any; +}; + +export type BinaryCondition = { + conditionType: 'binary'; + operator: '=' | '!=' | '<>' | '<' | '<=' | '>' | '>='; + left: LeftOperand; + right: RightOperand; +}; + +export type AndCondition = { + conditionType: 'and'; + conditions: FilterCondition[]; +}; + +export type OrCondition = { + conditionType: 'or'; + conditions: FilterCondition[]; +}; + +export type NullCondition = { + conditionType: 'isNull' | 'isNotNull'; + expr: LeftOperand; +}; + +export type NotCondition = { + conditionType: 'not'; + condition: FilterCondition; +}; + +export type LikeCondition = { + conditionType: 'like'; + left: LeftOperand; + right: RightOperand; +}; + +export type PredicateCondition = { + conditionType: 'specificPredicate'; + predicate: 'exists' | 'notExists' | 'emptyArray' | 'notEmptyArray'; + expr: LeftOperand; +}; + +export type InCondition = { + conditionType: 'in'; + expr: LeftOperand; + values: any[]; +}; + +export type FilterCondition = + | BinaryCondition + | AndCondition + | OrCondition + | NullCondition + | NotCondition + | LikeCondition + | PredicateCondition + | InCondition; + +export type SortItem = { + columnName: string; + direction?: 'ASC' | 'DESC'; +}; + +export type AggregateColumn = { + aggregateFunction: 'count' | 'sum' | 'avg' | 'min' | 'max'; + columnArgument?: string; + alias: string; +}; + +export type CollectionAggregate = { + condition?: FilterCondition; + groupByColumns: string[]; + aggregateColumns: AggregateColumn[]; +}; + +export type FullQueryOptions = { + condition?: FilterCondition; + sort?: SortItem[]; + limit?: number; + skip?: number; +}; diff --git a/packages/web/package.json b/packages/web/package.json index 8874f20a8..b485383f3 100644 --- a/packages/web/package.json +++ b/packages/web/package.json @@ -69,6 +69,7 @@ "highlight.js": "^11.11.1", "interval-operations": "^1.0.7", "leaflet": "^1.8.0", + "openai": "^5.10.1", "wellknown": "^0.5.0", "xml-formatter": "^3.6.4" } diff --git a/packages/web/src/appobj/DatabaseAppObject.svelte b/packages/web/src/appobj/DatabaseAppObject.svelte index b998091eb..6233e5734 100644 --- a/packages/web/src/appobj/DatabaseAppObject.svelte +++ b/packages/web/src/appobj/DatabaseAppObject.svelte @@ -71,7 +71,8 @@ const handleDropDatabase = () => { showModal(ConfirmModal, { message: _t('database.dropConfirm', { - defaultMessage: 'Really drop database {name}? All opened sessions with this database will be forcefully closed.', + defaultMessage: + 'Really drop database {name}? All opened sessions with this database will be forcefully closed.', values: { name }, }), onConfirm: () => @@ -207,6 +208,18 @@ // showSnackbarSuccess(`Saved to archive ${resp.archiveFolder}`); }; + const handleDatabaseChat = () => { + openNewTab({ + title: 'Chat', + icon: 'img ai', + tabComponent: 'DatabaseChatTab', + props: { + conid: connection._id, + database: name, + }, + }); + }; + const handleCompareWithCurrentDb = () => { openNewTab( { @@ -312,7 +325,8 @@ const handleGenerateDropAllObjectsScript = () => { showModal(ConfirmModal, { message: _t('database.dropAllObjectsConfirm', { - defaultMessage: 'This will generate script, after executing this script all objects in {name} will be dropped. Continue?', + defaultMessage: + 'This will generate script, after executing this script all objects in {name} will be dropped. Continue?', values: { name }, }), @@ -364,7 +378,9 @@ await dbgateApi.executeQuery(${JSON.stringify( const handleShowDataDeployer = () => { showModal(ChooseArchiveFolderModal, { - message: _t('database.chooseArchiveFolderForDataDeployer', { defaultMessage: 'Choose archive folder for data deployer' }), + message: _t('database.chooseArchiveFolderForDataDeployer', { + defaultMessage: 'Choose archive folder for data deployer', + }), onConfirm: archiveFolder => { openNewTab( { @@ -396,57 +412,109 @@ await dbgateApi.executeQuery(${JSON.stringify( driver?.databaseEngineTypes?.includes('sql') || driver?.databaseEngineTypes?.includes('document'); return [ - hasPermission(`dbops/query`) && { onClick: handleNewQuery, text: _t('database.newQuery', { defaultMessage: 'New query' }), isNewQuery: true }, + hasPermission(`dbops/query`) && { + onClick: handleNewQuery, + text: _t('database.newQuery', { defaultMessage: 'New query' }), + isNewQuery: true, + }, hasPermission(`dbops/model/edit`) && !connection.isReadOnly && - driver?.databaseEngineTypes?.includes('sql') && { onClick: handleNewTable, text: _t('database.newTable', { defaultMessage: 'New table' }) }, + driver?.databaseEngineTypes?.includes('sql') && { + onClick: handleNewTable, + text: _t('database.newTable', { defaultMessage: 'New table' }), + }, !connection.isReadOnly && hasPermission(`dbops/model/edit`) && driver?.databaseEngineTypes?.includes('document') && { onClick: handleNewCollection, - text: _t('database.newCollection', { defaultMessage: 'New {collectionLabel}', values: { collectionLabel: driver?.collectionSingularLabel ?? 'collection/container' } }), + text: _t('database.newCollection', { + defaultMessage: 'New {collectionLabel}', + values: { collectionLabel: driver?.collectionSingularLabel ?? 'collection/container' }, + }), }, hasPermission(`dbops/query`) && driver?.databaseEngineTypes?.includes('sql') && - isProApp() && { onClick: handleQueryDesigner, text: _t('database.designQuery', { defaultMessage: 'Design query' }) }, + isProApp() && { + onClick: handleQueryDesigner, + text: _t('database.designQuery', { defaultMessage: 'Design query' }), + }, driver?.databaseEngineTypes?.includes('sql') && isProApp() && { onClick: handleNewPerspective, text: _t('database.designPerspectiveQuery', { defaultMessage: 'Design perspective query' }), }, - connection.useSeparateSchemas && { onClick: handleRefreshSchemas, text: _t('database.refreshSchemas', { defaultMessage: 'Refresh schemas' }) }, + connection.useSeparateSchemas && { + onClick: handleRefreshSchemas, + text: _t('database.refreshSchemas', { defaultMessage: 'Refresh schemas' }), + }, { divider: true }, isSqlOrDoc && !connection.isReadOnly && - hasPermission(`dbops/import`) && { onClick: handleImport, text: _t('database.import', { defaultMessage: 'Import' }) }, - isSqlOrDoc && hasPermission(`dbops/export`) && { onClick: handleExport, text: _t('database.export', { defaultMessage: 'Export' }) }, + hasPermission(`dbops/import`) && { + onClick: handleImport, + text: _t('database.import', { defaultMessage: 'Import' }), + }, + isSqlOrDoc && + hasPermission(`dbops/export`) && { + onClick: handleExport, + text: _t('database.export', { defaultMessage: 'Export' }), + }, driver?.supportsDatabaseRestore && isProApp() && hasPermission(`dbops/sql-dump/import`) && - !connection.isReadOnly && { onClick: handleRestoreDatabase, text: _t('database.restoreDatabaseBackup', { defaultMessage: 'Restore database backup' }) }, + !connection.isReadOnly && { + onClick: handleRestoreDatabase, + text: _t('database.restoreDatabaseBackup', { defaultMessage: 'Restore database backup' }), + }, driver?.supportsDatabaseBackup && isProApp() && - hasPermission(`dbops/sql-dump/export`) && { onClick: handleBackupDatabase, text: _t('database.createDatabaseBackup', { defaultMessage: 'Create database backup' }) }, + hasPermission(`dbops/sql-dump/export`) && { + onClick: handleBackupDatabase, + text: _t('database.createDatabaseBackup', { defaultMessage: 'Create database backup' }), + }, isSqlOrDoc && !connection.isReadOnly && !connection.singleDatabase && isSqlOrDoc && - hasPermission(`dbops/dropdb`) && { onClick: handleDropDatabase, text: _t('database.dropDatabase', { defaultMessage: 'Drop database' }) }, + hasPermission(`dbops/dropdb`) && { + onClick: handleDropDatabase, + text: _t('database.dropDatabase', { defaultMessage: 'Drop database' }), + }, { divider: true }, - driver?.databaseEngineTypes?.includes('sql') && { onClick: handleCopyName, text: _t('database.copyDatabaseName', { defaultMessage: 'Copy database name' }) }, - driver?.databaseEngineTypes?.includes('sql') && { onClick: handleShowDiagram, text: _t('database.showDiagram', { defaultMessage: 'Show diagram' }) }, + driver?.databaseEngineTypes?.includes('sql') && { + onClick: handleCopyName, + text: _t('database.copyDatabaseName', { defaultMessage: 'Copy database name' }), + }, + driver?.databaseEngineTypes?.includes('sql') && { + onClick: handleShowDiagram, + text: _t('database.showDiagram', { defaultMessage: 'Show diagram' }), + }, driver?.databaseEngineTypes?.includes('sql') && - hasPermission(`dbops/sql-generator`) && { onClick: handleSqlGenerator, text: _t('database.sqlGenerator', { defaultMessage: 'SQL Generator' }) }, + hasPermission(`dbops/sql-generator`) && { + onClick: handleSqlGenerator, + text: _t('database.sqlGenerator', { defaultMessage: 'SQL Generator' }), + }, driver?.supportsDatabaseProfiler && isProApp() && - hasPermission(`dbops/profiler`) && { onClick: handleDatabaseProfiler, text: _t('database.databaseProfiler', { defaultMessage: 'Database profiler' }) }, + hasPermission(`dbops/profiler`) && { + onClick: handleDatabaseProfiler, + text: _t('database.databaseProfiler', { defaultMessage: 'Database profiler' }), + }, // isSqlOrDoc && // isSqlOrDoc && // hasPermission(`dbops/model/view`) && { onClick: handleOpenJsonModel, text: 'Open model as JSON' }, isSqlOrDoc && isProApp() && - hasPermission(`dbops/model/view`) && { onClick: handleExportModel, text: _t('database.exportDbModel', { defaultMessage: 'Export DB model' }) }, + hasPermission(`dbops/model/view`) && { + onClick: handleExportModel, + text: _t('database.exportDbModel', { defaultMessage: 'Export DB model' }), + }, + isProApp() && + driver?.databaseEngineTypes?.includes('sql') && { + onClick: handleDatabaseChat, + text: _t('database.databaseChat', { defaultMessage: 'Database chat' }), + }, isSqlOrDoc && _.get($currentDatabase, 'connection._id') && hasPermission('dbops/model/compare') && @@ -455,14 +523,23 @@ await dbgateApi.executeQuery(${JSON.stringify( (_.get($currentDatabase, 'connection._id') == _.get(connection, '_id') && _.get($currentDatabase, 'name') != _.get(connection, 'name'))) && { onClick: handleCompareWithCurrentDb, - text: _t('database.compareWithCurrentDb', { defaultMessage: 'Compare with {name}', values: { name: _.get($currentDatabase, 'name') } }), + text: _t('database.compareWithCurrentDb', { + defaultMessage: 'Compare with {name}', + values: { name: _.get($currentDatabase, 'name') }, + }), }, - driver?.databaseEngineTypes?.includes('keyvalue') && { onClick: handleGenerateScript, text: _t('database.generateScript', { defaultMessage: 'Generate script' }) }, + driver?.databaseEngineTypes?.includes('keyvalue') && { + onClick: handleGenerateScript, + text: _t('database.generateScript', { defaultMessage: 'Generate script' }), + }, ($openedSingleDatabaseConnections.includes(connection._id) || (_.get($currentDatabase, 'connection._id') == _.get(connection, '_id') && - _.get($currentDatabase, 'name') == name)) && { onClick: handleDisconnect, text: _t('database.disconnect', { defaultMessage: 'Disconnect' }) }, + _.get($currentDatabase, 'name') == name)) && { + onClick: handleDisconnect, + text: _t('database.disconnect', { defaultMessage: 'Disconnect' }), + }, { divider: true }, diff --git a/packages/web/src/celldata/XmlCellView.svelte b/packages/web/src/celldata/XmlCellView.svelte index ca18a81dd..a95e9a1b1 100644 --- a/packages/web/src/celldata/XmlCellView.svelte +++ b/packages/web/src/celldata/XmlCellView.svelte @@ -1,5 +1,5 @@ diff --git a/packages/web/src/commands/stdCommands.ts b/packages/web/src/commands/stdCommands.ts index a1fc8f2c1..e37bd9b1a 100644 --- a/packages/web/src/commands/stdCommands.ts +++ b/packages/web/src/commands/stdCommands.ts @@ -714,6 +714,28 @@ if (isProApp()) { ); }, }); + + registerCommand({ + id: 'database.chat', + category: 'Database', + name: 'Database chat', + toolbar: true, + icon: 'icon ai', + testEnabled: () => + getCurrentDatabase() != null && + findEngineDriver(getCurrentDatabase()?.connection, getExtensions())?.databaseEngineTypes?.includes('sql'), + onClick: () => { + openNewTab({ + title: 'Chat', + icon: 'img ai', + tabComponent: 'DatabaseChatTab', + props: { + conid: getCurrentDatabase()?.connection?._id, + database: getCurrentDatabase()?.name, + }, + }); + }, + }); } if (hasPermission('settings/change')) { diff --git a/packages/web/src/datagrid/CollectionDataGridCore.svelte b/packages/web/src/datagrid/CollectionDataGridCore.svelte index f49bfc989..0ea8f53ac 100644 --- a/packages/web/src/datagrid/CollectionDataGridCore.svelte +++ b/packages/web/src/datagrid/CollectionDataGridCore.svelte @@ -122,7 +122,11 @@ import _ from 'lodash'; import { registerQuickExportHandler } from '../buttons/ToolStripExportButton.svelte'; import registerCommand from '../commands/registerCommand'; - import { extractShellConnection, extractShellConnectionHostable, extractShellHostConnection } from '../impexp/createImpExpScript'; + import { + extractShellConnection, + extractShellConnectionHostable, + extractShellHostConnection, + } from '../impexp/createImpExpScript'; import { apiCall } from '../utility/api'; import { registerMenu } from '../utility/contextMenu'; diff --git a/packages/web/src/datagrid/DataFilterControl.svelte b/packages/web/src/datagrid/DataFilterControl.svelte index 594cd81e4..c62b9bdb0 100644 --- a/packages/web/src/datagrid/DataFilterControl.svelte +++ b/packages/web/src/datagrid/DataFilterControl.svelte @@ -80,11 +80,12 @@ ); } - if (filterBehaviour.supportArrayTesting) { - res.push( - { onClick: () => setFilter('NOT EMPTY ARRAY'), text: 'Array is not empty' }, - { onClick: () => setFilter('EMPTY ARRAY'), text: 'Array is empty' } - ); + if (filterBehaviour.supportNotEmptyArrayTesting) { + res.push({ onClick: () => setFilter('NOT EMPTY ARRAY'), text: 'Array is not empty' }); + } + + if (filterBehaviour.supportEmptyArrayTesting) { + res.push({ onClick: () => setFilter('EMPTY ARRAY'), text: 'Array is empty' }); } if (filterBehaviour.supportNullTesting) { @@ -132,7 +133,7 @@ ); } - if (filterBehaviour.supportBooleanValues && filterBehaviour.supportNullTesting) { + if (filterBehaviour.supportBooleanOrNull) { res.push( { onClick: () => setFilter('TRUE, NULL'), text: 'Is True or NULL' }, { onClick: () => setFilter('FALSE, NULL'), text: 'Is False or NULL' } diff --git a/packages/web/src/elements/SqlHighlighter.svelte b/packages/web/src/elements/SqlHighlighter.svelte new file mode 100644 index 000000000..41d3aa438 --- /dev/null +++ b/packages/web/src/elements/SqlHighlighter.svelte @@ -0,0 +1,41 @@ + + +{#key code} + +
{code}
+{/key} + + diff --git a/packages/web/src/celldata/XmlHighlighter.svelte b/packages/web/src/elements/XmlHighlighter.svelte similarity index 87% rename from packages/web/src/celldata/XmlHighlighter.svelte rename to packages/web/src/elements/XmlHighlighter.svelte index 2f5fe655c..794f9b13d 100644 --- a/packages/web/src/celldata/XmlHighlighter.svelte +++ b/packages/web/src/elements/XmlHighlighter.svelte @@ -6,7 +6,7 @@ export let code = ''; - $: formattedCode = xmlFormat(code, { indentation: ' ' }); + $: formattedCode = xmlFormat(code, { indentation: ' ', throwOnFailure: false }); onMount(() => { hljs.registerLanguage('xml', xmlGrammar); diff --git a/packages/web/src/elements/sqlGrammar.js b/packages/web/src/elements/sqlGrammar.js new file mode 100644 index 000000000..52d198b21 --- /dev/null +++ b/packages/web/src/elements/sqlGrammar.js @@ -0,0 +1,691 @@ +/* + Language: SQL + Website: https://en.wikipedia.org/wiki/SQL + Category: common, database + */ + +/* + +Goals: + +SQL is intended to highlight basic/common SQL keywords and expressions + +- If pretty much every single SQL server includes supports, then it's a canidate. +- It is NOT intended to include tons of vendor specific keywords (Oracle, MySQL, + PostgreSQL) although the list of data types is purposely a bit more expansive. +- For more specific SQL grammars please see: + - PostgreSQL and PL/pgSQL - core + - T-SQL - https://github.com/highlightjs/highlightjs-tsql + - sql_more (core) + + */ + +export default function(hljs) { + const regex = hljs.regex; + const COMMENT_MODE = hljs.COMMENT('--', '$'); + const STRING = { + scope: 'string', + variants: [ + { + begin: /'/, + end: /'/, + contains: [ { match: /''/ } ] + } + ] + }; + const QUOTED_IDENTIFIER = { + begin: /"/, + end: /"/, + contains: [ { match: /""/ } ] + }; + + const LITERALS = [ + "true", + "false", + // Not sure it's correct to call NULL literal, and clauses like IS [NOT] NULL look strange that way. + // "null", + "unknown" + ]; + + const MULTI_WORD_TYPES = [ + "double precision", + "large object", + "with timezone", + "without timezone" + ]; + + const TYPES = [ + 'bigint', + 'binary', + 'blob', + 'boolean', + 'char', + 'character', + 'clob', + 'date', + 'dec', + 'decfloat', + 'decimal', + 'float', + 'int', + 'integer', + 'interval', + 'nchar', + 'nclob', + 'national', + 'numeric', + 'real', + 'row', + 'smallint', + 'time', + 'timestamp', + 'varchar', + 'varying', // modifier (character varying) + 'varbinary' + ]; + + const NON_RESERVED_WORDS = [ + "add", + "asc", + "collation", + "desc", + "final", + "first", + "last", + "view" + ]; + + // https://jakewheat.github.io/sql-overview/sql-2016-foundation-grammar.html#reserved-word + const RESERVED_WORDS = [ + "abs", + "acos", + "all", + "allocate", + "alter", + "and", + "any", + "are", + "array", + "array_agg", + "array_max_cardinality", + "as", + "asensitive", + "asin", + "asymmetric", + "at", + "atan", + "atomic", + "authorization", + "avg", + "begin", + "begin_frame", + "begin_partition", + "between", + "bigint", + "binary", + "blob", + "boolean", + "both", + "by", + "call", + "called", + "cardinality", + "cascaded", + "case", + "cast", + "ceil", + "ceiling", + "char", + "char_length", + "character", + "character_length", + "check", + "classifier", + "clob", + "close", + "coalesce", + "collate", + "collect", + "column", + "commit", + "condition", + "connect", + "constraint", + "contains", + "convert", + "copy", + "corr", + "corresponding", + "cos", + "cosh", + "count", + "covar_pop", + "covar_samp", + "create", + "cross", + "cube", + "cume_dist", + "current", + "current_catalog", + "current_date", + "current_default_transform_group", + "current_path", + "current_role", + "current_row", + "current_schema", + "current_time", + "current_timestamp", + "current_path", + "current_role", + "current_transform_group_for_type", + "current_user", + "cursor", + "cycle", + "date", + "day", + "deallocate", + "dec", + "decimal", + "decfloat", + "declare", + "default", + "define", + "delete", + "dense_rank", + "deref", + "describe", + "deterministic", + "disconnect", + "distinct", + "double", + "drop", + "dynamic", + "each", + "element", + "else", + "empty", + "end", + "end_frame", + "end_partition", + "end-exec", + "equals", + "escape", + "every", + "except", + "exec", + "execute", + "exists", + "exp", + "external", + "extract", + "false", + "fetch", + "filter", + "first_value", + "float", + "floor", + "for", + "foreign", + "frame_row", + "free", + "from", + "full", + "function", + "fusion", + "get", + "global", + "grant", + "group", + "grouping", + "groups", + "having", + "hold", + "hour", + "identity", + "in", + "indicator", + "initial", + "inner", + "inout", + "insensitive", + "insert", + "int", + "integer", + "intersect", + "intersection", + "interval", + "into", + "is", + "join", + "json_array", + "json_arrayagg", + "json_exists", + "json_object", + "json_objectagg", + "json_query", + "json_table", + "json_table_primitive", + "json_value", + "lag", + "language", + "large", + "last_value", + "lateral", + "lead", + "leading", + "left", + "like", + "like_regex", + "listagg", + "ln", + "local", + "localtime", + "localtimestamp", + "log", + "log10", + "lower", + "match", + "match_number", + "match_recognize", + "matches", + "max", + "member", + "merge", + "method", + "min", + "minute", + "mod", + "modifies", + "module", + "month", + "multiset", + "national", + "natural", + "nchar", + "nclob", + "new", + "no", + "none", + "normalize", + "not", + "nth_value", + "ntile", + "null", + "nullif", + "numeric", + "octet_length", + "occurrences_regex", + "of", + "offset", + "old", + "omit", + "on", + "one", + "only", + "open", + "or", + "order", + "out", + "outer", + "over", + "overlaps", + "overlay", + "parameter", + "partition", + "pattern", + "per", + "percent", + "percent_rank", + "percentile_cont", + "percentile_disc", + "period", + "portion", + "position", + "position_regex", + "power", + "precedes", + "precision", + "prepare", + "primary", + "procedure", + "ptf", + "range", + "rank", + "reads", + "real", + "recursive", + "ref", + "references", + "referencing", + "regr_avgx", + "regr_avgy", + "regr_count", + "regr_intercept", + "regr_r2", + "regr_slope", + "regr_sxx", + "regr_sxy", + "regr_syy", + "release", + "result", + "return", + "returns", + "revoke", + "right", + "rollback", + "rollup", + "row", + "row_number", + "rows", + "running", + "savepoint", + "scope", + "scroll", + "search", + "second", + "seek", + "select", + "sensitive", + "session_user", + "set", + "show", + "similar", + "sin", + "sinh", + "skip", + "smallint", + "some", + "specific", + "specifictype", + "sql", + "sqlexception", + "sqlstate", + "sqlwarning", + "sqrt", + "start", + "static", + "stddev_pop", + "stddev_samp", + "submultiset", + "subset", + "substring", + "substring_regex", + "succeeds", + "sum", + "symmetric", + "system", + "system_time", + "system_user", + "table", + "tablesample", + "tan", + "tanh", + "then", + "time", + "timestamp", + "timezone_hour", + "timezone_minute", + "to", + "trailing", + "translate", + "translate_regex", + "translation", + "treat", + "trigger", + "trim", + "trim_array", + "true", + "truncate", + "uescape", + "union", + "unique", + "unknown", + "unnest", + "update", + "upper", + "user", + "using", + "value", + "values", + "value_of", + "var_pop", + "var_samp", + "varbinary", + "varchar", + "varying", + "versioning", + "when", + "whenever", + "where", + "width_bucket", + "window", + "with", + "within", + "without", + "year", + ]; + + // these are reserved words we have identified to be functions + // and should only be highlighted in a dispatch-like context + // ie, array_agg(...), etc. + const RESERVED_FUNCTIONS = [ + "abs", + "acos", + "array_agg", + "asin", + "atan", + "avg", + "cast", + "ceil", + "ceiling", + "coalesce", + "corr", + "cos", + "cosh", + "count", + "covar_pop", + "covar_samp", + "cume_dist", + "dense_rank", + "deref", + "element", + "exp", + "extract", + "first_value", + "floor", + "json_array", + "json_arrayagg", + "json_exists", + "json_object", + "json_objectagg", + "json_query", + "json_table", + "json_table_primitive", + "json_value", + "lag", + "last_value", + "lead", + "listagg", + "ln", + "log", + "log10", + "lower", + "max", + "min", + "mod", + "nth_value", + "ntile", + "nullif", + "percent_rank", + "percentile_cont", + "percentile_disc", + "position", + "position_regex", + "power", + "rank", + "regr_avgx", + "regr_avgy", + "regr_count", + "regr_intercept", + "regr_r2", + "regr_slope", + "regr_sxx", + "regr_sxy", + "regr_syy", + "row_number", + "sin", + "sinh", + "sqrt", + "stddev_pop", + "stddev_samp", + "substring", + "substring_regex", + "sum", + "tan", + "tanh", + "translate", + "translate_regex", + "treat", + "trim", + "trim_array", + "unnest", + "upper", + "value_of", + "var_pop", + "var_samp", + "width_bucket", + ]; + + // these functions can + const POSSIBLE_WITHOUT_PARENS = [ + "current_catalog", + "current_date", + "current_default_transform_group", + "current_path", + "current_role", + "current_schema", + "current_transform_group_for_type", + "current_user", + "session_user", + "system_time", + "system_user", + "current_time", + "localtime", + "current_timestamp", + "localtimestamp" + ]; + + // those exist to boost relevance making these very + // "SQL like" keyword combos worth +1 extra relevance + const COMBOS = [ + "create table", + "insert into", + "primary key", + "foreign key", + "not null", + "alter table", + "add constraint", + "grouping sets", + "on overflow", + "character set", + "respect nulls", + "ignore nulls", + "nulls first", + "nulls last", + "depth first", + "breadth first" + ]; + + const FUNCTIONS = RESERVED_FUNCTIONS; + + const KEYWORDS = [ + ...RESERVED_WORDS, + ...NON_RESERVED_WORDS + ].filter((keyword) => { + return !RESERVED_FUNCTIONS.includes(keyword); + }); + + const VARIABLE = { + scope: "variable", + match: /@[a-z0-9][a-z0-9_]*/, + }; + + const OPERATOR = { + scope: "operator", + match: /[-+*/=%^~]|&&?|\|\|?|!=?|<(?:=>?|<|>)?|>[>=]?/, + relevance: 0, + }; + + const FUNCTION_CALL = { + match: regex.concat(/\b/, regex.either(...FUNCTIONS), /\s*\(/), + relevance: 0, + keywords: { built_in: FUNCTIONS } + }; + + // turns a multi-word keyword combo into a regex that doesn't + // care about extra whitespace etc. + // input: "START QUERY" + // output: /\bSTART\s+QUERY\b/ + function kws_to_regex(list) { + return regex.concat( + /\b/, + regex.either(...list.map((kw) => { + return kw.replace(/\s+/, "\\s+") + })), + /\b/ + ) + } + + const MULTI_WORD_KEYWORDS = { + scope: "keyword", + match: kws_to_regex(COMBOS), + relevance: 0, + }; + + // keywords with less than 3 letters are reduced in relevancy + function reduceRelevancy(list, { + exceptions, when + } = {}) { + const qualifyFn = when; + exceptions = exceptions || []; + return list.map((item) => { + if (item.match(/\|\d+$/) || exceptions.includes(item)) { + return item; + } else if (qualifyFn(item)) { + return `${item}|0`; + } else { + return item; + } + }); + } + + return { + name: 'SQL', + case_insensitive: true, + // does not include {} or HTML tags ` x.length < 3 }), + literal: LITERALS, + type: TYPES, + built_in: POSSIBLE_WITHOUT_PARENS + }, + contains: [ + { + scope: "type", + match: kws_to_regex(MULTI_WORD_TYPES) + }, + MULTI_WORD_KEYWORDS, + FUNCTION_CALL, + VARIABLE, + STRING, + QUOTED_IDENTIFIER, + hljs.C_NUMBER_MODE, + hljs.C_BLOCK_COMMENT_MODE, + COMMENT_MODE, + OPERATOR + ] + }; +} \ No newline at end of file diff --git a/packages/web/src/celldata/xmlGrammar.js b/packages/web/src/elements/xmlGrammar.js similarity index 100% rename from packages/web/src/celldata/xmlGrammar.js rename to packages/web/src/elements/xmlGrammar.js diff --git a/packages/web/src/forms/FormJsonFileInputField.svelte b/packages/web/src/forms/FormJsonFileInputField.svelte new file mode 100644 index 000000000..846198240 --- /dev/null +++ b/packages/web/src/forms/FormJsonFileInputField.svelte @@ -0,0 +1,58 @@ + + + + + diff --git a/packages/web/src/icons/FontIcon.svelte b/packages/web/src/icons/FontIcon.svelte index d2c5ef036..e293e3acf 100644 --- a/packages/web/src/icons/FontIcon.svelte +++ b/packages/web/src/icons/FontIcon.svelte @@ -73,6 +73,7 @@ 'icon scheduler-event': 'mdi mdi-calendar-blank', 'icon arrow-link': 'mdi mdi-arrow-top-right-thick', 'icon reset': 'mdi mdi-cancel', + 'icon send': 'mdi mdi-send', 'icon window-restore': 'mdi mdi-window-restore', 'icon window-maximize': 'mdi mdi-window-maximize', @@ -163,8 +164,10 @@ 'icon wait': 'mdi mdi-timer-sand', 'icon more': 'mdi mdi-more', 'icon copy': 'mdi mdi-content-copy', + 'icon arrow-start-here': 'mdi mdi-arrow-down-bold-circle', 'icon run': 'mdi mdi-play', + 'icon run-settings': 'mdi mdi-cog-play', 'icon chevron-down': 'mdi mdi-chevron-down', 'icon chevron-left': 'mdi mdi-chevron-left', 'icon chevron-right': 'mdi mdi-chevron-right', @@ -280,6 +283,8 @@ 'img admin': 'mdi mdi-security color-icon-blue', 'img auth': 'mdi mdi-account-key color-icon-blue', 'img cloud-connection': 'mdi mdi-cloud-lock color-icon-blue', + 'img ai': 'mdi mdi-head-lightbulb color-icon-yellow', + 'img run': 'mdi mdi-play color-icon-blue', 'img add': 'mdi mdi-plus-circle color-icon-green', 'img minus': 'mdi mdi-minus-circle color-icon-red', @@ -338,6 +343,7 @@ 'img db-restore': 'mdi mdi-database-import color-icon-red', 'img settings': 'mdi mdi-cog color-icon-blue', 'img data-deploy': 'mdi mdi-database-settings color-icon-green', + 'img arrow-start-here': 'mdi mdi-arrow-down-bold-circle color-icon-green', }; diff --git a/packages/web/src/icons/ThinkingIcon.svelte b/packages/web/src/icons/ThinkingIcon.svelte new file mode 100644 index 000000000..24c81dbbf --- /dev/null +++ b/packages/web/src/icons/ThinkingIcon.svelte @@ -0,0 +1,51 @@ + +
+ +
+ + diff --git a/packages/web/src/impexp/SimpleFilesInput.svelte b/packages/web/src/impexp/SimpleFilesInput.svelte new file mode 100644 index 000000000..79e2961fa --- /dev/null +++ b/packages/web/src/impexp/SimpleFilesInput.svelte @@ -0,0 +1,105 @@ + + + + + + + + + diff --git a/packages/web/src/impexp/SourceTargetConfig.svelte b/packages/web/src/impexp/SourceTargetConfig.svelte index 8c20688a5..38a8a19cd 100644 --- a/packages/web/src/impexp/SourceTargetConfig.svelte +++ b/packages/web/src/impexp/SourceTargetConfig.svelte @@ -173,7 +173,9 @@ {#if storageType == 'database' || storageType == 'query'} - + {#if !$connectionInfo?.singleDatabase} + + {/if} {/if} {#if storageType == 'database'} diff --git a/packages/web/src/modals/SetFilterModal.svelte b/packages/web/src/modals/SetFilterModal.svelte index 574d2a668..436d734ff 100644 --- a/packages/web/src/modals/SetFilterModal.svelte +++ b/packages/web/src/modals/SetFilterModal.svelte @@ -63,7 +63,9 @@
- + {#if !filterBehaviour.disableOr} + + {/if}
diff --git a/packages/web/src/query/QueryAiAssistant.svelte b/packages/web/src/query/QueryAiAssistant.svelte deleted file mode 100644 index b44912f77..000000000 --- a/packages/web/src/query/QueryAiAssistant.svelte +++ /dev/null @@ -1 +0,0 @@ -AI Assistant \ No newline at end of file diff --git a/packages/web/src/settings/ConnectionDriverFields.svelte b/packages/web/src/settings/ConnectionDriverFields.svelte index 7c048f7c2..0e578d650 100644 --- a/packages/web/src/settings/ConnectionDriverFields.svelte +++ b/packages/web/src/settings/ConnectionDriverFields.svelte @@ -18,6 +18,9 @@ import FormDropDownTextField from '../forms/FormDropDownTextField.svelte'; import { getConnectionLabel } from 'dbgate-tools'; import { _t } from '../translations'; + import FilesInput from '../impexp/FilesInput.svelte'; + import SimpleFilesInput from '../impexp/SimpleFilesInput.svelte'; + import FormJsonFileInputField from '../forms/FormJsonFileInputField.svelte'; export let getDatabaseList; export let currentConnection; @@ -462,6 +465,10 @@ /> {/if} +{#if driver?.showConnectionField('certificateJson', $values, showConnectionFieldArgs)} + +{/if} + {#if driver}
diff --git a/packages/web/src/tabs/QueryTab.svelte b/packages/web/src/tabs/QueryTab.svelte index 4746dcff3..a2102fa72 100644 --- a/packages/web/src/tabs/QueryTab.svelte +++ b/packages/web/src/tabs/QueryTab.svelte @@ -13,15 +13,6 @@ testEnabled: () => getCurrentEditor()?.isSqlEditor(), onClick: () => getCurrentEditor().formatCode(), }); - registerCommand({ - id: 'query.switchAiAssistant', - category: 'Query', - name: 'AI Assistant', - keyText: 'Shift+Alt+A', - icon: 'icon ai', - testEnabled: () => isProApp(), - onClick: () => getCurrentEditor().toggleAiAssistant(), - }); registerCommand({ id: 'query.insertSqlJoin', category: 'Query', @@ -157,7 +148,6 @@ import QueryParametersModal from '../modals/QueryParametersModal.svelte'; import { isProApp } from '../utility/proTools'; import HorizontalSplitter from '../elements/HorizontalSplitter.svelte'; - import QueryAiAssistant from '../query/QueryAiAssistant.svelte'; import uuidv1 from 'uuid/v1'; import ToolStripButton from '../buttons/ToolStripButton.svelte'; import { getIntSettingsValue } from '../settings/settingsTools'; @@ -212,8 +202,6 @@ let domEditor; let domToolStrip; let intervalId; - let isAiAssistantVisible = isProApp() && localStorage.getItem(`tabdata_isAiAssistantVisible_${tabid}`) == 'true'; - let domAiAssistant; let isInTransaction = false; let isAutocommit = false; let splitterInitialValue = undefined; @@ -287,12 +275,6 @@ domEditor?.getEditor()?.focus(); } - $: { - if (!isAiAssistantVisible && domEditor) { - domEditor?.getEditor()?.focus(); - } - } - export function isSqlEditor() { return driver?.databaseEngineTypes?.includes('sql'); } @@ -317,10 +299,6 @@ visibleResultTabs = !visibleResultTabs; } - export function toggleAiAssistant() { - isAiAssistantVisible = !isAiAssistantVisible; - } - function getParameterSplitterOptions() { if (!queryParameterStyle) { return null; @@ -631,29 +609,6 @@ ); } - async function handleKeyDown(event) { - if (isProApp()) { - if (event.code == 'Space' && event.shiftKey && event.ctrlKey && !isAiAssistantVisible) { - event.preventDefault(); - event.stopPropagation(); - toggleAiAssistant(); - await sleep(100); - if (domAiAssistant) { - domAiAssistant.handleCompleteOnCursor(); - domEditor?.getEditor()?.focus(); - } - } else if (event.code == 'Space' && event.shiftKey && event.ctrlKey && isAiAssistantVisible && domAiAssistant) { - event.preventDefault(); - event.stopPropagation(); - domAiAssistant.handleCompleteOnCursor(); - } else if (event.code?.startsWith('Digit') && event.altKey && isAiAssistantVisible && domAiAssistant) { - event.preventDefault(); - event.stopPropagation(); - domAiAssistant.insertCompletion(parseInt(event.code.substring(5)) - 1); - } - } - } - function createMenu() { return [ { command: 'query.execute' }, @@ -675,7 +630,6 @@ { command: 'query.replace' }, { divider: true }, { command: 'query.toggleVisibleResultTabs' }, - { command: 'query.switchAiAssistant', hideDisabled: true }, ]; } @@ -695,127 +649,91 @@ localStorage.getItem(`tabdata_queryParamStyle_${tabid}`) ?? initialArgs?.queryParameterStyle ?? (initialArgs?.scriptTemplate == 'CALL OBJECT' ? ':' : ''); - - $: localStorage.setItem(`tabdata_isAiAssistantVisible_${tabid}`, isAiAssistantVisible ? 'true' : 'false'); - + - - - {#if driver?.databaseEngineTypes?.includes('sql')} - { - setEditorData(e.detail); - if (isInitialized) { - markTabUnsaved(tabid); - } - errorMessages = []; - }} - on:focus={() => { - activator.activate(); - domToolStrip?.activate(); - invalidateCommands(); - setTimeout(() => { - isInitialized = true; - }, 100); - }} - bind:this={domEditor} - onExecuteFragment={(sql, startLine) => executeCore(sql, startLine)} - {errorMessages} - onKeyDown={handleKeyDown} - /> - {:else} - setEditorData(e.detail)} - on:focus={() => { - activator.activate(); - domToolStrip?.activate(); - invalidateCommands(); - }} - bind:this={domEditor} - /> - {/if} - - - getSqlFrontMatter($editorValue, yaml)} - > - - - - - - + {#if driver?.databaseEngineTypes?.includes('sql')} + { + setEditorData(e.detail); + if (isInitialized) { + markTabUnsaved(tabid); + } + errorMessages = []; + }} + on:focus={() => { + activator.activate(); + domToolStrip?.activate(); + invalidateCommands(); + setTimeout(() => { + isInitialized = true; + }, 100); + }} + bind:this={domEditor} + onExecuteFragment={(sql, startLine) => executeCore(sql, startLine)} + {errorMessages} + /> + {:else} + setEditorData(e.detail)} + on:focus={() => { + activator.activate(); + domToolStrip?.activate(); + invalidateCommands(); + }} + bind:this={domEditor} + /> + {/if} - { - isAiAssistantVisible = false; - }} - text={$editorValue} - getLine={() => domEditor.getEditor().getSelectionRange().start.row} - onInsertAtCursor={text => { - const editor = domEditor.getEditor(); - editor.session.insert(editor.getCursorPosition(), text); - domEditor?.getEditor()?.focus(); - }} - getTextOrSelectedText={() => domEditor.getEditor().getSelectedText() || $editorValue} - onSetSelectedText={text => { - const editor = domEditor.getEditor(); - if (editor.getSelectedText()) { - const range = editor.selection.getRange(); - editor.session.replace(range, text); - } else { - editor.setValue(text); - } - }} - {tabid} - /> + onSetFrontMatterField={handleSetFrontMatterField} + onGetFrontMatter={() => getSqlFrontMatter($editorValue, yaml)} + > + + + + - + - - AI Assistant - | FileParseResultError} FileParseResult + */ + +/** + * @template [T = any] + * @param {File} file + * @returns {Promise>} + */ +export async function parseFileAsJson(file) { + try { + const text = await file.text(); + const data = JSON.parse(text); + return { + success: true, + data, + }; + } catch (error) { + return { + success: false, + error: error instanceof Error ? error.message : 'Unknown parsing error', + }; + } +} diff --git a/packages/web/src/widgets/WidgetIconPanel.svelte b/packages/web/src/widgets/WidgetIconPanel.svelte index 1d374da0f..7459320b7 100644 --- a/packages/web/src/widgets/WidgetIconPanel.svelte +++ b/packages/web/src/widgets/WidgetIconPanel.svelte @@ -60,11 +60,11 @@ name: 'archive', title: 'Archive (saved tabular data)', }, - { - icon: 'icon plugin', - name: 'plugins', - title: 'Extensions & Plugins', - }, + // { + // icon: 'icon plugin', + // name: 'plugins', + // title: 'Extensions & Plugins', + // }, { icon: 'icon cell-data', name: 'cell-data', @@ -116,6 +116,13 @@ $visibleWidgetSideBar = true; }, }, + { + text: 'Manage plugins', + onClick: () => { + $selectedWidget = 'plugins'; + $visibleWidgetSideBar = true; + }, + }, ]; currentDropDownMenu.set({ left, top, items }); } @@ -159,6 +166,7 @@ {#each widgets .filter(x => x && hasPermission(`widgets/${x.name}`)) .filter(x => !x.isPremiumPromo || !isProApp()) + // .filter(x => !x.isPremiumOnly || isProApp()) .filter(x => x.name != 'cloud-private' || $cloudSigninTokenHolder) as item}
=18": version "20.12.10" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.12.10.tgz#8f0c3f12b0f075eee1fe20c1afb417e9765bef76" @@ -3677,6 +3951,13 @@ dependencies: undici-types "~5.26.4" +"@types/node@>=13.7.0": + version "24.0.3" + resolved "https://registry.yarnpkg.com/@types/node/-/node-24.0.3.tgz#f935910f3eece3a3a2f8be86b96ba833dc286cab" + integrity sha512-R4I/kzCYAdRLzfiCabn9hxWfbuHS573x+r0dJMkkzThEa7pbrcDWK+9zu3e7aBOouf+rQAciqPFMnxwr0aWgKg== + dependencies: + undici-types "~7.8.0" + "@types/node@>=8": version "22.10.5" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.10.5.tgz#95af89a3fb74a2bb41ef9927f206e6472026e48b" @@ -3689,6 +3970,13 @@ resolved "https://registry.yarnpkg.com/@types/node/-/node-13.13.52.tgz#03c13be70b9031baaed79481c0c0cfb0045e53f7" integrity sha512-s3nugnZumCC//n4moGGe6tkNMyYEdaDBitVjwPxXmR5lnMG5dHePinH2EdxkG3Rh1ghFHHixAG4NJhpJW1rthQ== +"@types/node@^22.8.7": + version "22.15.32" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.15.32.tgz#c301cc2275b535a5e54bb81d516b1d2e9afe06e5" + integrity sha512-3jigKqgSjsH6gYZv2nEsqdXfZqIFGAV36XYYjf9KGZ3PSG+IhLecqPnI310RvjutyMwifE2hhhNEklOUrvx/wA== + dependencies: + undici-types "~6.21.0" + "@types/normalize-package-data@^2.4.0": version "2.4.4" resolved "https://registry.yarnpkg.com/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz#56e2cc26c397c038fab0e3a917a12d5c5909e901" @@ -3709,6 +3997,16 @@ resolved "https://registry.yarnpkg.com/@types/pug/-/pug-2.0.10.tgz#52f8dbd6113517aef901db20b4f3fca543b88c1f" integrity sha512-Sk/uYFOBAB7mb74XcpizmH0KOR2Pv3D2Hmrh1Dmy5BmK3MpdSa5kqZcg6EKBdklU0bFXX9gCfzvpnyUehrPIuA== +"@types/qs@*": + version "6.14.0" + resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.14.0.tgz#d8b60cecf62f2db0fb68e5e006077b9178b85de5" + integrity sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ== + +"@types/range-parser@*": + version "1.2.7" + resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb" + integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ== + "@types/readable-stream@^4.0.0": version "4.0.12" resolved "https://registry.yarnpkg.com/@types/readable-stream/-/readable-stream-4.0.12.tgz#9a683715338313a30b3d7f2527e09414098f7c44" @@ -3717,6 +4015,16 @@ "@types/node" "*" safe-buffer "~5.1.1" +"@types/request@^2.48.8": + version "2.48.12" + resolved "https://registry.yarnpkg.com/@types/request/-/request-2.48.12.tgz#0f590f615a10f87da18e9790ac94c29ec4c5ef30" + integrity sha512-G3sY+NpsA9jnwm0ixhAFQSJ3Q9JkpLZpJbI3GMv0mIAT0y3mRabYeINzal5WOChIiaTEGQYlHOKgkaM9EisWHw== + dependencies: + "@types/caseless" "*" + "@types/node" "*" + "@types/tough-cookie" "*" + form-data "^2.5.0" + "@types/resolve@1.17.1": version "1.17.1" resolved "https://registry.yarnpkg.com/@types/resolve/-/resolve-1.17.1.tgz#3afd6ad8967c77e4376c598a82ddd58f46ec45d6" @@ -3731,11 +4039,33 @@ dependencies: sass "*" +"@types/send@*": + version "0.17.5" + resolved "https://registry.yarnpkg.com/@types/send/-/send-0.17.5.tgz#d991d4f2b16f2b1ef497131f00a9114290791e74" + integrity sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w== + dependencies: + "@types/mime" "^1" + "@types/node" "*" + +"@types/serve-static@*": + version "1.15.8" + resolved "https://registry.yarnpkg.com/@types/serve-static/-/serve-static-1.15.8.tgz#8180c3fbe4a70e8f00b9f70b9ba7f08f35987877" + integrity sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg== + dependencies: + "@types/http-errors" "*" + "@types/node" "*" + "@types/send" "*" + "@types/stack-utils@^2.0.0": version "2.0.3" resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.3.tgz#6209321eb2c1712a7e7466422b8cb1fc0d9dd5d8" integrity sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw== +"@types/tough-cookie@*": + version "4.0.5" + resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.5.tgz#cb6e2a691b70cb177c6e3ae9c1d2e8b2ea8cd304" + integrity sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA== + "@types/webidl-conversions@*": version "7.0.3" resolved "https://registry.yarnpkg.com/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz#1306dbfa53768bcbcfc95a1c8cde367975581859" @@ -4266,6 +4596,11 @@ arrify@^1.0.1: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== +arrify@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/arrify/-/arrify-2.0.1.tgz#c9655e9331e0abcd588d2a7cad7e9956f66701fa" + integrity sha512-3duEwti880xqi4eAMN8AyR4a0ByT90zoYdLlevfrvU43vb0YZwZVfxOgxWrLXXXpyugL0hNZc9G6BiB5B3nUug== + asn1@^0.2.4, asn1@^0.2.6, asn1@~0.2.3: version "0.2.6" resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.6.tgz#0d3a7bb6e64e02a90c0303b31f292868ea09a08d" @@ -4300,6 +4635,13 @@ async-lock@^1.2.6: resolved "https://registry.yarnpkg.com/async-lock/-/async-lock-1.4.1.tgz#56b8718915a9b68b10fce2f2a9a3dddf765ef53f" integrity sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ== +async-retry@^1.3.3: + version "1.3.3" + resolved "https://registry.yarnpkg.com/async-retry/-/async-retry-1.3.3.tgz#0e7f36c04d8478e7a58bdbed80cedf977785f280" + integrity sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw== + dependencies: + retry "0.13.1" + async@^2.6.4: version "2.6.4" resolved "https://registry.yarnpkg.com/async/-/async-2.6.4.tgz#706b7ff6084664cd7eae713f6f965433b5504221" @@ -4485,7 +4827,7 @@ bare-events@^2.2.0: resolved "https://registry.yarnpkg.com/bare-events/-/bare-events-2.5.4.tgz#16143d435e1ed9eafd1ab85f12b89b3357a41745" integrity sha512-+gFfDkR8pj4/TrWCGUGWmJIkBwuxPS5F+a5yWjOHQt2hHvNZd5YLzadjmDUtFmMM4y429bnKLa8bYBMHcYdnQA== -base64-js@^1.3.1: +base64-js@^1.3.0, base64-js@^1.3.1: version "1.5.1" resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== @@ -4540,6 +4882,11 @@ big.js@^5.2.2: resolved "https://registry.yarnpkg.com/big.js/-/big.js-5.2.2.tgz#65f0af382f578bcdc742bd9c281e9cb2d7768328" integrity sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ== +bignumber.js@^9.0.0: + version "9.3.0" + resolved "https://registry.yarnpkg.com/bignumber.js/-/bignumber.js-9.3.0.tgz#bdba7e2a4c1a2eba08290e8dcad4f36393c92acd" + integrity sha512-EM7aMFTXbptt/wZdMlBv2t8IViwQL+h6SLHosp8Yf0dqJMTnY6iL32opnAB6kAdL0SZPuvcAzFr31o0c/R3/RA== + binary-extensions@^2.0.0: version "2.3.0" resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" @@ -5925,6 +6272,16 @@ duplexer2@~0.0.2: dependencies: readable-stream "~1.1.9" +duplexify@^4.0.0, duplexify@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/duplexify/-/duplexify-4.1.3.tgz#a07e1c0d0a2c001158563d32592ba58bddb0236f" + integrity sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA== + dependencies: + end-of-stream "^1.4.1" + inherits "^2.0.3" + readable-stream "^3.1.1" + stream-shift "^1.0.2" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -5938,7 +6295,7 @@ ecc-jsbn@~0.1.1: jsbn "~0.1.0" safer-buffer "^2.1.0" -ecdsa-sig-formatter@1.0.11: +ecdsa-sig-formatter@1.0.11, ecdsa-sig-formatter@^1.0.11: version "1.0.11" resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf" integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ== @@ -6154,6 +6511,16 @@ es-set-tostringtag@^2.0.3: has-tostringtag "^1.0.2" hasown "^2.0.1" +es-set-tostringtag@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz#f31dbbe0c183b00a6d26eb6325c810c0fd18bd4d" + integrity sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA== + dependencies: + es-errors "^1.3.0" + get-intrinsic "^1.2.6" + has-tostringtag "^1.0.2" + hasown "^2.0.2" + es-to-primitive@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" @@ -6517,7 +6884,7 @@ extend-shallow@^3.0.0, extend-shallow@^3.0.2: assign-symbols "^1.0.0" is-extendable "^1.0.1" -extend@~3.0.2: +extend@^3.0.2, extend@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== @@ -6562,6 +6929,11 @@ extsprintf@^1.2.0: resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.1.tgz#8d172c064867f235c0c84a596806d279bf4bcc07" integrity sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA== +farmhash-modern@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/farmhash-modern/-/farmhash-modern-1.1.0.tgz#c36b34ad196290d57b0b482dc89e637d0b59835f" + integrity sha512-6ypT4XfgqJk/F3Yuv4SX26I3doUjt0GTG4a+JgWxXQpxXzTBq8fPUeGHfcYMMDPHJHm3yPOSjaeBwBGAHWXCdA== + fast-copy@^3.0.0, fast-copy@^3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/fast-copy/-/fast-copy-3.0.2.tgz#59c68f59ccbcac82050ba992e0d5c389097c9d35" @@ -6646,6 +7018,13 @@ fastq@^1.6.0: dependencies: reusify "^1.0.4" +faye-websocket@0.11.4: + version "0.11.4" + resolved "https://registry.yarnpkg.com/faye-websocket/-/faye-websocket-0.11.4.tgz#7f0d9275cfdd86a1c963dc8b65fcc451edcbb1da" + integrity sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g== + dependencies: + websocket-driver ">=0.5.1" + fb-watchman@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/fb-watchman/-/fb-watchman-2.0.2.tgz#e9524ee6b5c77e9e5001af0f85f3adbb8623255c" @@ -6770,6 +7149,25 @@ find-yarn-workspace-root@^2.0.0: dependencies: micromatch "^4.0.2" +firebase-admin@^13.4.0: + version "13.4.0" + resolved "https://registry.yarnpkg.com/firebase-admin/-/firebase-admin-13.4.0.tgz#7bf6a2573bf0bb2c0b5c9ac08af18992c38bd972" + integrity sha512-Y8DcyKK+4pl4B93ooiy1G8qvdyRMkcNFfBSh+8rbVcw4cW8dgG0VXCCTp5NUwub8sn9vSPsOwpb9tE2OuFmcfQ== + dependencies: + "@fastify/busboy" "^3.0.0" + "@firebase/database-compat" "^2.0.0" + "@firebase/database-types" "^1.0.6" + "@types/node" "^22.8.7" + farmhash-modern "^1.1.0" + google-auth-library "^9.14.2" + jsonwebtoken "^9.0.0" + jwks-rsa "^3.1.0" + node-forge "^1.3.1" + uuid "^11.0.2" + optionalDependencies: + "@google-cloud/firestore" "^7.11.0" + "@google-cloud/storage" "^7.14.0" + flat-cache@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-2.0.1.tgz#5d296d6f04bda44a4630a301413bdbc2ec085ec0" @@ -6824,6 +7222,17 @@ forever-agent@~0.6.1: resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" integrity sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw== +form-data@^2.5.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.5.3.tgz#f9bcf87418ce748513c0c3494bb48ec270c97acc" + integrity sha512-XHIrMD0NpDrNM/Ckf7XJiBbLl57KEhT3+i3yY+eWm+cqYZJQTZrKo8Y8AWKnuV5GT4scfuUGt9LzNoIx3dU1nQ== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + es-set-tostringtag "^2.1.0" + mime-types "^2.1.35" + safe-buffer "^5.2.1" + form-data@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/form-data/-/form-data-3.0.1.tgz#ebd53791b78356a99af9a300d4282c4d5eb9755f" @@ -6977,6 +7386,26 @@ gauge@~2.7.3: strip-ansi "^3.0.1" wide-align "^1.1.0" +gaxios@^6.0.0, gaxios@^6.0.2, gaxios@^6.1.1: + version "6.7.1" + resolved "https://registry.yarnpkg.com/gaxios/-/gaxios-6.7.1.tgz#ebd9f7093ede3ba502685e73390248bb5b7f71fb" + integrity sha512-LDODD4TMYx7XXdpwxAVRAIAuB0bzv0s+ywFonY46k126qzQHT9ygyoa9tncmOiQmmDrik65UYsEkv3lbfqQ3yQ== + dependencies: + extend "^3.0.2" + https-proxy-agent "^7.0.1" + is-stream "^2.0.0" + node-fetch "^2.6.9" + uuid "^9.0.1" + +gcp-metadata@^6.1.0: + version "6.1.1" + resolved "https://registry.yarnpkg.com/gcp-metadata/-/gcp-metadata-6.1.1.tgz#f65aa69f546bc56e116061d137d3f5f90bdec494" + integrity sha512-a4tiq7E0/5fTjxPAaH4jpjkSv/uCaU2p5KC6HVGrvl0cDjA8iBZv4vv1gyzlmK0ZUKqwpOyQMKzZQe3lTit77A== + dependencies: + gaxios "^6.1.1" + google-logging-utils "^0.0.2" + json-bigint "^1.0.0" + generate-function@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/generate-function/-/generate-function-2.3.1.tgz#f069617690c10c868e73b8465746764f97c3479f" @@ -7201,6 +7630,41 @@ globby@^9.2.0: pify "^4.0.1" slash "^2.0.0" +google-auth-library@^9.14.2, google-auth-library@^9.3.0, google-auth-library@^9.6.3: + version "9.15.1" + resolved "https://registry.yarnpkg.com/google-auth-library/-/google-auth-library-9.15.1.tgz#0c5d84ed1890b2375f1cd74f03ac7b806b392928" + integrity sha512-Jb6Z0+nvECVz+2lzSMt9u98UsoakXxA2HGHMCxh+so3n90XgYWkq5dur19JAJV7ONiJY22yBTyJB1TSkvPq9Ng== + dependencies: + base64-js "^1.3.0" + ecdsa-sig-formatter "^1.0.11" + gaxios "^6.1.1" + gcp-metadata "^6.1.0" + gtoken "^7.0.0" + jws "^4.0.0" + +google-gax@^4.3.3: + version "4.6.1" + resolved "https://registry.yarnpkg.com/google-gax/-/google-gax-4.6.1.tgz#57f8e3d893d4c708a71167cdcf47eb3afab95929" + integrity sha512-V6eky/xz2mcKfAd1Ioxyd6nmA61gao3n01C+YeuIwu3vzM9EDR6wcVzMSIbLMDXWeoi9SHYctXuKYC5uJUT3eQ== + dependencies: + "@grpc/grpc-js" "^1.10.9" + "@grpc/proto-loader" "^0.7.13" + "@types/long" "^4.0.0" + abort-controller "^3.0.0" + duplexify "^4.0.0" + google-auth-library "^9.3.0" + node-fetch "^2.7.0" + object-hash "^3.0.0" + proto3-json-serializer "^2.0.2" + protobufjs "^7.3.2" + retry-request "^7.0.0" + uuid "^9.0.1" + +google-logging-utils@^0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/google-logging-utils/-/google-logging-utils-0.0.2.tgz#5fd837e06fa334da450433b9e3e1870c1594466a" + integrity sha512-NEgUnEcBiP5HrPzufUkBzJOD/Sxsco3rLNo1F1TNf7ieU8ryUzBhqba8r756CjLX7rn3fHl6iLEwPYuqpoKgQQ== + gopd@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" @@ -7218,6 +7682,14 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.1.3, graceful-fs@^4.1.6, resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +gtoken@^7.0.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/gtoken/-/gtoken-7.1.0.tgz#d61b4ebd10132222817f7222b1e6064bd463fc26" + integrity sha512-pCcEwRi+TKpMlxAQObHDQ56KawURgyAf6jtIY046fJ5tIv3zDe/LEIubckAO8fj6JnAxLdmWkUfNyulQ2iKdEw== + dependencies: + gaxios "^6.0.0" + jws "^4.0.0" + hammerjs@^2.0.8: version "2.0.8" resolved "https://registry.yarnpkg.com/hammerjs/-/hammerjs-2.0.8.tgz#04ef77862cff2bb79d30f7692095930222bf60f1" @@ -7390,6 +7862,11 @@ html-encoding-sniffer@^2.0.1: dependencies: whatwg-encoding "^1.0.5" +html-entities@^2.5.2: + version "2.6.0" + resolved "https://registry.yarnpkg.com/html-entities/-/html-entities-2.6.0.tgz#7c64f1ea3b36818ccae3d3fb48b6974208e984f8" + integrity sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -7411,6 +7888,11 @@ http-errors@2.0.0: statuses "2.0.1" toidentifier "1.0.1" +http-parser-js@>=0.5.1: + version "0.5.10" + resolved "https://registry.yarnpkg.com/http-parser-js/-/http-parser-js-0.5.10.tgz#b3277bd6d7ed5588e20ea73bf724fcbe44609075" + integrity sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA== + http-proxy-agent@^4.0.1: version "4.0.1" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz#8a8c8ef7f5932ccf953c296ca8291b95aa74aa3a" @@ -9170,6 +9652,18 @@ jwa@^2.0.0: ecdsa-sig-formatter "1.0.11" safe-buffer "^5.0.1" +jwks-rsa@^3.1.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jwks-rsa/-/jwks-rsa-3.2.0.tgz#132bc8bfa7b03928a273bbc93486f70226449e04" + integrity sha512-PwchfHcQK/5PSydeKCs1ylNym0w/SSv8a62DgHJ//7x2ZclCoinlsjAfDxAAbpoTPybOum/Jgy+vkvMmKz89Ww== + dependencies: + "@types/express" "^4.17.20" + "@types/jsonwebtoken" "^9.0.4" + debug "^4.3.4" + jose "^4.15.4" + limiter "^1.1.5" + lru-memoizer "^2.2.0" + jws@^3.2.2: version "3.2.2" resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304" @@ -9310,6 +9804,11 @@ lie@3.1.1: dependencies: immediate "~3.0.5" +limiter@^1.1.5: + version "1.1.5" + resolved "https://registry.yarnpkg.com/limiter/-/limiter-1.1.5.tgz#8f92a25b3b16c6131293a0cc834b4a838a2aa7c2" + integrity sha512-FWWMIEOxz3GwUI4Ts/IvgVy6LPvoMPgjMdQ185nN6psJyBJ4yOpzqm695/h5umdLJg2vW3GR5iG11MAkR2AzJA== + line-reader@^0.4.0: version "0.4.0" resolved "https://registry.yarnpkg.com/line-reader/-/line-reader-0.4.0.tgz#17e44818da0ac335675ba300954f94ef670e66fd" @@ -9388,6 +9887,11 @@ lodash.camelcase@^4.3.0: resolved "https://registry.yarnpkg.com/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz#b28aa6288a2b9fc651035c7711f65ab6190331a6" integrity sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA== +lodash.clonedeep@^4.5.0: + version "4.5.0" + resolved "https://registry.yarnpkg.com/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz#e23f3f9c4f8fbdde872529c1071857a086e5ccef" + integrity sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ== + lodash.defaults@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.defaults/-/lodash.defaults-4.2.0.tgz#d09178716ffea4dde9e5fb7b37f6f0802274580c" @@ -9463,11 +9967,18 @@ long@*, long@^5.2.1, long@~5.2.3: resolved "https://registry.yarnpkg.com/long/-/long-5.2.3.tgz#a3ba97f3877cf1d778eccbcb048525ebb77499e1" integrity sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q== -long@^5.2.3: +long@^5.0.0, long@^5.2.3: version "5.3.2" resolved "https://registry.yarnpkg.com/long/-/long-5.3.2.tgz#1d84463095999262d7d7b7f8bfd4a8cc55167f83" integrity sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA== +lru-cache@6.0.0, lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + lru-cache@^10.2.0: version "10.4.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" @@ -9485,18 +9996,19 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" -lru-cache@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" - integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== - dependencies: - yallist "^4.0.0" - lru-cache@^7.14.1: version "7.18.3" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.18.3.tgz#f793896e0fd0e954a59dfdd82f0773808df6aa89" integrity sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA== +lru-memoizer@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/lru-memoizer/-/lru-memoizer-2.3.0.tgz#ef0fbc021bceb666794b145eefac6be49dc47f31" + integrity sha512-GXn7gyHAMhO13WSKrIiNfztwxodVsP8IoZ3XfrJV4yH2x0/OeTO/FIaAHTY5YekdGgW94njfuKmyyt1E0mR6Ug== + dependencies: + lodash.clonedeep "^4.5.0" + lru-cache "6.0.0" + lru.min@^1.0.0: version "1.1.1" resolved "https://registry.yarnpkg.com/lru.min/-/lru.min-1.1.1.tgz#146e01e3a183fa7ba51049175de04667d5701f0e" @@ -9713,7 +10225,7 @@ mime-db@1.52.0: resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== -mime-types@^2.1.12, mime-types@^2.1.27, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: +mime-types@^2.1.12, mime-types@^2.1.27, mime-types@^2.1.35, mime-types@~2.1.19, mime-types@~2.1.24, mime-types@~2.1.34: version "2.1.35" resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== @@ -9725,6 +10237,11 @@ mime@1.6.0: resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== +mime@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/mime/-/mime-3.0.0.tgz#b374550dca3a0c18443b0c950a6a58f1931cf7a7" + integrity sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A== + mimic-fn@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-2.1.0.tgz#7ed2c2ccccaf84d3ffcb7a69b57711fc2083401b" @@ -10168,6 +10685,11 @@ node-firebird@^1.1.9: big-integer "^1.6.51" long "^5.2.3" +node-forge@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" + integrity sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA== + node-gyp@^7.1.0: version "7.1.2" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-7.1.2.tgz#21a810aebb187120251c3bcec979af1587b188ae" @@ -10585,7 +11107,7 @@ p-limit@^2.0.0, p-limit@^2.2.0, p-limit@^2.2.1: dependencies: p-try "^2.0.0" -p-limit@^3.1.0: +p-limit@^3.0.1, p-limit@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== @@ -11168,6 +11690,31 @@ prompts@^2.0.1: kleur "^3.0.3" sisteransi "^1.0.5" +proto3-json-serializer@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/proto3-json-serializer/-/proto3-json-serializer-2.0.2.tgz#5b705203b4d58f3880596c95fad64902617529dd" + integrity sha512-SAzp/O4Yh02jGdRc+uIrGoe87dkN/XtwxfZ4ZyafJHymd79ozp5VG5nyZ7ygqPM5+cpLDjjGnYFUkngonyDPOQ== + dependencies: + protobufjs "^7.2.5" + +protobufjs@^7.2.5, protobufjs@^7.2.6, protobufjs@^7.3.2: + version "7.5.3" + resolved "https://registry.yarnpkg.com/protobufjs/-/protobufjs-7.5.3.tgz#13f95a9e3c84669995ec3652db2ac2fb00b89363" + integrity sha512-sildjKwVqOI2kmFDiXQ6aEB0fjYTafpEvIBs8tOR8qI4spuL9OPROLVu2qZqi/xgCfsHIwVqlaF8JBjWFHnKbw== + dependencies: + "@protobufjs/aspromise" "^1.1.2" + "@protobufjs/base64" "^1.1.2" + "@protobufjs/codegen" "^2.0.4" + "@protobufjs/eventemitter" "^1.1.0" + "@protobufjs/fetch" "^1.1.0" + "@protobufjs/float" "^1.0.2" + "@protobufjs/inquire" "^1.1.0" + "@protobufjs/path" "^1.1.2" + "@protobufjs/pool" "^1.1.0" + "@protobufjs/utf8" "^1.1.0" + "@types/node" ">=13.7.0" + long "^5.0.0" + proxy-addr@~2.0.7: version "2.0.7" resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.7.tgz#f19fe69ceab311eeb94b42e70e8c2070f9ba1025" @@ -11594,6 +12141,20 @@ ret@~0.1.10: resolved "https://registry.yarnpkg.com/ret/-/ret-0.1.15.tgz#b8a4825d5bdb1fc3f6f53c2bc33f81388681c7bc" integrity sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg== +retry-request@^7.0.0: + version "7.0.2" + resolved "https://registry.yarnpkg.com/retry-request/-/retry-request-7.0.2.tgz#60bf48cfb424ec01b03fca6665dee91d06dd95f3" + integrity sha512-dUOvLMJ0/JJYEn8NrpOaGNE7X3vpI5XlZS/u0ANjqtcZVKnIxP7IgCFwrKTxENw29emmwug53awKtaMm4i9g5w== + dependencies: + "@types/request" "^2.48.8" + extend "^3.0.2" + teeny-request "^9.0.0" + +retry@0.13.1: + version "0.13.1" + resolved "https://registry.yarnpkg.com/retry/-/retry-0.13.1.tgz#185b1587acf67919d63b357349e03537b2484658" + integrity sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg== + retry@^0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" @@ -11728,7 +12289,7 @@ safe-buffer@5.1.2, safe-buffer@~5.1.0, safe-buffer@~5.1.1: resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== -safe-buffer@5.2.1, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@~5.2.0: +safe-buffer@5.2.1, safe-buffer@>=5.1.0, safe-buffer@^5.0.1, safe-buffer@^5.1.0, safe-buffer@^5.1.2, safe-buffer@^5.2.1, safe-buffer@~5.2.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== @@ -12438,6 +12999,13 @@ stream-chain@^2.2.5: resolved "https://registry.yarnpkg.com/stream-chain/-/stream-chain-2.2.5.tgz#b30967e8f14ee033c5b9a19bbe8a2cba90ba0d09" integrity sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA== +stream-events@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/stream-events/-/stream-events-1.0.5.tgz#bbc898ec4df33a4902d892333d47da9bf1c406d5" + integrity sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg== + dependencies: + stubs "^3.0.0" + stream-json@^1.8.0: version "1.8.0" resolved "https://registry.yarnpkg.com/stream-json/-/stream-json-1.8.0.tgz#53f486b2e3b4496c506131f8d7260ba42def151c" @@ -12445,6 +13013,11 @@ stream-json@^1.8.0: dependencies: stream-chain "^2.2.5" +stream-shift@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/stream-shift/-/stream-shift-1.0.3.tgz#85b8fab4d71010fc3ba8772e8046cc49b8a3864b" + integrity sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ== + stream-transform@^3.3.2: version "3.3.2" resolved "https://registry.yarnpkg.com/stream-transform/-/stream-transform-3.3.2.tgz#398c67b2f3b6ed5d04ceadde9e412bda8416c8ab" @@ -12829,6 +13402,17 @@ tedious@^18.6.1: native-duplexpair "^1.0.0" sprintf-js "^1.1.3" +teeny-request@^9.0.0: + version "9.0.0" + resolved "https://registry.yarnpkg.com/teeny-request/-/teeny-request-9.0.0.tgz#18140de2eb6595771b1b02203312dfad79a4716d" + integrity sha512-resvxdc6Mgb7YEThw6G6bExlXKkv6+YbuzGg9xuXxSgxJF7Ozs+o8Y9+2R3sArdWdW8nOokoQb1yrpFB0pQK2g== + dependencies: + http-proxy-agent "^5.0.0" + https-proxy-agent "^5.0.0" + node-fetch "^2.6.9" + stream-events "^1.0.5" + uuid "^9.0.0" + terminal-link@^2.0.0: version "2.1.1" resolved "https://registry.yarnpkg.com/terminal-link/-/terminal-link-2.1.1.tgz#14a64a27ab3c0df933ea546fba55f2d078edc994" @@ -13077,6 +13661,11 @@ tslib@^2.0.3, tslib@^2.2.0, tslib@^2.3.1, tslib@^2.6.2: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.1.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tunnel-agent@^0.6.0: version "0.6.0" resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" @@ -13255,6 +13844,16 @@ undici-types@~6.20.0: resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.20.0.tgz#8171bf22c1f588d1554d55bf204bc624af388433" integrity sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +undici-types@~7.8.0: + version "7.8.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.8.0.tgz#de00b85b710c54122e44fbfd911f8d70174cd294" + integrity sha512-9UJ2xGDvQ43tYyVMpuHlsgApydB8ZKfVYTsLDhXkFL/6gfkp+U8xTGdh8pMJv1SpZna0zxG1DwsKZsreLbXBxw== + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -13363,17 +13962,22 @@ utils-merge@1.0.1: resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" integrity sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA== +uuid@^11.0.2: + version "11.1.0" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-11.1.0.tgz#9549028be1753bb934fc96e2bca09bb4105ae912" + integrity sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A== + uuid@^3.3.2, uuid@^3.4.0: version "3.4.0" resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== -uuid@^8.3.0: +uuid@^8.0.0, uuid@^8.3.0: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== -uuid@^9.0.1: +uuid@^9.0.0, uuid@^9.0.1: version "9.0.1" resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== @@ -13568,6 +14172,20 @@ webpack@^5.91.0: watchpack "^2.4.1" webpack-sources "^3.2.3" +websocket-driver@>=0.5.1: + version "0.7.4" + resolved "https://registry.yarnpkg.com/websocket-driver/-/websocket-driver-0.7.4.tgz#89ad5295bbf64b480abcba31e4953aca706f5760" + integrity sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg== + dependencies: + http-parser-js ">=0.5.1" + safe-buffer ">=5.1.0" + websocket-extensions ">=0.1.1" + +websocket-extensions@>=0.1.1: + version "0.1.4" + resolved "https://registry.yarnpkg.com/websocket-extensions/-/websocket-extensions-0.1.4.tgz#7f8473bc839dfd87608adb95d7eb075211578a42" + integrity sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg== + wellknown@^0.5.0: version "0.5.0" resolved "https://registry.yarnpkg.com/wellknown/-/wellknown-0.5.0.tgz#09ae9871fa826cf0a6ec1537ef00c379d78d7101" @@ -13604,6 +14222,14 @@ whatwg-url@^13.0.0: tr46 "^4.1.1" webidl-conversions "^7.0.0" +whatwg-url@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" + integrity sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw== + dependencies: + tr46 "~0.0.3" + webidl-conversions "^3.0.0" + whatwg-url@^8.0.0, whatwg-url@^8.5.0: version "8.7.0" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-8.7.0.tgz#656a78e510ff8f3937bc0bcbe9f5c0ac35941b77"