@malloy-publisher/server 0.0.120 → 0.0.121

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.
@@ -14,29 +14,48 @@ function createBigQueryClient(connection: ApiConnection): BigQuery {
14
14
  throw new Error("BigQuery connection is required");
15
15
  }
16
16
 
17
- if (!connection.bigqueryConnection.defaultProjectId) {
18
- throw new Error("BigQuery defaultProjectId is required");
19
- }
20
-
21
17
  const config: {
22
18
  projectId: string;
19
+ credentials?: object;
23
20
  keyFilename?: string;
24
21
  } = {
25
- projectId: connection.bigqueryConnection.defaultProjectId,
22
+ projectId: connection.bigqueryConnection.defaultProjectId || "",
26
23
  };
27
24
 
28
25
  // Add service account key if provided
29
26
  if (connection.bigqueryConnection.serviceAccountKeyJson) {
30
27
  try {
31
- config.keyFilename = JSON.parse(
28
+ const credentials = JSON.parse(
32
29
  connection.bigqueryConnection.serviceAccountKeyJson,
33
30
  );
31
+ config.credentials = credentials;
32
+
33
+ // Use project_id from credentials if defaultProjectId is not set
34
+ if (!config.projectId && credentials.project_id) {
35
+ config.projectId = credentials.project_id;
36
+ }
37
+
38
+ if (!config.projectId) {
39
+ throw new Error(
40
+ "BigQuery project ID is required. Either set the defaultProjectId in the connection configuration or the project_id in the service account key JSON.",
41
+ );
42
+ }
34
43
  } catch (error) {
35
44
  logger.warn(
36
45
  "Failed to parse service account key JSON, using default credentials",
37
46
  { error },
38
47
  );
39
48
  }
49
+ } else if (
50
+ Object.keys(connection.bigqueryConnection).length === 0 &&
51
+ process.env.GOOGLE_APPLICATION_CREDENTIALS
52
+ ) {
53
+ // Note: The BigQuery client will infer the project ID from the ADC file.
54
+ config.keyFilename = process.env.GOOGLE_APPLICATION_CREDENTIALS || "";
55
+ } else {
56
+ throw new Error(
57
+ "BigQuery connection is required, either set the bigqueryConnection in the connection configuration or set the GOOGLE_APPLICATION_CREDENTIALS environment variable.",
58
+ );
40
59
  }
41
60
 
42
61
  return new BigQuery(config);
@@ -58,11 +77,6 @@ export async function getSchemasForConnection(
58
77
  throw new Error("BigQuery connection is required");
59
78
  }
60
79
  try {
61
- const projectId = connection.bigqueryConnection?.defaultProjectId;
62
- if (!projectId) {
63
- throw new Error("BigQuery project ID is required");
64
- }
65
-
66
80
  const bigquery = createBigQueryClient(connection);
67
81
  const [datasets] = await bigquery.getDatasets();
68
82
 
@@ -87,18 +101,20 @@ export async function getSchemasForConnection(
87
101
  try {
88
102
  // Use the connection's runSQL method to query schemas
89
103
  const result = await malloyConnection.runSQL(
90
- "SELECT schema_name FROM information_schema.schemata",
104
+ "SELECT schema_name as row FROM information_schema.schemata ORDER BY schema_name",
91
105
  );
92
106
 
93
107
  const rows = standardizeRunSQLResult(result);
94
108
  return rows.map((row: unknown) => {
95
- const typedRow = row as Record<string, unknown>;
109
+ const schemaName = row as string;
96
110
  return {
97
- name: typedRow.schema_name as string,
98
- isHidden: ["information_schema", "pg_catalog"].includes(
99
- typedRow.schema_name as string,
100
- ),
101
- isDefault: typedRow.schema_name === "public",
111
+ name: schemaName,
112
+ isHidden: [
113
+ "information_schema",
114
+ "pg_catalog",
115
+ "pg_toast",
116
+ ].includes(schemaName),
117
+ isDefault: schemaName === "public",
102
118
  };
103
119
  });
104
120
  } catch (error) {
@@ -172,9 +188,12 @@ export async function getSchemasForConnection(
172
188
  return rows.map((row: unknown) => {
173
189
  const typedRow = row as Record<string, unknown>;
174
190
  return {
175
- name: typedRow.name as string,
176
- isHidden: false,
177
- isDefault: typedRow.name === connection.trinoConnection?.schema,
191
+ name: typedRow.Schema as string,
192
+ isHidden: ["information_schema", "performance_schema"].includes(
193
+ typedRow.Schema as string,
194
+ ),
195
+ isDefault:
196
+ typedRow.Schema === connection.trinoConnection?.schema,
178
197
  };
179
198
  });
180
199
  } catch (error) {
@@ -339,11 +358,6 @@ export async function listTablesForSchema(
339
358
  ): Promise<string[]> {
340
359
  if (connection.type === "bigquery") {
341
360
  try {
342
- const projectId = connection.bigqueryConnection?.defaultProjectId;
343
- if (!projectId) {
344
- throw new Error("BigQuery project ID is required");
345
- }
346
-
347
361
  // Use BigQuery client directly for efficient table listing
348
362
  // This is much faster than querying all regions
349
363
  const bigquery = createBigQueryClient(connection);
@@ -391,13 +405,10 @@ export async function listTablesForSchema(
391
405
  }
392
406
  try {
393
407
  const result = await malloyConnection.runSQL(
394
- `SELECT table_name FROM information_schema.tables WHERE table_schema = '${schemaName}'`,
408
+ `SELECT table_name as row FROM information_schema.tables WHERE table_schema = '${schemaName}' ORDER BY table_name`,
395
409
  );
396
410
  const rows = standardizeRunSQLResult(result);
397
- return rows.map((row: unknown) => {
398
- const typedRow = row as Record<string, unknown>;
399
- return typedRow.table_name as string;
400
- });
411
+ return rows as string[];
401
412
  } catch (error) {
402
413
  logger.error(
403
414
  `Error getting tables for Postgres schema ${schemaName} in connection ${connection.name}`,
@@ -440,7 +451,7 @@ export async function listTablesForSchema(
440
451
  const rows = standardizeRunSQLResult(result);
441
452
  return rows.map((row: unknown) => {
442
453
  const typedRow = row as Record<string, unknown>;
443
- return typedRow.name as string;
454
+ return typedRow.Table as string;
444
455
  });
445
456
  } catch (error) {
446
457
  logger.error(