@duckcodeailabs/dql-cli 1.6.12 → 1.6.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/dql-notebook/assets/{index-McpLeeN0.js → index-osG-H64_.js} +225 -192
- package/dist/assets/dql-notebook/index.html +1 -1
- package/dist/llm/analytics-tools.d.ts.map +1 -1
- package/dist/llm/analytics-tools.js +2 -1
- package/dist/llm/analytics-tools.js.map +1 -1
- package/dist/llm/providers/claude-agent-sdk.d.ts.map +1 -1
- package/dist/llm/providers/claude-agent-sdk.js +2 -1
- package/dist/llm/providers/claude-agent-sdk.js.map +1 -1
- package/dist/llm/providers/claude-code.js +1 -0
- package/dist/llm/providers/claude-code.js.map +1 -1
- package/dist/llm/providers/dql-agent-provider.d.ts.map +1 -1
- package/dist/llm/providers/dql-agent-provider.js +1 -0
- package/dist/llm/providers/dql-agent-provider.js.map +1 -1
- package/dist/llm/types.d.ts +1 -0
- package/dist/llm/types.d.ts.map +1 -1
- package/dist/local-runtime.d.ts +11 -0
- package/dist/local-runtime.d.ts.map +1 -1
- package/dist/local-runtime.js +205 -77
- package/dist/local-runtime.js.map +1 -1
- package/dist/package.json +10 -10
- package/package.json +11 -11
- package/dist/assets/dql-notebook/assets/index-BbGJ8gZk.js +0 -3639
- package/dist/assets/dql-notebook/assets/index-C4oZK5xm.js +0 -3612
- package/dist/assets/dql-notebook/assets/index-CEMXuPm0.js +0 -3802
- package/dist/assets/dql-notebook/assets/index-CIMLd3Cb.js +0 -3289
- package/dist/assets/dql-notebook/assets/index-DISMWw19.js +0 -3780
package/dist/local-runtime.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import { execSync } from 'node:child_process';
|
|
1
|
+
import { execFileSync, execSync } from 'node:child_process';
|
|
2
2
|
import { createServer } from 'node:http';
|
|
3
3
|
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, statSync, watch, writeFileSync } from 'node:fs';
|
|
4
|
+
import { createRequire } from 'node:module';
|
|
4
5
|
import { homedir } from 'node:os';
|
|
5
6
|
import { dirname, extname, join, normalize, relative, resolve } from 'node:path';
|
|
6
7
|
import Anthropic from '@anthropic-ai/sdk';
|
|
@@ -1928,8 +1929,32 @@ export async function startLocalServer(opts) {
|
|
|
1928
1929
|
?? Object.keys(connections)[0]
|
|
1929
1930
|
?? 'default';
|
|
1930
1931
|
const dbtProfiles = discoverDbtProfileConnections(projectRoot, cfg);
|
|
1932
|
+
const connectorStatus = getConnectorInstallStatuses(projectRoot);
|
|
1931
1933
|
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1932
|
-
res.end(serializeJSON({ default: defaultKey, connections, dbtProfiles }));
|
|
1934
|
+
res.end(serializeJSON({ default: defaultKey, connections, dbtProfiles, connectorStatus }));
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
if (req.method === 'POST' && path === '/api/connectors/install') {
|
|
1938
|
+
try {
|
|
1939
|
+
const body = await readJSON(req);
|
|
1940
|
+
const driver = typeof body.driver === 'string' ? body.driver : '';
|
|
1941
|
+
const status = installConnectorPackage(projectRoot, driver);
|
|
1942
|
+
res.writeHead(200, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1943
|
+
res.end(serializeJSON({
|
|
1944
|
+
ok: true,
|
|
1945
|
+
status,
|
|
1946
|
+
connectorStatus: getConnectorInstallStatuses(projectRoot),
|
|
1947
|
+
}));
|
|
1948
|
+
}
|
|
1949
|
+
catch (error) {
|
|
1950
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
1951
|
+
res.writeHead(400, { 'Content-Type': 'application/json; charset=utf-8' });
|
|
1952
|
+
res.end(serializeJSON({
|
|
1953
|
+
ok: false,
|
|
1954
|
+
error: message,
|
|
1955
|
+
connectorStatus: getConnectorInstallStatuses(projectRoot),
|
|
1956
|
+
}));
|
|
1957
|
+
}
|
|
1933
1958
|
return;
|
|
1934
1959
|
}
|
|
1935
1960
|
// Save/update connections
|
|
@@ -3636,6 +3661,90 @@ function getProjectConnectionsForApi(config) {
|
|
|
3636
3661
|
}
|
|
3637
3662
|
return connections;
|
|
3638
3663
|
}
|
|
3664
|
+
const CONNECTOR_INSTALLS = {
|
|
3665
|
+
duckdb: {
|
|
3666
|
+
driver: 'duckdb',
|
|
3667
|
+
label: 'DuckDB',
|
|
3668
|
+
packageName: 'duckdb',
|
|
3669
|
+
packageSpec: 'duckdb@^1.1.0',
|
|
3670
|
+
builtIn: false,
|
|
3671
|
+
},
|
|
3672
|
+
snowflake: {
|
|
3673
|
+
driver: 'snowflake',
|
|
3674
|
+
label: 'Snowflake',
|
|
3675
|
+
packageName: 'snowflake-sdk',
|
|
3676
|
+
packageSpec: 'snowflake-sdk@^1.12.0',
|
|
3677
|
+
builtIn: false,
|
|
3678
|
+
},
|
|
3679
|
+
databricks: {
|
|
3680
|
+
driver: 'databricks',
|
|
3681
|
+
label: 'Databricks',
|
|
3682
|
+
builtIn: true,
|
|
3683
|
+
},
|
|
3684
|
+
};
|
|
3685
|
+
function connectorInstallRoot(projectRoot) {
|
|
3686
|
+
return join(projectRoot, '.dql', 'connectors');
|
|
3687
|
+
}
|
|
3688
|
+
function connectorModuleSearchPaths(projectRoot) {
|
|
3689
|
+
return [connectorInstallRoot(projectRoot), projectRoot];
|
|
3690
|
+
}
|
|
3691
|
+
function connectorInstallCommand(projectRoot, packageSpec) {
|
|
3692
|
+
return `npm install --prefix ${connectorInstallRoot(projectRoot)} ${packageSpec}`;
|
|
3693
|
+
}
|
|
3694
|
+
function isConnectorPackageInstalled(projectRoot, packageName) {
|
|
3695
|
+
for (const basePath of connectorModuleSearchPaths(projectRoot)) {
|
|
3696
|
+
try {
|
|
3697
|
+
const req = createRequire(join(basePath, 'package.json'));
|
|
3698
|
+
req.resolve(packageName);
|
|
3699
|
+
return true;
|
|
3700
|
+
}
|
|
3701
|
+
catch {
|
|
3702
|
+
// Try the next supported location.
|
|
3703
|
+
}
|
|
3704
|
+
}
|
|
3705
|
+
return false;
|
|
3706
|
+
}
|
|
3707
|
+
export function getConnectorInstallStatuses(projectRoot) {
|
|
3708
|
+
return Object.values(CONNECTOR_INSTALLS).map((definition) => {
|
|
3709
|
+
const installPath = connectorInstallRoot(projectRoot);
|
|
3710
|
+
const installed = definition.builtIn || (definition.packageName
|
|
3711
|
+
? isConnectorPackageInstalled(projectRoot, definition.packageName)
|
|
3712
|
+
: true);
|
|
3713
|
+
return {
|
|
3714
|
+
...definition,
|
|
3715
|
+
installed,
|
|
3716
|
+
installPath,
|
|
3717
|
+
installCommand: definition.packageSpec
|
|
3718
|
+
? connectorInstallCommand(projectRoot, definition.packageSpec)
|
|
3719
|
+
: undefined,
|
|
3720
|
+
};
|
|
3721
|
+
});
|
|
3722
|
+
}
|
|
3723
|
+
function installConnectorPackage(projectRoot, driver) {
|
|
3724
|
+
const definition = CONNECTOR_INSTALLS[driver];
|
|
3725
|
+
if (!definition) {
|
|
3726
|
+
throw new Error(`Unknown connector "${driver}".`);
|
|
3727
|
+
}
|
|
3728
|
+
if (definition.builtIn || !definition.packageSpec) {
|
|
3729
|
+
return getConnectorInstallStatuses(projectRoot).find((status) => status.driver === definition.driver);
|
|
3730
|
+
}
|
|
3731
|
+
const installRoot = connectorInstallRoot(projectRoot);
|
|
3732
|
+
mkdirSync(installRoot, { recursive: true });
|
|
3733
|
+
const packageJsonPath = join(installRoot, 'package.json');
|
|
3734
|
+
if (!existsSync(packageJsonPath)) {
|
|
3735
|
+
writeFileSync(packageJsonPath, JSON.stringify({
|
|
3736
|
+
private: true,
|
|
3737
|
+
description: 'Project-local DQL connector packages',
|
|
3738
|
+
}, null, 2) + '\n', 'utf-8');
|
|
3739
|
+
}
|
|
3740
|
+
execFileSync('npm', ['install', '--prefix', installRoot, '--no-audit', '--no-fund', definition.packageSpec], {
|
|
3741
|
+
cwd: projectRoot,
|
|
3742
|
+
encoding: 'utf-8',
|
|
3743
|
+
stdio: 'pipe',
|
|
3744
|
+
timeout: 10 * 60 * 1000,
|
|
3745
|
+
});
|
|
3746
|
+
return getConnectorInstallStatuses(projectRoot).find((status) => status.driver === definition.driver);
|
|
3747
|
+
}
|
|
3639
3748
|
function getStoredConnections(raw) {
|
|
3640
3749
|
const value = raw.connections;
|
|
3641
3750
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
@@ -3940,6 +4049,9 @@ export function normalizeProjectConnection(connection, projectRoot) {
|
|
|
3940
4049
|
if ((normalized.driver === 'file' || normalized.driver === 'duckdb') && normalized.filepath && normalized.filepath !== ':memory:' && !isAbsoluteLikePath(normalized.filepath)) {
|
|
3941
4050
|
normalized.filepath = resolve(projectRoot, normalized.filepath);
|
|
3942
4051
|
}
|
|
4052
|
+
if (normalized.driver === 'file' || normalized.driver === 'duckdb' || normalized.driver === 'snowflake') {
|
|
4053
|
+
normalized.moduleSearchPaths = connectorModuleSearchPaths(projectRoot);
|
|
4054
|
+
}
|
|
3943
4055
|
if (normalized.driver === 'sqlite' && normalized.database && normalized.database !== ':memory:' && !isAbsoluteLikePath(normalized.database)) {
|
|
3944
4056
|
normalized.database = resolve(projectRoot, normalized.database);
|
|
3945
4057
|
}
|
|
@@ -5711,45 +5823,7 @@ function mapDbtProfileOutput(output) {
|
|
|
5711
5823
|
result.envRefs.forEach((ref) => envRefs.add(ref));
|
|
5712
5824
|
return result.value;
|
|
5713
5825
|
};
|
|
5714
|
-
const port = numberValue(output, 'port');
|
|
5715
|
-
const sslRaw = read('ssl', 'sslmode');
|
|
5716
|
-
const ssl = sslRaw === undefined
|
|
5717
|
-
? undefined
|
|
5718
|
-
: !['false', '0', 'disable', 'disabled', 'off'].includes(sslRaw.toLowerCase());
|
|
5719
5826
|
switch (adapter) {
|
|
5720
|
-
case 'postgres':
|
|
5721
|
-
case 'postgresql':
|
|
5722
|
-
return {
|
|
5723
|
-
adapter,
|
|
5724
|
-
connection: compactConnection({
|
|
5725
|
-
driver: 'postgresql',
|
|
5726
|
-
host: read('host'),
|
|
5727
|
-
port,
|
|
5728
|
-
database: read('dbname', 'database'),
|
|
5729
|
-
schema: read('schema'),
|
|
5730
|
-
username: read('user', 'username'),
|
|
5731
|
-
password: read('password', 'pass'),
|
|
5732
|
-
ssl,
|
|
5733
|
-
}),
|
|
5734
|
-
envRefs: [...envRefs],
|
|
5735
|
-
warnings,
|
|
5736
|
-
};
|
|
5737
|
-
case 'redshift':
|
|
5738
|
-
return {
|
|
5739
|
-
adapter,
|
|
5740
|
-
connection: compactConnection({
|
|
5741
|
-
driver: 'redshift',
|
|
5742
|
-
host: read('host'),
|
|
5743
|
-
port: port ?? 5439,
|
|
5744
|
-
database: read('dbname', 'database'),
|
|
5745
|
-
schema: read('schema'),
|
|
5746
|
-
username: read('user', 'username'),
|
|
5747
|
-
password: read('password', 'pass'),
|
|
5748
|
-
ssl,
|
|
5749
|
-
}),
|
|
5750
|
-
envRefs: [...envRefs],
|
|
5751
|
-
warnings,
|
|
5752
|
-
};
|
|
5753
5827
|
case 'snowflake': {
|
|
5754
5828
|
const privateKeyPath = read('private_key_path', 'privateKeyPath');
|
|
5755
5829
|
const privateKey = read('private_key', 'privateKey');
|
|
@@ -5759,9 +5833,19 @@ function mapDbtProfileOutput(output) {
|
|
|
5759
5833
|
? 'key_pair'
|
|
5760
5834
|
: normalizedAuthenticator === 'externalbrowser'
|
|
5761
5835
|
? 'external_browser'
|
|
5762
|
-
: normalizedAuthenticator === '
|
|
5763
|
-
? '
|
|
5764
|
-
: '
|
|
5836
|
+
: normalizedAuthenticator === 'usernamepasswordmfa'
|
|
5837
|
+
? 'mfa'
|
|
5838
|
+
: normalizedAuthenticator === 'oauthauthorizationcode'
|
|
5839
|
+
? 'oauth_authorization_code'
|
|
5840
|
+
: normalizedAuthenticator === 'oauthclientcredentials'
|
|
5841
|
+
? 'oauth_client_credentials'
|
|
5842
|
+
: normalizedAuthenticator === 'programmaticaccesstoken'
|
|
5843
|
+
? 'programmatic_access_token'
|
|
5844
|
+
: normalizedAuthenticator === 'workloadidentity'
|
|
5845
|
+
? 'workload_identity'
|
|
5846
|
+
: normalizedAuthenticator === 'oauth'
|
|
5847
|
+
? 'oauth'
|
|
5848
|
+
: 'password';
|
|
5765
5849
|
return {
|
|
5766
5850
|
adapter,
|
|
5767
5851
|
connection: compactConnection({
|
|
@@ -5778,22 +5862,34 @@ function mapDbtProfileOutput(output) {
|
|
|
5778
5862
|
privateKeyPassphrase: read('private_key_passphrase', 'privateKeyPassphrase'),
|
|
5779
5863
|
authenticator,
|
|
5780
5864
|
authMethod,
|
|
5781
|
-
|
|
5782
|
-
|
|
5783
|
-
|
|
5784
|
-
|
|
5785
|
-
|
|
5786
|
-
|
|
5787
|
-
|
|
5788
|
-
|
|
5789
|
-
|
|
5790
|
-
|
|
5791
|
-
|
|
5792
|
-
|
|
5793
|
-
|
|
5794
|
-
|
|
5795
|
-
|
|
5796
|
-
|
|
5865
|
+
token: read('token'),
|
|
5866
|
+
accessUrl: read('access_url', 'accessUrl'),
|
|
5867
|
+
application: read('application'),
|
|
5868
|
+
browserActionTimeout: readNumber(output, 'browser_action_timeout', 'browserActionTimeout'),
|
|
5869
|
+
clientRequestMFAToken: readBoolean(output, 'client_request_mfa_token', 'clientRequestMFAToken'),
|
|
5870
|
+
clientStoreTemporaryCredential: readBoolean(output, 'client_store_temporary_credential', 'clientStoreTemporaryCredential'),
|
|
5871
|
+
clientSessionKeepAlive: readBoolean(output, 'client_session_keep_alive', 'clientSessionKeepAlive'),
|
|
5872
|
+
clientSessionKeepAliveHeartbeatFrequency: readNumber(output, 'client_session_keep_alive_heartbeat_frequency', 'clientSessionKeepAliveHeartbeatFrequency'),
|
|
5873
|
+
credentialCacheDir: read('credential_cache_dir', 'credentialCacheDir'),
|
|
5874
|
+
keepAlive: readBoolean(output, 'keep_alive', 'keepAlive'),
|
|
5875
|
+
noProxy: read('no_proxy', 'noProxy'),
|
|
5876
|
+
oauthAuthorizationUrl: read('oauth_authorization_url', 'oauthAuthorizationUrl'),
|
|
5877
|
+
oauthClientId: read('oauth_client_id', 'oauthClientId'),
|
|
5878
|
+
oauthClientSecret: read('oauth_client_secret', 'oauthClientSecret'),
|
|
5879
|
+
oauthRedirectUri: read('oauth_redirect_uri', 'oauthRedirectUri'),
|
|
5880
|
+
oauthScope: read('oauth_scope', 'oauthScope'),
|
|
5881
|
+
oauthTokenRequestUrl: read('oauth_token_request_url', 'oauthTokenRequestUrl'),
|
|
5882
|
+
passcode: read('passcode'),
|
|
5883
|
+
passcodeInPassword: readBoolean(output, 'passcode_in_password', 'passcodeInPassword'),
|
|
5884
|
+
proxyHost: read('proxy_host', 'proxyHost'),
|
|
5885
|
+
proxyPassword: read('proxy_password', 'proxyPassword'),
|
|
5886
|
+
proxyPort: readNumber(output, 'proxy_port', 'proxyPort'),
|
|
5887
|
+
proxyProtocol: read('proxy_protocol', 'proxyProtocol'),
|
|
5888
|
+
proxyUser: read('proxy_user', 'proxyUser'),
|
|
5889
|
+
queryTag: read('query_tag', 'queryTag'),
|
|
5890
|
+
timeout: readNumber(output, 'timeout'),
|
|
5891
|
+
workloadIdentityProvider: read('workload_identity_provider', 'workloadIdentityProvider'),
|
|
5892
|
+
workloadIdentityAzureClientId: read('workload_identity_azure_client_id', 'workloadIdentityAzureClientId'),
|
|
5797
5893
|
}),
|
|
5798
5894
|
envRefs: [...envRefs],
|
|
5799
5895
|
warnings,
|
|
@@ -5809,7 +5905,9 @@ function mapDbtProfileOutput(output) {
|
|
|
5809
5905
|
envRefs: [...envRefs],
|
|
5810
5906
|
warnings,
|
|
5811
5907
|
};
|
|
5812
|
-
case 'databricks':
|
|
5908
|
+
case 'databricks': {
|
|
5909
|
+
const databricksAuth = read('auth_type', 'auth_method', 'authMethod');
|
|
5910
|
+
const authMethod = databricksAuth?.toLowerCase().includes('oauth') ? 'oauth' : 'token';
|
|
5813
5911
|
return {
|
|
5814
5912
|
adapter,
|
|
5815
5913
|
connection: compactConnection({
|
|
@@ -5821,15 +5919,44 @@ function mapDbtProfileOutput(output) {
|
|
|
5821
5919
|
database: read('catalog', 'database'),
|
|
5822
5920
|
schema: read('schema'),
|
|
5823
5921
|
token: read('token'),
|
|
5824
|
-
authMethod
|
|
5922
|
+
authMethod,
|
|
5923
|
+
waitTimeout: read('wait_timeout', 'waitTimeout'),
|
|
5924
|
+
byteLimit: readNumber(output, 'byte_limit', 'byteLimit'),
|
|
5825
5925
|
}),
|
|
5826
5926
|
envRefs: [...envRefs],
|
|
5827
5927
|
warnings,
|
|
5828
5928
|
};
|
|
5929
|
+
}
|
|
5829
5930
|
default:
|
|
5830
5931
|
return null;
|
|
5831
5932
|
}
|
|
5832
5933
|
}
|
|
5934
|
+
function readBoolean(source, ...keys) {
|
|
5935
|
+
for (const key of keys) {
|
|
5936
|
+
const raw = source[key];
|
|
5937
|
+
if (typeof raw === 'boolean')
|
|
5938
|
+
return raw;
|
|
5939
|
+
if (raw === undefined || raw === null)
|
|
5940
|
+
continue;
|
|
5941
|
+
const value = String(raw).trim().toLowerCase();
|
|
5942
|
+
if (['true', '1', 'yes', 'y'].includes(value))
|
|
5943
|
+
return true;
|
|
5944
|
+
if (['false', '0', 'no', 'n'].includes(value))
|
|
5945
|
+
return false;
|
|
5946
|
+
}
|
|
5947
|
+
return undefined;
|
|
5948
|
+
}
|
|
5949
|
+
function readNumber(source, ...keys) {
|
|
5950
|
+
for (const key of keys) {
|
|
5951
|
+
const raw = source[key];
|
|
5952
|
+
if (raw === undefined || raw === null || raw === '')
|
|
5953
|
+
continue;
|
|
5954
|
+
const value = Number(raw);
|
|
5955
|
+
if (Number.isFinite(value))
|
|
5956
|
+
return value;
|
|
5957
|
+
}
|
|
5958
|
+
return undefined;
|
|
5959
|
+
}
|
|
5833
5960
|
function text(source, ...keys) {
|
|
5834
5961
|
for (const key of keys) {
|
|
5835
5962
|
const raw = source[key];
|
|
@@ -5855,13 +5982,6 @@ function resolveDbtEnvVars(value) {
|
|
|
5855
5982
|
});
|
|
5856
5983
|
return { value: replaced, envRefs };
|
|
5857
5984
|
}
|
|
5858
|
-
function numberValue(source, key) {
|
|
5859
|
-
const raw = source[key];
|
|
5860
|
-
if (raw === undefined || raw === null || raw === '')
|
|
5861
|
-
return undefined;
|
|
5862
|
-
const value = Number(raw);
|
|
5863
|
-
return Number.isFinite(value) ? value : undefined;
|
|
5864
|
-
}
|
|
5865
5985
|
function compactConnection(connection) {
|
|
5866
5986
|
const compact = {};
|
|
5867
5987
|
for (const [key, value] of Object.entries(connection)) {
|
|
@@ -5879,12 +5999,6 @@ function requiredConnectionFields(connection, envRefs) {
|
|
|
5879
5999
|
missing.add(String(field));
|
|
5880
6000
|
};
|
|
5881
6001
|
switch (connection.driver) {
|
|
5882
|
-
case 'postgresql':
|
|
5883
|
-
case 'redshift':
|
|
5884
|
-
needs('host');
|
|
5885
|
-
needs('database');
|
|
5886
|
-
needs('username');
|
|
5887
|
-
break;
|
|
5888
6002
|
case 'snowflake':
|
|
5889
6003
|
needs('account');
|
|
5890
6004
|
needs('warehouse');
|
|
@@ -5901,13 +6015,27 @@ function requiredConnectionFields(connection, envRefs) {
|
|
|
5901
6015
|
missing.add('token');
|
|
5902
6016
|
}
|
|
5903
6017
|
}
|
|
6018
|
+
else if (connection.authMethod === 'programmatic_access_token') {
|
|
6019
|
+
if (!connection.token && !connection.password) {
|
|
6020
|
+
missing.add('token');
|
|
6021
|
+
}
|
|
6022
|
+
}
|
|
6023
|
+
else if (connection.authMethod === 'oauth_authorization_code') {
|
|
6024
|
+
needs('oauthClientId');
|
|
6025
|
+
needs('oauthClientSecret');
|
|
6026
|
+
}
|
|
6027
|
+
else if (connection.authMethod === 'oauth_client_credentials') {
|
|
6028
|
+
needs('oauthClientId');
|
|
6029
|
+
needs('oauthClientSecret');
|
|
6030
|
+
needs('oauthTokenRequestUrl');
|
|
6031
|
+
}
|
|
6032
|
+
else if (connection.authMethod === 'workload_identity') {
|
|
6033
|
+
needs('workloadIdentityProvider');
|
|
6034
|
+
}
|
|
5904
6035
|
else if (connection.authMethod !== 'external_browser') {
|
|
5905
6036
|
needs('password');
|
|
5906
6037
|
}
|
|
5907
6038
|
break;
|
|
5908
|
-
case 'bigquery':
|
|
5909
|
-
needs('projectId');
|
|
5910
|
-
break;
|
|
5911
6039
|
case 'duckdb':
|
|
5912
6040
|
needs('filepath');
|
|
5913
6041
|
break;
|