@runnerty/executor-snowflake 1.0.1 → 1.1.0

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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm whoami *)",
5
+ "Bash(npm config *)"
6
+ ]
7
+ }
8
+ }
package/README.md CHANGED
@@ -76,18 +76,43 @@ export SNOWFLAKE_PASSWORD="mypassword"
76
76
  }
77
77
  ```
78
78
 
79
+ #### External Browser (SSO) Authentication:
80
+
81
+ Set `authenticator` to `externalbrowser` to authenticate through your identity provider (Okta, Azure AD, etc.) using the default browser, the same way tools like DataGrip do. This is useful for local development against accounts that are only reachable through federated SSO. The browser is opened once and, when `clientStoreTemporaryCredential` is enabled (default), the token is cached so subsequent connections reuse it without prompting again.
82
+
83
+ > Note: external browser authentication is interactive and therefore intended for local/interactive usage, not for headless/scheduled execution.
84
+
85
+ ```json
86
+ {
87
+ "id": "snowflake_default",
88
+ "type": "@runnerty-executor-snowflake",
89
+ "account": "@ENV(SNOWFLAKE_ACCOUNT)",
90
+ "user": "@ENV(SNOWFLAKE_USERNAME)",
91
+ "host": "@ENV(SNOWFLAKE_HOST)",
92
+ "database": "@ENV(SNOWFLAKE_DATABASE)",
93
+ "schema": "@ENV(SNOWFLAKE_SCHEMA)",
94
+ "warehouse": "@ENV(SNOWFLAKE_WAREHOUSE)",
95
+ "role": "@ENV(SNOWFLAKE_ROLE)",
96
+ "authenticator": "externalbrowser"
97
+ }
98
+ ```
99
+
79
100
  #### Configuration params:
80
101
 
81
- | Parameter | Description |
82
- | :---------- | :-------------------------------------------------------------- |
83
- | account | Snowflake account identifier (e.g., "myaccount.us-east-1") |
84
- | username | The Snowflake user to authenticate as. |
85
- | database | Name of the database to use for this connection. (Optional) |
86
- | schema | Name of the schema to use for this connection. (Optional) |
87
- | warehouse | Name of the warehouse to use for this connection. (Optional) |
88
- | role | Name of the role to use for this connection. (Optional) |
89
- | timeout | Connection timeout in milliseconds. (Default: 60000) |
90
- | application | Application name for connection tracking. (Default: "runnerty") |
102
+ | Parameter | Description |
103
+ | :----------------------------- | :----------------------------------------------------------------------------------------------------------- |
104
+ | account | Snowflake account identifier (e.g., "myaccount.us-east-1") |
105
+ | user | The Snowflake user to authenticate as. |
106
+ | host | Snowflake host name. (Optional) |
107
+ | database | Name of the database to use for this connection. (Optional) |
108
+ | schema | Name of the schema to use for this connection. (Optional) |
109
+ | warehouse | Name of the warehouse to use for this connection. (Optional) |
110
+ | role | Name of the role to use for this connection. (Optional) |
111
+ | authenticator | Authentication method. Set to `externalbrowser` for browser-based SSO. (Default: OAuth token authentication) |
112
+ | clientStoreTemporaryCredential | Cache the SSO token so the browser opens only once. Only applies to `externalbrowser`. (Default: true) |
113
+ | browserActionTimeout | Time in milliseconds to wait for the browser SSO action. Only applies to `externalbrowser`. (Optional) |
114
+ | timeout | Connection timeout in milliseconds. (Default: 60000) |
115
+ | application | Application name for connection tracking. (Default: "runnerty") |
91
116
 
92
117
  ### Plan samples:
93
118
 
@@ -259,6 +284,7 @@ This executor requires OAuth authentication setup. Make sure you have:
259
284
  ### Features:
260
285
 
261
286
  - ✅ **OAuth Authentication** - Secure token-based authentication
287
+ - ✅ **External Browser (SSO)** - Browser-based federated authentication (Okta, Azure AD, ...)
262
288
  - ✅ **Streaming Support** - Efficient processing of large datasets
263
289
  - ✅ **Multiple Export Formats** - XLSX, CSV, JSON
264
290
  - ✅ **Parameterized Queries** - Support for `:parameter` placeholders
package/index.js CHANGED
@@ -59,21 +59,30 @@ class snowflakeExecutor extends Executor {
59
59
 
60
60
  async createConnection(params) {
61
61
  try {
62
- const token = await getToken(params);
62
+ const useExternalBrowser = (params.authenticator || '').toLowerCase() === 'externalbrowser';
63
+
64
+ // The external browser (SSO) flow does not use the OAuth token endpoint
65
+ const token = useExternalBrowser ? null : await getToken(params);
63
66
 
64
67
  const connectionOptions = this.getConnectionOptions(params, token);
65
68
 
66
69
  return new Promise((resolve, reject) => {
67
70
  const connection = snowflake.createConnection(connectionOptions);
68
71
 
69
- // Usar connect normal con token OAuth
70
- connection.connect((err, conn) => {
72
+ const connectCallback = (err, conn) => {
71
73
  if (err) {
72
74
  reject(new Error(`Snowflake connection error: ${err.message}`));
73
75
  } else {
74
76
  resolve(conn);
75
77
  }
76
- });
78
+ };
79
+
80
+ // External browser (SSO) authentication is asynchronous: it must use connectAsync
81
+ if (useExternalBrowser) {
82
+ connection.connectAsync(connectCallback);
83
+ } else {
84
+ connection.connect(connectCallback);
85
+ }
77
86
  });
78
87
  } catch (error) {
79
88
  throw new Error(`Failed to get token or connect: ${error.message}`);
@@ -81,11 +90,9 @@ class snowflakeExecutor extends Executor {
81
90
  }
82
91
 
83
92
  getConnectionOptions(params, token) {
84
- return {
93
+ const options = {
85
94
  account: params.account,
86
95
  username: params.user,
87
- authenticator: 'oauth', // Especificar que usamos OAuth
88
- token: token, // Token OAuth obtenido de la API
89
96
  database: params.database,
90
97
  schema: params.schema,
91
98
  warehouse: params.warehouse,
@@ -93,6 +100,21 @@ class snowflakeExecutor extends Executor {
93
100
  timeout: params.timeout || 60000,
94
101
  application: params.application || 'runnerty'
95
102
  };
103
+
104
+ if ((params.authenticator || '').toLowerCase() === 'externalbrowser') {
105
+ // Browser-based SSO (opens the default browser to authenticate against the IdP).
106
+ // clientStoreTemporaryCredential caches the token so the browser is opened only
107
+ // once and reused across processes.
108
+ options.authenticator = 'EXTERNALBROWSER';
109
+ if (params.host) options.host = params.host;
110
+ options.clientStoreTemporaryCredential = params.clientStoreTemporaryCredential !== false;
111
+ if (params.browserActionTimeout) options.browserActionTimeout = params.browserActionTimeout;
112
+ } else {
113
+ options.authenticator = 'oauth'; // OAuth token obtained from the token endpoint
114
+ options.token = token;
115
+ }
116
+
117
+ return options;
96
118
  }
97
119
 
98
120
  async executeQuery(connection, query) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runnerty/executor-snowflake",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "Runnerty module: Snowflake executor",
5
5
  "author": "Coderty",
6
6
  "license": "MIT",
package/schema.json CHANGED
@@ -59,6 +59,36 @@
59
59
  },
60
60
  "encoding": {
61
61
  "type": "string"
62
+ },
63
+ "account": {
64
+ "type": "string"
65
+ },
66
+ "url": {
67
+ "type": "string"
68
+ },
69
+ "schema": {
70
+ "type": "string"
71
+ },
72
+ "warehouse": {
73
+ "type": "string"
74
+ },
75
+ "role": {
76
+ "type": "string"
77
+ },
78
+ "application": {
79
+ "type": "string"
80
+ },
81
+ "timeout": {
82
+ "type": "number"
83
+ },
84
+ "authenticator": {
85
+ "type": "string"
86
+ },
87
+ "browserActionTimeout": {
88
+ "type": "number"
89
+ },
90
+ "clientStoreTemporaryCredential": {
91
+ "type": "boolean"
62
92
  }
63
93
  }
64
94
  },