@malloy-publisher/server 0.2.5 → 0.2.6

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.
@@ -731,6 +731,8 @@ paths:
731
731
  application/json:
732
732
  schema:
733
733
  $ref: "#/components/schemas/Table"
734
+ "400":
735
+ $ref: "#/components/responses/BadRequest"
734
736
  "401":
735
737
  $ref: "#/components/responses/Unauthorized"
736
738
  "404":
@@ -779,6 +781,8 @@ paths:
779
781
  application/json:
780
782
  schema:
781
783
  $ref: "#/components/schemas/SqlSource"
784
+ "400":
785
+ $ref: "#/components/responses/BadRequest"
782
786
  "401":
783
787
  $ref: "#/components/responses/Unauthorized"
784
788
  "404":
@@ -1089,6 +1093,8 @@ paths:
1089
1093
  application/json:
1090
1094
  schema:
1091
1095
  $ref: "#/components/schemas/Table"
1096
+ "400":
1097
+ $ref: "#/components/responses/BadRequest"
1092
1098
  "401":
1093
1099
  $ref: "#/components/responses/Unauthorized"
1094
1100
  "404":
@@ -1143,6 +1149,8 @@ paths:
1143
1149
  application/json:
1144
1150
  schema:
1145
1151
  $ref: "#/components/schemas/SqlSource"
1152
+ "400":
1153
+ $ref: "#/components/responses/BadRequest"
1146
1154
  "401":
1147
1155
  $ref: "#/components/responses/Unauthorized"
1148
1156
  "404":
@@ -5347,12 +5355,34 @@ components:
5347
5355
  type: object
5348
5356
  description: Standard error response format
5349
5357
  properties:
5358
+ code:
5359
+ type: integer
5360
+ description: HTTP status code, repeated in the body for convenience
5350
5361
  message:
5351
5362
  type: string
5352
5363
  description: Human-readable error message describing what went wrong
5353
5364
  details:
5354
5365
  type: string
5355
5366
  description: Additional error details or context
5367
+ reason:
5368
+ type: string
5369
+ description: |
5370
+ Machine-readable discriminator, for callers that must branch on
5371
+ which error they got rather than on prose. Absent unless a caller is
5372
+ expected to act on it, so treat absence as "no special handling".
5373
+
5374
+ TABLE_NOT_FOUND distinguishes a table that is not in the database
5375
+ from the other conditions that also answer 404 on these routes --
5376
+ an environment or connection this server does not host. The former
5377
+ says nothing about whether the caller reached the right server; the
5378
+ latter is a routing problem worth retrying elsewhere.
5379
+
5380
+ Deliberately an open string rather than an enum. Generators render
5381
+ an enum closed, so adding a second value here would break every
5382
+ client generated before it -- on the one field whose purpose is to
5383
+ grow. Callers must treat an unrecognized value as absent.
5384
+
5385
+ Known values: TABLE_NOT_FOUND.
5356
5386
  required:
5357
5387
  - message
5358
5388
 
@@ -2375,6 +2375,8 @@ function internalErrorToHttpError(error) {
2375
2375
  return httpError(404, error.message);
2376
2376
  } else if (error instanceof MalloyError) {
2377
2377
  return httpError(400, error.message);
2378
+ } else if (error instanceof TableNotFoundError) {
2379
+ return httpError(404, error.message, "TABLE_NOT_FOUND");
2378
2380
  } else if (error instanceof ConnectionNotFoundError) {
2379
2381
  return httpError(404, error.message);
2380
2382
  } else if (error instanceof DestinationNotFoundError) {
@@ -2407,16 +2409,17 @@ function internalErrorToHttpError(error) {
2407
2409
  return httpError(500, error.message);
2408
2410
  }
2409
2411
  }
2410
- function httpError(code, message) {
2412
+ function httpError(code, message, reason) {
2411
2413
  return {
2412
2414
  status: code,
2413
2415
  json: {
2414
2416
  code,
2415
- message
2417
+ message,
2418
+ ...reason ? { reason } : {}
2416
2419
  }
2417
2420
  };
2418
2421
  }
2419
- var NotImplementedError, BadRequestError, InvalidArgumentError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
2422
+ var NotImplementedError, BadRequestError, InvalidArgumentError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
2420
2423
  var init_errors = __esm(() => {
2421
2424
  init_constants();
2422
2425
  NotImplementedError = class NotImplementedError extends Error {
@@ -2456,6 +2459,11 @@ var init_errors = __esm(() => {
2456
2459
  super(message);
2457
2460
  }
2458
2461
  };
2462
+ TableNotFoundError = class TableNotFoundError extends Error {
2463
+ constructor(message) {
2464
+ super(message);
2465
+ }
2466
+ };
2459
2467
  ConnectionError = class ConnectionError extends Error {
2460
2468
  constructor(message) {
2461
2469
  super(message);
package/dist/server.mjs CHANGED
@@ -156558,6 +156558,8 @@ function internalErrorToHttpError(error) {
156558
156558
  return httpError(404, error.message);
156559
156559
  } else if (error instanceof MalloyError) {
156560
156560
  return httpError(400, error.message);
156561
+ } else if (error instanceof TableNotFoundError) {
156562
+ return httpError(404, error.message, "TABLE_NOT_FOUND");
156561
156563
  } else if (error instanceof ConnectionNotFoundError) {
156562
156564
  return httpError(404, error.message);
156563
156565
  } else if (error instanceof DestinationNotFoundError) {
@@ -156590,16 +156592,17 @@ function internalErrorToHttpError(error) {
156590
156592
  return httpError(500, error.message);
156591
156593
  }
156592
156594
  }
156593
- function httpError(code, message) {
156595
+ function httpError(code, message, reason) {
156594
156596
  return {
156595
156597
  status: code,
156596
156598
  json: {
156597
156599
  code,
156598
- message
156600
+ message,
156601
+ ...reason ? { reason } : {}
156599
156602
  }
156600
156603
  };
156601
156604
  }
156602
- var NotImplementedError, BadRequestError, InvalidArgumentError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
156605
+ var NotImplementedError, BadRequestError, InvalidArgumentError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, MaterializationEligibilityError, PublisherConfigError, FrozenConfigError, AccessDeniedError, NotQueryableError, MaterializationNotFoundError, MaterializationConflictError, InvalidStateTransitionError, ServiceUnavailableError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
156603
156606
  var init_errors = __esm(() => {
156604
156607
  init_constants();
156605
156608
  NotImplementedError = class NotImplementedError extends Error {
@@ -156639,6 +156642,11 @@ var init_errors = __esm(() => {
156639
156642
  super(message);
156640
156643
  }
156641
156644
  };
156645
+ TableNotFoundError = class TableNotFoundError extends Error {
156646
+ constructor(message) {
156647
+ super(message);
156648
+ }
156649
+ };
156642
156650
  ConnectionError = class ConnectionError extends Error {
156643
156651
  constructor(message) {
156644
156652
  super(message);
@@ -234644,14 +234652,14 @@ var init_connection = __esm(() => {
234644
234652
  });
234645
234653
  const result2 = await super.fetchTableSchema(tableKey, azureUrl);
234646
234654
  if (!result2) {
234647
- throw new Error(`Azure file not found: ${azureUrl}`);
234655
+ throw new TableNotFoundError(`Azure file not found: ${azureUrl}`);
234648
234656
  }
234649
234657
  return result2;
234650
234658
  }
234651
234659
  }
234652
234660
  const result = await super.fetchTableSchema(tableKey, tablePath);
234653
234661
  if (!result) {
234654
- throw new Error(`Table ${tablePath} not found`);
234662
+ throw new TableNotFoundError(`Table ${tablePath} not found`);
234655
234663
  }
234656
234664
  return result;
234657
234665
  }
@@ -234703,13 +234711,13 @@ var init_connection = __esm(() => {
234703
234711
  });
234704
234712
  const result2 = await super.fetchTableSchema(tableKey, prefixedPath);
234705
234713
  if (!result2) {
234706
- throw new Error(`Table ${prefixedPath} not found in connection ${this.connectionName}`);
234714
+ throw new TableNotFoundError(`Table ${prefixedPath} not found in connection ${this.connectionName}`);
234707
234715
  }
234708
234716
  return result2;
234709
234717
  }
234710
234718
  const result = await super.fetchTableSchema(tableKey, tablePath);
234711
234719
  if (!result) {
234712
- throw new Error(`Table ${tablePath} not found in connection ${this.connectionName}`);
234720
+ throw new TableNotFoundError(`Table ${tablePath} not found in connection ${this.connectionName}`);
234713
234721
  }
234714
234722
  return result;
234715
234723
  }
@@ -277549,6 +277557,26 @@ function validateAdminAuthoredConnection(connectionName, connectionConfig) {
277549
277557
  }
277550
277558
  }
277551
277559
  }
277560
+ var BIGQUERY_NOT_FOUND = /^Not found: (Table|Dataset)\b/;
277561
+ var BIGQUERY_IMPROPER_PATH = /^Improper table path\b/;
277562
+ var DUCKDB_TABLE_NOT_FOUND = /^Catalog Error: Table with name .+ does not exist/;
277563
+ var DUCKDB_CATALOG_NOT_FOUND = /^Binder Error: Catalog .+ does not exist/;
277564
+ function driverErrorToPublisherError(message) {
277565
+ if (BIGQUERY_NOT_FOUND.test(message) || DUCKDB_TABLE_NOT_FOUND.test(message) || DUCKDB_CATALOG_NOT_FOUND.test(message)) {
277566
+ return new TableNotFoundError(message);
277567
+ }
277568
+ if (BIGQUERY_IMPROPER_PATH.test(message)) {
277569
+ return new InvalidArgumentError(message);
277570
+ }
277571
+ return new ConnectionError(message);
277572
+ }
277573
+ function classifyDriverFailure(error) {
277574
+ if (error instanceof TableNotFoundError || error instanceof InvalidArgumentError) {
277575
+ return error;
277576
+ }
277577
+ const message = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error);
277578
+ return driverErrorToPublisherError(message);
277579
+ }
277552
277580
 
277553
277581
  class ConnectionController {
277554
277582
  environmentStore;
@@ -277615,10 +277643,10 @@ class ConnectionController {
277615
277643
  try {
277616
277644
  const source = await malloyConnection.fetchTableSchema(tableKey, tablePath);
277617
277645
  if (!source) {
277618
- throw new ConnectionError(`Table ${tablePath} not found`);
277646
+ throw new TableNotFoundError(`Table ${tablePath} not found`);
277619
277647
  }
277620
277648
  if (typeof source === "string") {
277621
- throw new ConnectionError(source);
277649
+ throw driverErrorToPublisherError(source);
277622
277650
  }
277623
277651
  return {
277624
277652
  source: JSON.stringify(source),
@@ -277629,13 +277657,21 @@ class ConnectionController {
277629
277657
  }))
277630
277658
  };
277631
277659
  } catch (error) {
277632
- const errorMessage = error instanceof Error ? error.message : typeof error === "string" ? error : JSON.stringify(error);
277660
+ const classified = classifyDriverFailure(error);
277661
+ if (!(classified instanceof ConnectionError)) {
277662
+ logger.warn("table not resolvable", {
277663
+ tableKey,
277664
+ tablePath,
277665
+ reason: classified.constructor.name
277666
+ });
277667
+ throw classified;
277668
+ }
277633
277669
  logger.error("fetchTableSchema error", {
277634
277670
  error,
277635
277671
  tableKey,
277636
277672
  tablePath
277637
277673
  });
277638
- throw new ConnectionError(errorMessage);
277674
+ throw classified;
277639
277675
  }
277640
277676
  }
277641
277677
  async getConnection(environmentName, connectionName) {
@@ -277669,13 +277705,13 @@ class ConnectionController {
277669
277705
  selectStr: sqlStatement
277670
277706
  });
277671
277707
  if (typeof schema === "string") {
277672
- throw new ConnectionError(schema);
277708
+ throw driverErrorToPublisherError(schema);
277673
277709
  }
277674
277710
  return {
277675
277711
  source: JSON.stringify(schema)
277676
277712
  };
277677
277713
  } catch (error) {
277678
- throw new ConnectionError(error.message);
277714
+ throw classifyDriverFailure(error);
277679
277715
  }
277680
277716
  }
277681
277717
  async getTable(environmentName, connectionName, schemaName, tablePath, packageName) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/server",
3
3
  "description": "Malloy Publisher Server",
4
- "version": "0.2.5",
4
+ "version": "0.2.6",
5
5
  "main": "dist/server.mjs",
6
6
  "bin": {
7
7
  "malloy-publisher": "dist/server.mjs"