@lightdash/cli 2.562.0 → 2.563.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.
- package/dist/.tsbuildinfo.build +1 -1
- package/dist/agentConnectionConnectOption.d.ts +8 -0
- package/dist/agentConnectionConnectOption.d.ts.map +1 -0
- package/dist/agentConnectionConnectOption.js +39 -0
- package/dist/agentConnectionOption.d.ts +3 -0
- package/dist/agentConnectionOption.d.ts.map +1 -0
- package/dist/agentConnectionOption.js +48 -0
- package/dist/agentConnections/agentTokenProvider.d.ts +13 -0
- package/dist/agentConnections/agentTokenProvider.d.ts.map +1 -0
- package/dist/agentConnections/agentTokenProvider.js +294 -0
- package/dist/agentConnections/apiUrl.d.ts +4 -0
- package/dist/agentConnections/apiUrl.d.ts.map +1 -0
- package/dist/agentConnections/apiUrl.js +37 -0
- package/dist/agentConnections/commandPolicy.d.ts +14 -0
- package/dist/agentConnections/commandPolicy.d.ts.map +1 -0
- package/dist/agentConnections/commandPolicy.js +108 -0
- package/dist/agentConnections/configLock.d.ts +12 -0
- package/dist/agentConnections/configLock.d.ts.map +1 -0
- package/dist/agentConnections/configLock.js +191 -0
- package/dist/agentConnections/connectInputs.d.ts +20 -0
- package/dist/agentConnections/connectInputs.d.ts.map +1 -0
- package/dist/agentConnections/connectInputs.js +49 -0
- package/dist/agentConnections/fixtures.d.ts +3 -0
- package/dist/agentConnections/fixtures.d.ts.map +1 -0
- package/dist/agentConnections/fixtures.js +36 -0
- package/dist/agentConnections/initialToken.d.ts +26 -0
- package/dist/agentConnections/initialToken.d.ts.map +1 -0
- package/dist/agentConnections/initialToken.js +93 -0
- package/dist/agentConnections/lifecycle.d.ts +17 -0
- package/dist/agentConnections/lifecycle.d.ts.map +1 -0
- package/dist/agentConnections/lifecycle.js +44 -0
- package/dist/agentConnections/personalRecovery.d.ts +27 -0
- package/dist/agentConnections/personalRecovery.d.ts.map +1 -0
- package/dist/agentConnections/personalRecovery.js +71 -0
- package/dist/agentConnections/projectSelection.d.ts +4 -0
- package/dist/agentConnections/projectSelection.d.ts.map +1 -0
- package/dist/agentConnections/projectSelection.js +48 -0
- package/dist/agentConnections/providerProcess.fixture.d.ts +2 -0
- package/dist/agentConnections/providerProcess.fixture.d.ts.map +1 -0
- package/dist/agentConnections/providerProcess.fixture.js +19 -0
- package/dist/agentConnections/requestPolicy.d.ts +11 -0
- package/dist/agentConnections/requestPolicy.d.ts.map +1 -0
- package/dist/agentConnections/requestPolicy.js +76 -0
- package/dist/agentConnections/schema.d.ts +66 -0
- package/dist/agentConnections/schema.d.ts.map +1 -0
- package/dist/agentConnections/schema.js +184 -0
- package/dist/agentConnections/statusResponse.d.ts +10 -0
- package/dist/agentConnections/statusResponse.d.ts.map +1 -0
- package/dist/agentConnections/statusResponse.js +146 -0
- package/dist/agentConnections/store.d.ts +36 -0
- package/dist/agentConnections/store.d.ts.map +1 -0
- package/dist/agentConnections/store.js +275 -0
- package/dist/agentConnections/warehouseStatus.d.ts +30 -0
- package/dist/agentConnections/warehouseStatus.d.ts.map +1 -0
- package/dist/agentConnections/warehouseStatus.js +184 -0
- package/dist/analytics/analytics.d.ts.map +1 -1
- package/dist/analytics/analytics.js +4 -0
- package/dist/config.d.ts +3 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +2 -2
- package/dist/credentials.d.ts +27 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +161 -0
- package/dist/dbt/models.d.ts.map +1 -1
- package/dist/dbt/models.js +45 -14
- package/dist/handlers/agentAccess.d.ts.map +1 -1
- package/dist/handlers/agentAccess.js +9 -1
- package/dist/handlers/agentConnect.d.ts.map +1 -1
- package/dist/handlers/agentConnect.js +2 -0
- package/dist/handlers/agentConnectionConnect.d.ts +5 -0
- package/dist/handlers/agentConnectionConnect.d.ts.map +1 -0
- package/dist/handlers/agentConnectionConnect.js +371 -0
- package/dist/handlers/agentConnectionStatus.d.ts +7 -0
- package/dist/handlers/agentConnectionStatus.d.ts.map +1 -0
- package/dist/handlers/agentConnectionStatus.js +228 -0
- package/dist/handlers/agentRevoke.d.ts +7 -0
- package/dist/handlers/agentRevoke.d.ts.map +1 -0
- package/dist/handlers/agentRevoke.js +144 -0
- package/dist/handlers/agentStatus.d.ts +4 -1
- package/dist/handlers/agentStatus.d.ts.map +1 -1
- package/dist/handlers/agentStatus.js +7 -0
- package/dist/handlers/apps/createApp.d.ts.map +1 -1
- package/dist/handlers/apps/createApp.js +2 -0
- package/dist/handlers/apps/preview.d.ts.map +1 -1
- package/dist/handlers/apps/preview.js +6 -0
- package/dist/handlers/apps/previewProxy.d.ts.map +1 -1
- package/dist/handlers/apps/previewProxy.js +2 -0
- package/dist/handlers/apps/validate.d.ts.map +1 -1
- package/dist/handlers/apps/validate.js +20 -8
- package/dist/handlers/compile.d.ts.map +1 -1
- package/dist/handlers/compile.js +3 -0
- package/dist/handlers/connectSnowflake.d.ts.map +1 -1
- package/dist/handlers/connectSnowflake.js +2 -0
- package/dist/handlers/createProject.d.ts.map +1 -1
- package/dist/handlers/createProject.js +2 -0
- package/dist/handlers/dbt/apiClient.d.ts +4 -2
- package/dist/handlers/dbt/apiClient.d.ts.map +1 -1
- package/dist/handlers/dbt/apiClient.js +138 -4
- package/dist/handlers/dbt/compile.d.ts.map +1 -1
- package/dist/handlers/dbt/compile.js +13 -2
- package/dist/handlers/dbt/getDbtProfileTargetName.d.ts.map +1 -1
- package/dist/handlers/dbt/getDbtProfileTargetName.js +12 -4
- package/dist/handlers/dbt/getDbtVersion.d.ts.map +1 -1
- package/dist/handlers/dbt/getDbtVersion.js +12 -4
- package/dist/handlers/dbt/getWarehouseClient.d.ts.map +1 -1
- package/dist/handlers/dbt/getWarehouseClient.js +15 -5
- package/dist/handlers/dbt/refresh.d.ts.map +1 -1
- package/dist/handlers/dbt/refresh.js +2 -0
- package/dist/handlers/dbt/run.d.ts.map +1 -1
- package/dist/handlers/dbt/run.js +10 -3
- package/dist/handlers/deploy.d.ts.map +1 -1
- package/dist/handlers/deploy.js +17 -1
- package/dist/handlers/diagnostics.d.ts.map +1 -1
- package/dist/handlers/diagnostics.js +2 -0
- package/dist/handlers/download.d.ts.map +1 -1
- package/dist/handlers/download.js +19 -5
- package/dist/handlers/exportChartImage.d.ts.map +1 -1
- package/dist/handlers/exportChartImage.js +2 -0
- package/dist/handlers/generateExposures.d.ts.map +1 -1
- package/dist/handlers/generateExposures.js +4 -1
- package/dist/handlers/getProject.d.ts.map +1 -1
- package/dist/handlers/getProject.js +25 -1
- package/dist/handlers/listProjects.d.ts.map +1 -1
- package/dist/handlers/listProjects.js +2 -0
- package/dist/handlers/login/connectionBrowser.d.ts +2 -0
- package/dist/handlers/login/connectionBrowser.d.ts.map +1 -0
- package/dist/handlers/login/connectionBrowser.js +22 -0
- package/dist/handlers/login/loopback.d.ts +15 -0
- package/dist/handlers/login/loopback.d.ts.map +1 -0
- package/dist/handlers/login/loopback.js +135 -0
- package/dist/handlers/login/oauth.d.ts.map +1 -1
- package/dist/handlers/login/oauth.js +16 -3
- package/dist/handlers/login/pat.d.ts.map +1 -1
- package/dist/handlers/login/pat.js +2 -0
- package/dist/handlers/login.d.ts.map +1 -1
- package/dist/handlers/login.js +8 -1
- package/dist/handlers/oauthLogin.d.ts.map +1 -1
- package/dist/handlers/oauthLogin.js +2 -0
- package/dist/handlers/ordinary/harness.mocks.d.ts +42 -0
- package/dist/handlers/ordinary/harness.mocks.d.ts.map +1 -0
- package/dist/handlers/ordinary/harness.mocks.js +180 -0
- package/dist/handlers/preAggregateAudit.d.ts.map +1 -1
- package/dist/handlers/preAggregateAudit.js +2 -0
- package/dist/handlers/preview.d.ts.map +1 -1
- package/dist/handlers/preview.js +4 -0
- package/dist/handlers/renameHandler.d.ts.map +1 -1
- package/dist/handlers/renameHandler.js +2 -0
- package/dist/handlers/renameProject.d.ts.map +1 -1
- package/dist/handlers/renameProject.js +2 -0
- package/dist/handlers/resolveProjectFlag.d.ts.map +1 -1
- package/dist/handlers/resolveProjectFlag.js +5 -0
- package/dist/handlers/runChart.d.ts.map +1 -1
- package/dist/handlers/runChart.js +7 -2
- package/dist/handlers/selectProject.d.ts.map +1 -1
- package/dist/handlers/selectProject.js +5 -0
- package/dist/handlers/setProject.d.ts.map +1 -1
- package/dist/handlers/setProject.js +5 -0
- package/dist/handlers/setWarehouse.d.ts.map +1 -1
- package/dist/handlers/setWarehouse.js +2 -0
- package/dist/handlers/slugUpdate.d.ts.map +1 -1
- package/dist/handlers/slugUpdate.js +2 -0
- package/dist/handlers/sourceSelection.d.ts.map +1 -1
- package/dist/handlers/sourceSelection.js +13 -2
- package/dist/handlers/sql.d.ts.map +1 -1
- package/dist/handlers/sql.js +7 -2
- package/dist/handlers/utils.d.ts +3 -0
- package/dist/handlers/utils.d.ts.map +1 -1
- package/dist/handlers/utils.js +39 -0
- package/dist/handlers/validate.d.ts.map +1 -1
- package/dist/handlers/validate.js +2 -0
- package/dist/handlers/warehouseCatalog.d.ts.map +1 -1
- package/dist/handlers/warehouseCatalog.js +7 -2
- package/dist/index.js +43 -3
- package/dist/lightdash-config/index.d.ts.map +1 -1
- package/dist/lightdash-config/index.js +4 -1
- package/package.json +3 -3
|
@@ -6,11 +6,13 @@ const fs_1 = require("fs");
|
|
|
6
6
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
7
7
|
const uuid_1 = require("uuid");
|
|
8
8
|
const config_1 = require("../config");
|
|
9
|
+
const credentials_1 = require("../credentials");
|
|
9
10
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
10
11
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
11
12
|
const apiClient_1 = require("./dbt/apiClient");
|
|
12
13
|
const resolveProjectFlag_1 = require("./resolveProjectFlag");
|
|
13
14
|
const exportChartImageHandler = async (chartUuidOrSlug, options) => {
|
|
15
|
+
(0, credentials_1.refuseAgentConnection)();
|
|
14
16
|
globalState_1.default.setVerbose(options.verbose ?? false);
|
|
15
17
|
const spinner = globalState_1.default.startSpinner(`Exporting chart image for '${chartUuidOrSlug}'...`);
|
|
16
18
|
const isChartUuid = (0, uuid_1.validate)(chartUuidOrSlug);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateExposures.d.ts","sourceRoot":"","sources":["../../src/handlers/generateExposures.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"generateExposures.d.ts","sourceRoot":"","sources":["../../src/handlers/generateExposures.ts"],"names":[],"mappings":"AAmBA,KAAK,+BAA+B,GAAG;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,eAAO,MAAM,wBAAwB,YACxB,+BAA+B,kBAmH3C,CAAC"}
|
|
@@ -9,6 +9,7 @@ const path = tslib_1.__importStar(require("path"));
|
|
|
9
9
|
const uuid_1 = require("uuid");
|
|
10
10
|
const analytics_1 = require("../analytics/analytics");
|
|
11
11
|
const config_1 = require("../config");
|
|
12
|
+
const credentials_1 = require("../credentials");
|
|
12
13
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
13
14
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
14
15
|
const apiClient_1 = require("./dbt/apiClient");
|
|
@@ -17,7 +18,9 @@ const generateExposuresHandler = async (options) => {
|
|
|
17
18
|
globalState_1.default.setVerbose(options.verbose);
|
|
18
19
|
await (0, apiClient_1.checkLightdashVersion)();
|
|
19
20
|
const executionId = (0, uuid_1.v4)();
|
|
20
|
-
const config = await (0,
|
|
21
|
+
const config = await ((0, credentials_1.getAgentConnectionSelection)() === null
|
|
22
|
+
? (0, config_1.getConfig)()
|
|
23
|
+
: (0, config_1.getConfig)({ readOnly: true }).then(async (currentConfig) => (await Promise.resolve().then(() => tslib_1.__importStar(require('../agentConnections/projectSelection')))).configWithAgentProject(currentConfig)));
|
|
21
24
|
if (!(config.context?.project && config.context.serverUrl)) {
|
|
22
25
|
throw new common_1.AuthorizationError(`No active Lightdash project. Run 'lightdash login --help'`);
|
|
23
26
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getProject.d.ts","sourceRoot":"","sources":["../../src/handlers/getProject.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"getProject.d.ts","sourceRoot":"","sources":["../../src/handlers/getProject.ts"],"names":[],"mappings":"AAMA,KAAK,iBAAiB,GAAG;IACrB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,iBAAiB,YAAmB,iBAAiB,kBAsEjE,CAAC"}
|
|
@@ -4,6 +4,7 @@ exports.getProjectHandler = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const analytics_1 = require("../analytics/analytics");
|
|
6
6
|
const config_1 = require("../config");
|
|
7
|
+
const credentials_1 = require("../credentials");
|
|
7
8
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
8
9
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
9
10
|
const getProjectHandler = async (options) => {
|
|
@@ -11,7 +12,30 @@ const getProjectHandler = async (options) => {
|
|
|
11
12
|
let success = true;
|
|
12
13
|
globalState_1.default.setVerbose(options.verbose);
|
|
13
14
|
try {
|
|
14
|
-
const config = await (0,
|
|
15
|
+
const config = await ((0, credentials_1.getAgentConnectionSelection)() === null
|
|
16
|
+
? (0, config_1.getConfig)()
|
|
17
|
+
: (0, config_1.getConfig)({ readOnly: true }));
|
|
18
|
+
if ((0, credentials_1.getAgentConnectionSelection)() !== null) {
|
|
19
|
+
const credential = await (0, credentials_1.resolveCredential)(config);
|
|
20
|
+
if (credential.kind !== 'agent_connection')
|
|
21
|
+
throw new Error('An agent connection credential is required.');
|
|
22
|
+
const { publicConnectionReport } = await Promise.resolve().then(() => tslib_1.__importStar(require('../agentConnections/statusResponse')));
|
|
23
|
+
const { approvedProjects } = publicConnectionReport(credential.slot, [config.context?.apiKey, config.context?.proxyAuthorization]);
|
|
24
|
+
globalState_1.default.debug(`> Agent connection: ${JSON.stringify({ name: credential.slot.name, approvedProjects })}`);
|
|
25
|
+
if (approvedProjects.length === 1) {
|
|
26
|
+
const project = approvedProjects[0];
|
|
27
|
+
console.error(styles.bold('\nCurrent project:\n'));
|
|
28
|
+
console.error(` Name: ${project.name ?? 'Name unavailable'}`);
|
|
29
|
+
console.error(` UUID: ${project.projectUuid}`);
|
|
30
|
+
console.error('');
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.error(`This connection is approved for ${approvedProjects.length} projects. Pass --project on the command.`);
|
|
34
|
+
for (const project of approvedProjects)
|
|
35
|
+
console.error(` ${project.name ?? 'Name unavailable'} (${project.projectUuid})`);
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
15
39
|
globalState_1.default.debug(`> Config: ${JSON.stringify(config)}`);
|
|
16
40
|
const projectUuid = config.context?.project;
|
|
17
41
|
const projectName = config.context?.projectName;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"listProjects.d.ts","sourceRoot":"","sources":["../../src/handlers/listProjects.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"listProjects.d.ts","sourceRoot":"","sources":["../../src/handlers/listProjects.ts"],"names":[],"mappings":"AAOA,KAAK,mBAAmB,GAAG;IACvB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,eAAO,MAAM,mBAAmB,YAAmB,mBAAmB,kBAsDrE,CAAC"}
|
|
@@ -3,11 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.listProjectsHandler = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const common_1 = require("@lightdash/common");
|
|
6
|
+
const commandPolicy_1 = require("../agentConnections/commandPolicy");
|
|
6
7
|
const analytics_1 = require("../analytics/analytics");
|
|
7
8
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
8
9
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
9
10
|
const apiClient_1 = require("./dbt/apiClient");
|
|
10
11
|
const listProjectsHandler = async (options) => {
|
|
12
|
+
(0, commandPolicy_1.assertAgentCommandAllowed)('config list-projects');
|
|
11
13
|
const startTime = Date.now();
|
|
12
14
|
let success = true;
|
|
13
15
|
globalState_1.default.setVerbose(options.verbose);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connectionBrowser.d.ts","sourceRoot":"","sources":["../../../src/handlers/login/connectionBrowser.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,QAAS,MAAM,KAAG,OAAO,CAAC,OAAO,CAmBlE,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.openConnectionBrowser = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const credentials_1 = require("../../credentials");
|
|
6
|
+
const openConnectionBrowser = (url) => {
|
|
7
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
8
|
+
const { platform } = process;
|
|
9
|
+
let executable = 'xdg-open';
|
|
10
|
+
if (platform === 'darwin')
|
|
11
|
+
executable = 'open';
|
|
12
|
+
else if (platform === 'win32')
|
|
13
|
+
executable = 'rundll32.exe';
|
|
14
|
+
const args = platform === 'win32' ? ['url.dll,FileProtocolHandler', url] : [url];
|
|
15
|
+
const env = { ...process.env };
|
|
16
|
+
delete env.LIGHTDASH_API_KEY;
|
|
17
|
+
delete env.LIGHTDASH_PROXY_AUTHORIZATION;
|
|
18
|
+
return new Promise((resolve) => {
|
|
19
|
+
(0, child_process_1.execFile)(executable, args, { timeout: 5000, shell: false, env }, (error) => resolve(error === null));
|
|
20
|
+
});
|
|
21
|
+
};
|
|
22
|
+
exports.openConnectionBrowser = openConnectionBrowser;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type ConnectionCallback = {
|
|
2
|
+
code: string;
|
|
3
|
+
grantUuid: string | null;
|
|
4
|
+
};
|
|
5
|
+
export declare const createConnectionLoopback: ({ port, state, issuer, signal, }: {
|
|
6
|
+
port: number;
|
|
7
|
+
state: string;
|
|
8
|
+
issuer: string;
|
|
9
|
+
signal: AbortSignal;
|
|
10
|
+
}) => Promise<{
|
|
11
|
+
redirectUri: string;
|
|
12
|
+
result: Promise<ConnectionCallback>;
|
|
13
|
+
close: () => Promise<void>;
|
|
14
|
+
}>;
|
|
15
|
+
//# sourceMappingURL=loopback.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"loopback.d.ts","sourceRoot":"","sources":["../../../src/handlers/login/loopback.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,kBAAkB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAC5E,eAAO,MAAM,wBAAwB,qCAKlC;IACC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,WAAW,CAAC;CACvB;;;;EA2IA,CAAC"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createConnectionLoopback = void 0;
|
|
4
|
+
const http_1 = require("http");
|
|
5
|
+
const createConnectionLoopback = async ({ port, state, issuer, signal, }) => {
|
|
6
|
+
let settled = false;
|
|
7
|
+
let resolveResult = () => { };
|
|
8
|
+
let rejectResult = () => { };
|
|
9
|
+
const result = new Promise((resolve, reject) => {
|
|
10
|
+
resolveResult = resolve;
|
|
11
|
+
rejectResult = reject;
|
|
12
|
+
});
|
|
13
|
+
void result.catch(() => { });
|
|
14
|
+
const abort = () => {
|
|
15
|
+
if (!settled) {
|
|
16
|
+
settled = true;
|
|
17
|
+
rejectResult(new Error('Agent connection approval timed out or was cancelled. No credential was saved.'));
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const handle = (req, res) => {
|
|
21
|
+
const invalid = () => {
|
|
22
|
+
res.writeHead(400);
|
|
23
|
+
res.end('Invalid approval callback.');
|
|
24
|
+
};
|
|
25
|
+
let url;
|
|
26
|
+
try {
|
|
27
|
+
url = new URL(req.url ?? '/', 'http://localhost');
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
invalid();
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const params = url.searchParams;
|
|
34
|
+
const unique = [
|
|
35
|
+
'state',
|
|
36
|
+
'code',
|
|
37
|
+
'iss',
|
|
38
|
+
'error',
|
|
39
|
+
'grant_uuid',
|
|
40
|
+
'error_description',
|
|
41
|
+
].every((key) => params.getAll(key).length <= 1);
|
|
42
|
+
const code = params.get('code');
|
|
43
|
+
const error = params.get('error');
|
|
44
|
+
if (settled ||
|
|
45
|
+
req.method !== 'GET' ||
|
|
46
|
+
req.url?.split('?', 1)[0] !== '/callback' ||
|
|
47
|
+
url.pathname !== '/callback' ||
|
|
48
|
+
!unique ||
|
|
49
|
+
params.get('state') !== state ||
|
|
50
|
+
params.get('iss') !== issuer ||
|
|
51
|
+
(code === null) === (error === null) ||
|
|
52
|
+
code === '' ||
|
|
53
|
+
error === '') {
|
|
54
|
+
invalid();
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
settled = true;
|
|
58
|
+
res.writeHead(200, {
|
|
59
|
+
'Content-Type': 'text/plain',
|
|
60
|
+
'Cache-Control': 'no-store',
|
|
61
|
+
});
|
|
62
|
+
res.end('You can return to the CLI.');
|
|
63
|
+
if (error !== null)
|
|
64
|
+
rejectResult(new Error('Agent connection approval was denied. No credential was saved.'));
|
|
65
|
+
else
|
|
66
|
+
resolveResult({ code: code, grantUuid: params.get('grant_uuid') });
|
|
67
|
+
};
|
|
68
|
+
let servers = [];
|
|
69
|
+
const closeServers = async () => {
|
|
70
|
+
const closing = servers;
|
|
71
|
+
servers = [];
|
|
72
|
+
await Promise.all(closing.map((server) => {
|
|
73
|
+
server.closeAllConnections();
|
|
74
|
+
return new Promise((resolve) => {
|
|
75
|
+
server.close(() => resolve());
|
|
76
|
+
});
|
|
77
|
+
}));
|
|
78
|
+
};
|
|
79
|
+
const listen = (host, onPort) => new Promise((resolve, reject) => {
|
|
80
|
+
const server = (0, http_1.createServer)(handle);
|
|
81
|
+
servers.push(server);
|
|
82
|
+
server.once('error', reject);
|
|
83
|
+
server.listen(onPort, host, () => {
|
|
84
|
+
const address = server.address();
|
|
85
|
+
if (!address || typeof address === 'string')
|
|
86
|
+
reject(new Error('No listener address'));
|
|
87
|
+
else
|
|
88
|
+
resolve(address.port);
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
// localhost can resolve to either loopback family, so listen on both.
|
|
92
|
+
const listenOnLoopback = async (attempt = 0) => {
|
|
93
|
+
const bound = await listen('127.0.0.1', port);
|
|
94
|
+
try {
|
|
95
|
+
await listen('::1', bound);
|
|
96
|
+
return bound;
|
|
97
|
+
}
|
|
98
|
+
catch (error) {
|
|
99
|
+
const code = error instanceof Error && 'code' in error ? error.code : null;
|
|
100
|
+
if (code === 'EADDRNOTAVAIL' || code === 'EAFNOSUPPORT') {
|
|
101
|
+
servers = servers.slice(0, 1);
|
|
102
|
+
return bound;
|
|
103
|
+
}
|
|
104
|
+
await closeServers();
|
|
105
|
+
if (code !== 'EADDRINUSE' || port !== 0 || attempt >= 4)
|
|
106
|
+
throw error;
|
|
107
|
+
return listenOnLoopback(attempt + 1);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
const close = async () => {
|
|
111
|
+
signal.removeEventListener('abort', abort);
|
|
112
|
+
abort();
|
|
113
|
+
await closeServers();
|
|
114
|
+
};
|
|
115
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
116
|
+
if (signal.aborted) {
|
|
117
|
+
await close();
|
|
118
|
+
throw new Error('Agent connection approval was cancelled.');
|
|
119
|
+
}
|
|
120
|
+
try {
|
|
121
|
+
const bound = await listenOnLoopback();
|
|
122
|
+
if (signal.aborted)
|
|
123
|
+
throw new Error('Could not start the approval callback listener.');
|
|
124
|
+
return {
|
|
125
|
+
redirectUri: `http://localhost:${bound}/callback`,
|
|
126
|
+
result,
|
|
127
|
+
close,
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
catch {
|
|
131
|
+
await close();
|
|
132
|
+
throw new Error('Could not start the approval callback listener.');
|
|
133
|
+
}
|
|
134
|
+
};
|
|
135
|
+
exports.createConnectionLoopback = createConnectionLoopback;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/handlers/login/oauth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../../../src/handlers/login/oauth.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,WAAW,QAAe,MAAM,KAAG,OAAO,CAAC,OAAO,CA0B9D,CAAC"}
|
|
@@ -5,19 +5,32 @@ exports.openBrowser = void 0;
|
|
|
5
5
|
const tslib_1 = require("tslib");
|
|
6
6
|
const child_process_1 = require("child_process");
|
|
7
7
|
const util_1 = require("util");
|
|
8
|
+
const credentials_1 = require("../../credentials");
|
|
8
9
|
const globalState_1 = tslib_1.__importDefault(require("../../globalState"));
|
|
9
10
|
const execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
10
11
|
const openBrowser = async (url) => {
|
|
12
|
+
const childEnv = (0, credentials_1.getAgentConnectionSelection)() !== null
|
|
13
|
+
? await (0, credentials_1.getAgentConnectionChildEnvironment)()
|
|
14
|
+
: null;
|
|
11
15
|
try {
|
|
12
16
|
const { platform } = process;
|
|
13
17
|
if (platform === 'darwin') {
|
|
14
|
-
|
|
18
|
+
if (childEnv !== null)
|
|
19
|
+
await execAsync(`open "${url}"`, { env: childEnv });
|
|
20
|
+
else
|
|
21
|
+
await execAsync(`open "${url}"`);
|
|
15
22
|
}
|
|
16
23
|
else if (platform === 'win32') {
|
|
17
|
-
|
|
24
|
+
if (childEnv !== null)
|
|
25
|
+
await execAsync(`start "${url}"`, { env: childEnv });
|
|
26
|
+
else
|
|
27
|
+
await execAsync(`start "${url}"`);
|
|
18
28
|
}
|
|
19
29
|
else {
|
|
20
|
-
|
|
30
|
+
if (childEnv !== null)
|
|
31
|
+
await execAsync(`xdg-open "${url}"`, { env: childEnv });
|
|
32
|
+
else
|
|
33
|
+
await execAsync(`xdg-open "${url}"`);
|
|
21
34
|
}
|
|
22
35
|
return true;
|
|
23
36
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pat.d.ts","sourceRoot":"","sources":["../../../src/handlers/login/pat.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pat.d.ts","sourceRoot":"","sources":["../../../src/handlers/login/pat.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,2BAA2B,YAC3B,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,OAC1B,MAAM,kBACI,MAAM,KACtB,OAAO,CAAC,MAAM,CA0BhB,CAAC"}
|
|
@@ -4,7 +4,9 @@ exports.generatePersonalAccessToken = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const common_1 = require("@lightdash/common");
|
|
6
6
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
7
|
+
const credentials_1 = require("../../credentials");
|
|
7
8
|
const generatePersonalAccessToken = async (headers, url, hoursToExpire = 720) => {
|
|
9
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
8
10
|
const patUrl = new URL(`/api/v1/user/me/personal-access-tokens`, url).href;
|
|
9
11
|
const now = new Date();
|
|
10
12
|
const createToken = {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/handlers/login.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/handlers/login.ts"],"names":[],"mappings":"AAmBA,KAAK,YAAY,GAAG;IAChB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,qCAAqC;IACrC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yCAAyC;IACzC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,OAAO,EAAE,OAAO,CAAC;CACpB,CAAC;AA8CF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,UACzB,MAAM,GAAG,SAAS,QACpB,MAAM,CAAC,UAAU,KACvB,OAGF,CAAC;AA6HF,eAAO,MAAM,KAAK,aACJ,MAAM,GAAG,SAAS,WACnB,YAAY,kBAqKxB,CAAC"}
|
package/dist/handlers/login.js
CHANGED
|
@@ -8,6 +8,7 @@ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
|
8
8
|
const url_1 = require("url");
|
|
9
9
|
const analytics_1 = require("../analytics/analytics");
|
|
10
10
|
const config_1 = require("../config");
|
|
11
|
+
const credentials_1 = require("../credentials");
|
|
11
12
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
12
13
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
13
14
|
const apiClient_1 = require("./dbt/apiClient");
|
|
@@ -61,12 +62,16 @@ const getLoginMethod = (options) => {
|
|
|
61
62
|
* $LIGHTDASH_API_KEY` is a documented CI pattern — there both tokens are the
|
|
62
63
|
* same and nothing is shadowed.
|
|
63
64
|
*/
|
|
64
|
-
const isApiKeyEnvVarShadowing = (token, env = process.env) =>
|
|
65
|
+
const isApiKeyEnvVarShadowing = (token, env = process.env) => {
|
|
66
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
67
|
+
return !!env.LIGHTDASH_API_KEY && env.LIGHTDASH_API_KEY !== token;
|
|
68
|
+
};
|
|
65
69
|
exports.isApiKeyEnvVarShadowing = isApiKeyEnvVarShadowing;
|
|
66
70
|
const apiKeyEnvVarWarning = (when) => styles.warning(when === 'before-login'
|
|
67
71
|
? `\n⚠️ LIGHTDASH_API_KEY is set and takes precedence over the token saved by \`lightdash login\` (${config_1.configFilePath}).\n Every command will keep using LIGHTDASH_API_KEY until you unset it:\n\n ${styles.bold('unset LIGHTDASH_API_KEY')}\n`
|
|
68
72
|
: ` ⚠️ LIGHTDASH_API_KEY is still set and takes precedence — run ${styles.bold('unset LIGHTDASH_API_KEY')} for this login to take effect.\n`);
|
|
69
73
|
const loginWithToken = async (url, token) => {
|
|
74
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
70
75
|
const userInfoUrl = new url_1.URL(`/api/v1/user`, url).href;
|
|
71
76
|
const response = await (0, node_fetch_1.default)(userInfoUrl, {
|
|
72
77
|
method: 'GET',
|
|
@@ -84,6 +89,7 @@ const loginWithToken = async (url, token) => {
|
|
|
84
89
|
};
|
|
85
90
|
};
|
|
86
91
|
const loginWithEmailPassword = async (url, email, password) => {
|
|
92
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
87
93
|
const loginUrl = new url_1.URL('/api/v1/login', url).href;
|
|
88
94
|
const loginResponse = await (0, node_fetch_1.default)(loginUrl, {
|
|
89
95
|
method: 'POST',
|
|
@@ -141,6 +147,7 @@ const loginWithEmailPassword = async (url, email, password) => {
|
|
|
141
147
|
};
|
|
142
148
|
};
|
|
143
149
|
const login = async (urlInput, options) => {
|
|
150
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
144
151
|
globalState_1.default.setVerbose(options.verbose);
|
|
145
152
|
await (0, apiClient_1.checkLightdashVersion)();
|
|
146
153
|
// If no URL provided, try to use the saved URL from config
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauthLogin.d.ts","sourceRoot":"","sources":["../../src/handlers/oauthLogin.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"oauthLogin.d.ts","sourceRoot":"","sources":["../../src/handlers/oauthLogin.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,cAAc,QAClB,MAAM,cACC,MAAM,KACnB,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,gBAAgB,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAqPvE,CAAC"}
|
|
@@ -7,11 +7,13 @@ const http = tslib_1.__importStar(require("http"));
|
|
|
7
7
|
const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
|
|
8
8
|
const openid_client_1 = require("openid-client");
|
|
9
9
|
const url_1 = require("url");
|
|
10
|
+
const credentials_1 = require("../credentials");
|
|
10
11
|
const globalState_1 = tslib_1.__importDefault(require("../globalState"));
|
|
11
12
|
const styles = tslib_1.__importStar(require("../styles"));
|
|
12
13
|
const oauth_1 = require("./login/oauth");
|
|
13
14
|
const pat_1 = require("./login/pat");
|
|
14
15
|
const loginWithOauth = async (url, oauthPort) => {
|
|
16
|
+
(0, credentials_1.refuseAgentConnection)(true);
|
|
15
17
|
// Create a promise that will be resolved when we get the authorization code
|
|
16
18
|
let resolveAuth;
|
|
17
19
|
let rejectAuth;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { type IncomingHttpHeaders, type Server } from 'http';
|
|
2
|
+
import type { Config } from '../../config';
|
|
3
|
+
export type RecordedRequest = {
|
|
4
|
+
method: string;
|
|
5
|
+
path: string;
|
|
6
|
+
authorization: string | undefined;
|
|
7
|
+
body: string;
|
|
8
|
+
};
|
|
9
|
+
export type Reply = {
|
|
10
|
+
method: string;
|
|
11
|
+
path: string;
|
|
12
|
+
results?: unknown;
|
|
13
|
+
status?: number;
|
|
14
|
+
error?: string;
|
|
15
|
+
body?: string;
|
|
16
|
+
disconnect?: boolean;
|
|
17
|
+
raw?: string;
|
|
18
|
+
};
|
|
19
|
+
export declare class OrdinaryServer {
|
|
20
|
+
private readonly received;
|
|
21
|
+
readonly requests: RecordedRequest[];
|
|
22
|
+
readonly headers: IncomingHttpHeaders[];
|
|
23
|
+
readonly unexpected: RecordedRequest[];
|
|
24
|
+
readonly replies: Reply[];
|
|
25
|
+
readonly server: Server;
|
|
26
|
+
url: string;
|
|
27
|
+
onRequest: (() => void) | null;
|
|
28
|
+
constructor();
|
|
29
|
+
start(): Promise<void>;
|
|
30
|
+
waitForRequest(count: number): Promise<void>;
|
|
31
|
+
close(): Promise<void>;
|
|
32
|
+
expectComplete(): void;
|
|
33
|
+
}
|
|
34
|
+
export declare const personalConfig: (serverUrl: string) => Config;
|
|
35
|
+
export declare const saveConfig: (home: string, config: Config) => Promise<string>;
|
|
36
|
+
export declare const request: (method: string, url: string, body?: string) => RecordedRequest;
|
|
37
|
+
export declare const runOrdinaryCli: (home: string, args: string[]) => Promise<{
|
|
38
|
+
code: number | null;
|
|
39
|
+
stdout: string;
|
|
40
|
+
stderr: string;
|
|
41
|
+
}>;
|
|
42
|
+
//# sourceMappingURL=harness.mocks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness.mocks.d.ts","sourceRoot":"","sources":["../../../src/handlers/ordinary/harness.mocks.ts"],"names":[],"mappings":"AAGA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,KAAK,MAAM,EAAE,MAAM,MAAM,CAAC;AAO3E,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AAE3C,MAAM,MAAM,eAAe,GAAG;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,IAAI,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,MAAM,MAAM,KAAK,GAAG;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,GAAG,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AACF,qBAAa,cAAc;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAsB;IAC/C,QAAQ,CAAC,QAAQ,EAAE,eAAe,EAAE,CAAM;IAC1C,QAAQ,CAAC,OAAO,EAAE,mBAAmB,EAAE,CAAM;IAC7C,QAAQ,CAAC,UAAU,EAAE,eAAe,EAAE,CAAM;IAC5C,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,CAAM;IAC/B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,GAAG,SAAM;IACT,SAAS,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAAQ;IACtC,cAgEC;IACK,KAAK,kBAQV;IACK,cAAc,CAAC,KAAK,EAAE,MAAM,iBAWjC;IACK,KAAK,kBAMV;IACD,cAAc,SAGb;CACJ;AACD,eAAO,MAAM,cAAc,cAAe,MAAM,KAAG,MAcjD,CAAC;AACH,eAAO,MAAM,UAAU,SAAgB,MAAM,UAAU,MAAM,oBAK5D,CAAC;AACF,eAAO,MAAM,OAAO,WACR,MAAM,OACT,MAAM,oBAEZ,eAKD,CAAC;AAEH,eAAO,MAAM,cAAc,SAAgB,MAAM,QAAQ,MAAM,EAAE;UAsB/C,MAAM,GAAG,IAAI;YACX,MAAM;YACN,MAAM;EAuBzB,CAAC"}
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runOrdinaryCli = exports.request = exports.saveConfig = exports.personalConfig = exports.OrdinaryServer = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const events_1 = require("events");
|
|
7
|
+
const fs_1 = require("fs");
|
|
8
|
+
const http_1 = require("http");
|
|
9
|
+
const yaml = tslib_1.__importStar(require("js-yaml"));
|
|
10
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
11
|
+
const timers_1 = require("timers");
|
|
12
|
+
class OrdinaryServer {
|
|
13
|
+
received = new events_1.EventEmitter();
|
|
14
|
+
requests = [];
|
|
15
|
+
headers = [];
|
|
16
|
+
unexpected = [];
|
|
17
|
+
replies = [];
|
|
18
|
+
server;
|
|
19
|
+
url = '';
|
|
20
|
+
onRequest = null;
|
|
21
|
+
constructor() {
|
|
22
|
+
this.server = (0, http_1.createServer)((req, res) => {
|
|
23
|
+
let body = '';
|
|
24
|
+
req.on('data', (chunk) => {
|
|
25
|
+
body += String(chunk);
|
|
26
|
+
});
|
|
27
|
+
req.on('end', () => {
|
|
28
|
+
const request = {
|
|
29
|
+
method: req.method,
|
|
30
|
+
path: req.url,
|
|
31
|
+
authorization: req.headers.authorization,
|
|
32
|
+
body,
|
|
33
|
+
};
|
|
34
|
+
this.requests.push(request);
|
|
35
|
+
this.headers.push(req.headers);
|
|
36
|
+
this.onRequest?.();
|
|
37
|
+
this.received.emit('request');
|
|
38
|
+
const reply = this.replies.shift();
|
|
39
|
+
if (!reply ||
|
|
40
|
+
reply.method !== req.method ||
|
|
41
|
+
reply.path !== req.url ||
|
|
42
|
+
(reply.body !== undefined && reply.body !== body)) {
|
|
43
|
+
this.unexpected.push(request);
|
|
44
|
+
res.writeHead(500, { 'content-type': 'application/json' });
|
|
45
|
+
res.end(JSON.stringify({
|
|
46
|
+
status: 'error',
|
|
47
|
+
error: {
|
|
48
|
+
name: 'Unexpected',
|
|
49
|
+
message: 'Unexpected request',
|
|
50
|
+
},
|
|
51
|
+
}));
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
if (reply.disconnect) {
|
|
55
|
+
req.socket.destroy();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
res.writeHead(reply.status ?? 200, {
|
|
59
|
+
'content-type': reply.raw === undefined
|
|
60
|
+
? 'application/json'
|
|
61
|
+
: 'text/plain',
|
|
62
|
+
});
|
|
63
|
+
res.end(reply.raw ??
|
|
64
|
+
JSON.stringify(reply.error
|
|
65
|
+
? {
|
|
66
|
+
status: 'error',
|
|
67
|
+
error: {
|
|
68
|
+
name: 'Fixture',
|
|
69
|
+
message: reply.error,
|
|
70
|
+
statusCode: reply.status,
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
: { status: 'ok', results: reply.results }));
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
async start() {
|
|
78
|
+
await new Promise((resolve) => {
|
|
79
|
+
this.server.listen(0, '127.0.0.1', resolve);
|
|
80
|
+
});
|
|
81
|
+
const address = this.server.address();
|
|
82
|
+
if (!address || typeof address === 'string')
|
|
83
|
+
throw new Error('Missing server');
|
|
84
|
+
this.url = `http://127.0.0.1:${address.port}`;
|
|
85
|
+
}
|
|
86
|
+
async waitForRequest(count) {
|
|
87
|
+
if (this.requests.length >= count)
|
|
88
|
+
return;
|
|
89
|
+
await new Promise((resolve) => {
|
|
90
|
+
const check = () => {
|
|
91
|
+
if (this.requests.length >= count) {
|
|
92
|
+
this.received.off('request', check);
|
|
93
|
+
resolve();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
this.received.on('request', check);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
async close() {
|
|
100
|
+
this.received.removeAllListeners();
|
|
101
|
+
this.server.closeAllConnections();
|
|
102
|
+
await new Promise((resolve) => {
|
|
103
|
+
this.server.close(() => resolve());
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
expectComplete() {
|
|
107
|
+
expect(this.unexpected).toEqual([]);
|
|
108
|
+
expect(this.replies).toEqual([]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.OrdinaryServer = OrdinaryServer;
|
|
112
|
+
const personalConfig = (serverUrl) => ({
|
|
113
|
+
user: {
|
|
114
|
+
anonymousUuid: 'fixed',
|
|
115
|
+
userUuid: 'person',
|
|
116
|
+
organizationUuid: 'org',
|
|
117
|
+
},
|
|
118
|
+
context: {
|
|
119
|
+
serverUrl,
|
|
120
|
+
apiKey: 'ldpat_pin',
|
|
121
|
+
project: '11111111-1111-4111-8111-111111111111',
|
|
122
|
+
projectName: 'Main',
|
|
123
|
+
source: 'finance',
|
|
124
|
+
},
|
|
125
|
+
answers: { permissionToStoreWarehouseCredentials: false },
|
|
126
|
+
});
|
|
127
|
+
exports.personalConfig = personalConfig;
|
|
128
|
+
const saveConfig = async (home, config) => {
|
|
129
|
+
const file = path_1.default.join(home, '.config/lightdash/config.yaml');
|
|
130
|
+
await fs_1.promises.mkdir(path_1.default.dirname(file), { recursive: true });
|
|
131
|
+
await fs_1.promises.writeFile(file, yaml.dump(config));
|
|
132
|
+
return file;
|
|
133
|
+
};
|
|
134
|
+
exports.saveConfig = saveConfig;
|
|
135
|
+
const request = (method, url, body = '') => ({
|
|
136
|
+
method,
|
|
137
|
+
path: url,
|
|
138
|
+
body,
|
|
139
|
+
authorization: 'ApiKey ldpat_pin',
|
|
140
|
+
});
|
|
141
|
+
exports.request = request;
|
|
142
|
+
const runOrdinaryCli = async (home, args) => {
|
|
143
|
+
const entry = path_1.default.join(home, 'ordinary-entry.cjs');
|
|
144
|
+
const analytics = path_1.default.resolve(__dirname, '../../analytics/analytics.ts');
|
|
145
|
+
const index = path_1.default.resolve(__dirname, '../../index.ts');
|
|
146
|
+
await fs_1.promises.writeFile(entry, `const { LightdashAnalytics } = require(${JSON.stringify(analytics)}); LightdashAnalytics.track = async () => {}; LightdashAnalytics.identify = async () => {}; require(${JSON.stringify(index)});`);
|
|
147
|
+
const env = {
|
|
148
|
+
...process.env,
|
|
149
|
+
HOME: home,
|
|
150
|
+
NO_COLOR: '1',
|
|
151
|
+
FORCE_COLOR: '0',
|
|
152
|
+
CI: 'true',
|
|
153
|
+
};
|
|
154
|
+
const child = (0, child_process_1.spawn)(process.execPath, ['--import', 'tsx', entry, ...args], {
|
|
155
|
+
env,
|
|
156
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
157
|
+
});
|
|
158
|
+
let timer;
|
|
159
|
+
try {
|
|
160
|
+
return await new Promise((resolve, reject) => {
|
|
161
|
+
timer = (0, timers_1.setTimeout)(() => reject(new Error('Ordinary CLI child timed out after 20s')), 20_000);
|
|
162
|
+
let stdout = '';
|
|
163
|
+
let stderr = '';
|
|
164
|
+
child.stdout.on('data', (chunk) => {
|
|
165
|
+
stdout += String(chunk);
|
|
166
|
+
});
|
|
167
|
+
child.stderr.on('data', (chunk) => {
|
|
168
|
+
stderr += String(chunk);
|
|
169
|
+
});
|
|
170
|
+
child.on('error', reject);
|
|
171
|
+
child.on('close', (code) => resolve({ code, stdout, stderr }));
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
finally {
|
|
175
|
+
(0, timers_1.clearTimeout)(timer);
|
|
176
|
+
if (child.exitCode === null && child.signalCode === null)
|
|
177
|
+
child.kill('SIGKILL');
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
exports.runOrdinaryCli = runOrdinaryCli;
|