@lightdash/cli 1.16.0 → 1.17.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"connectSnowflake.d.ts","sourceRoot":"","sources":["../../src/handlers/connectSnowflake.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,0BAA0B,EAIlC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEH,wBAAwB,EAG3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAwB,MAAM,YAAY,CAAC;AAIlD,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,yBAAyB,GAAG,IAAI,CACjC,wBAAwB,EACtB,2BAA2B,GAC3B,+BAA+B,GAC/B,qBAAqB,GACrB,uBAAuB,GACvB,0BAA0B,GAC1B,+BAA+B,GAC/B,kBAAkB,GAClB,oBAAoB,CACzB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAChC,sBAAsB,EAAE,CACpB,WAAW,EAAE,0BAA0B,KACtC,yBAAyB,CAAC;IAC/B,eAAe,EAAE,MAAM,gBAAgB,CAAC;IACxC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AA0XF,eAAO,MAAM,uBAAuB,GAChC,SAAS,uBAAuB,EAChC,eAAc,4BAAkD,KACjE,OAAO,CAAC,IAAI,CAwEd,CAAC"}
1
+ {"version":3,"file":"connectSnowflake.d.ts","sourceRoot":"","sources":["../../src/handlers/connectSnowflake.ts"],"names":[],"mappings":"AAAA,OAAO,EAKH,KAAK,0BAA0B,EAIlC,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEH,wBAAwB,EAG3B,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAwB,MAAM,YAAY,CAAC;AAIlD,MAAM,MAAM,uBAAuB,GAAG;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,yBAAyB,GAAG,IAAI,CACjC,wBAAwB,EACtB,2BAA2B,GAC3B,+BAA+B,GAC/B,qBAAqB,GACrB,uBAAuB,GACvB,0BAA0B,GAC1B,+BAA+B,GAC/B,kBAAkB,GAClB,oBAAoB,CACzB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,KAAK,4BAA4B,GAAG;IAChC,sBAAsB,EAAE,CACpB,WAAW,EAAE,0BAA0B,KACtC,yBAAyB,CAAC;IAC/B,eAAe,EAAE,MAAM,gBAAgB,CAAC;IACxC,KAAK,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,GAAG,EAAE,MAAM,IAAI,CAAC;IAChB,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC,CAAC;AA6XF,eAAO,MAAM,uBAAuB,GAChC,SAAS,uBAAuB,EAChC,eAAc,4BAAkD,KACjE,OAAO,CAAC,IAAI,CAwEd,CAAC"}
@@ -8,7 +8,7 @@ const node_fetch_1 = tslib_1.__importDefault(require("node-fetch"));
8
8
  const node_crypto_1 = require("node:crypto");
9
9
  const analytics_1 = require("../analytics/analytics");
10
10
  const PAT_EXPIRY_DAYS = 365;
11
- const PAT_NETWORK_POLICY_BYPASS_MINUTES = 1440;
11
+ const PAT_NETWORK_POLICY_BYPASS_MINUTES = 60;
12
12
  const KEY_VERIFICATION_ATTEMPTS = 3;
13
13
  const KEY_VERIFICATION_RETRY_DELAY_MS = 5_000;
14
14
  const generateSnowflakeKeyPair = () => {
@@ -235,6 +235,7 @@ const createDurableCredential = async (authorizationCodeCredentials, warehouseCl
235
235
  const { tokenSecret } = await warehouseClient.createProgrammaticAccessToken(`LIGHTDASH_ONBOARDING_${Date.now()}`, PAT_EXPIRY_DAYS, PAT_NETWORK_POLICY_BYPASS_MINUTES);
236
236
  const expiresAt = new Date(dependencies.now().getTime() +
237
237
  PAT_EXPIRY_DAYS * 24 * 60 * 60 * 1000);
238
+ dependencies.write(`The token bypasses your Snowflake network policy for the next ${PAT_NETWORK_POLICY_BYPASS_MINUTES} minutes so this connection can be verified. Allowlist Lightdash's IP addresses in your network policy to keep it working afterwards.`);
238
239
  return {
239
240
  credentials: {
240
241
  type: common_1.WarehouseTypes.SNOWFLAKE,
@@ -291,7 +291,7 @@ describe('connectSnowflakeHandler', () => {
291
291
  });
292
292
  await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
293
293
  expect(setUserPublicKey).not.toHaveBeenCalled();
294
- expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 1440);
294
+ expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 60);
295
295
  const request = {
296
296
  code: options.code,
297
297
  credentials: {
@@ -321,8 +321,9 @@ describe('connectSnowflakeHandler', () => {
321
321
  it('falls back to a PAT when key registration lacks privileges', async () => {
322
322
  vi.mocked(setUserPublicKey).mockRejectedValue(new Error('Insufficient privileges to operate on user'));
323
323
  await expect((0, connectSnowflake_1.connectSnowflakeHandler)(options, getDependencies())).resolves.toBeUndefined();
324
- expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 1440);
324
+ expect(createProgrammaticAccessToken).toHaveBeenCalledWith(expect.stringMatching(/^LIGHTDASH_ONBOARDING_\d+$/), 365, 60);
325
325
  expect(write).toHaveBeenCalledWith('Secured with a programmatic access token (expires 2027-07-14)');
326
+ expect(write).toHaveBeenCalledWith(expect.stringContaining('bypasses your Snowflake network policy for the next 60 minutes'));
326
327
  });
327
328
  it('prints administrator remediation when both durable paths fail', async () => {
328
329
  vi.mocked(setUserPublicKey).mockRejectedValue(new Error('Insufficient privileges'));
@@ -53,7 +53,7 @@
53
53
  "@vitejs/plugin-react": "6.0.1",
54
54
  "autoprefixer": "10.4.20",
55
55
  "oxc-parser": "0.128.0",
56
- "postcss": "8.5.10",
56
+ "postcss": "8.5.18",
57
57
  "tailwindcss": "3.4.17",
58
58
  "typescript": "6.0.3",
59
59
  "vite": "8.0.5"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lightdash/cli",
3
- "version": "1.16.0",
3
+ "version": "1.17.1",
4
4
  "description": "Lightdash CLI tool",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -41,8 +41,8 @@
41
41
  "unique-names-generator": "4.7.1",
42
42
  "uuid": "11.1.1",
43
43
  "yaml": "2.8.3",
44
- "@lightdash/common": "1.16.0",
45
- "@lightdash/warehouses": "1.16.0"
44
+ "@lightdash/common": "1.17.1",
45
+ "@lightdash/warehouses": "1.17.1"
46
46
  },
47
47
  "devDependencies": {
48
48
  "@types/inquirer": "8.2.4",
@@ -1,5 +0,0 @@
1
- export declare const getOrganizationContentFileNames: ({ values, fallbackPrefix, }: {
2
- values: string[];
3
- fallbackPrefix: string;
4
- }) => string[];
5
- //# sourceMappingURL=fileNames.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fileNames.d.ts","sourceRoot":"","sources":["../../../src/handlers/organizationContent/fileNames.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,+BAA+B,GAAI,6BAG7C;IACC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;CAC1B,KAAG,MAAM,EAOJ,CAAC"}
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getOrganizationContentFileNames = void 0;
4
- const fileNames_1 = require("../contentAsCode/fileNames");
5
- const getOrganizationContentFileNames = ({ values, fallbackPrefix, }) => (0, fileNames_1.allocateContentFileNames)({
6
- items: values.map((value) => ({
7
- identity: value,
8
- displayName: value,
9
- })),
10
- fallbackPrefix,
11
- });
12
- exports.getOrganizationContentFileNames = getOrganizationContentFileNames;
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=fileNames.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"fileNames.test.d.ts","sourceRoot":"","sources":["../../../src/handlers/organizationContent/fileNames.test.ts"],"names":[],"mappings":""}
@@ -1,36 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const crypto_1 = require("crypto");
4
- const fileNames_1 = require("./fileNames");
5
- describe('organization content filenames', () => {
6
- it('uses generateSlug with normalized accents', () => {
7
- expect((0, fileNames_1.getOrganizationContentFileNames)({
8
- values: ['Málaga Finance'],
9
- fallbackPrefix: 'group',
10
- })).toStrictEqual(['malaga-finance.yml']);
11
- });
12
- it('uses a deterministic hash when no slug can be generated', () => {
13
- const value = '🎉';
14
- const hash = (0, crypto_1.createHash)('sha256')
15
- .update(value)
16
- .digest('hex')
17
- .slice(0, 8);
18
- expect((0, fileNames_1.getOrganizationContentFileNames)({
19
- values: [value],
20
- fallbackPrefix: 'group',
21
- })).toStrictEqual([`group-${hash}.yml`]);
22
- });
23
- it('adds stable hashes when different values generate the same slug', () => {
24
- const values = ['Finance?', 'Finance!'];
25
- expect((0, fileNames_1.getOrganizationContentFileNames)({
26
- values,
27
- fallbackPrefix: 'group',
28
- })).toStrictEqual(values.map((value) => {
29
- const hash = (0, crypto_1.createHash)('sha256')
30
- .update(value)
31
- .digest('hex')
32
- .slice(0, 8);
33
- return `finance-${hash}.yml`;
34
- }));
35
- });
36
- });