@malloy-publisher/server 0.0.161 → 0.0.165

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.
@@ -300,31 +300,68 @@ export class Model {
300
300
  }> {
301
301
  const startTime = performance.now();
302
302
  if (this.compilationError) {
303
- throw this.compilationError;
303
+ // Re-throw MalloyError and ModelCompilationError as-is (they map to 400/424)
304
+ if (
305
+ this.compilationError instanceof MalloyError ||
306
+ this.compilationError instanceof ModelCompilationError
307
+ ) {
308
+ throw this.compilationError;
309
+ }
310
+ // For other compilation errors, wrap as BadRequestError (400)
311
+ throw new BadRequestError(
312
+ `Model compilation failed: ${this.compilationError.message}`,
313
+ );
304
314
  }
305
315
  let runnable: QueryMaterializer;
306
316
  if (!this.modelMaterializer || !this.modelDef || !this.modelInfo)
307
317
  throw new BadRequestError("Model has no queryable entities.");
308
- if (!sourceName && !queryName && query) {
309
- runnable = this.modelMaterializer.loadQuery("\n" + query);
310
- } else if (queryName && !query) {
311
- runnable = this.modelMaterializer.loadQuery(
312
- `\nrun: ${sourceName ? sourceName + "->" : ""}${queryName}`,
313
- );
314
- } else {
315
- const endTime = performance.now();
316
- const executionTime = endTime - startTime;
317
- this.queryExecutionHistogram.record(executionTime, {
318
- "malloy.model.path": this.modelPath,
319
- "malloy.model.query.name": queryName,
320
- "malloy.model.query.source": sourceName,
321
- "malloy.model.query.query": query,
322
- "malloy.model.query.status": "error",
318
+
319
+ // Wrap loadQuery calls in try-catch to handle query parsing errors
320
+ try {
321
+ if (!sourceName && !queryName && query) {
322
+ runnable = this.modelMaterializer.loadQuery("\n" + query);
323
+ } else if (queryName && !query) {
324
+ runnable = this.modelMaterializer.loadQuery(
325
+ `\nrun: ${sourceName ? sourceName + "->" : ""}${queryName}`,
326
+ );
327
+ } else {
328
+ const endTime = performance.now();
329
+ const executionTime = endTime - startTime;
330
+ this.queryExecutionHistogram.record(executionTime, {
331
+ "malloy.model.path": this.modelPath,
332
+ "malloy.model.query.name": queryName,
333
+ "malloy.model.query.source": sourceName,
334
+ "malloy.model.query.query": query,
335
+ "malloy.model.query.status": "error",
336
+ });
337
+ throw new BadRequestError(
338
+ "Invalid query request. (Query AND !sourceName) OR (queryName AND sourceName) must be defined.",
339
+ );
340
+ }
341
+ } catch (error) {
342
+ // Re-throw BadRequestError as-is
343
+ if (error instanceof BadRequestError) {
344
+ throw error;
345
+ }
346
+ // Re-throw MalloyError as-is (maps to 400)
347
+ if (error instanceof MalloyError) {
348
+ throw error;
349
+ }
350
+ // For other query parsing errors, wrap as BadRequestError
351
+ const errorMessage =
352
+ error instanceof Error ? error.message : String(error);
353
+ logger.error("Query parsing error", {
354
+ error,
355
+ errorMessage,
356
+ projectName: this.packageName,
357
+ modelPath: this.modelPath,
358
+ query,
359
+ queryName,
360
+ sourceName,
323
361
  });
324
- throw new BadRequestError(
325
- "Invalid query request. (Query AND !sourceName) OR (queryName AND sourceName) must be defined.",
326
- );
362
+ throw new BadRequestError(`Invalid query: ${errorMessage}`);
327
363
  }
364
+
328
365
  const rowLimit =
329
366
  (await runnable.getPreparedResult()).resultExplore.limit || ROW_LIMIT;
330
367
  const endTime = performance.now();
@@ -24,6 +24,7 @@ import {
24
24
  PackageNotFoundError,
25
25
  ProjectNotFoundError,
26
26
  } from "../errors";
27
+ import { getOperationalState, markNotReady, markReady } from "../health";
27
28
  import { formatDuration, logger } from "../logger";
28
29
  import { Connection } from "../storage/DatabaseInterface";
29
30
  import { StorageConfig, StorageManager } from "../storage/StorageManager";
@@ -188,11 +189,13 @@ export class ProjectStore {
188
189
  }
189
190
 
190
191
  this.isInitialized = true;
192
+ markReady();
191
193
  const initializationDuration = performance.now() - initialTime;
192
194
  logger.info(
193
195
  `Project store successfully initialized in ${formatDuration(initializationDuration)}`,
194
196
  );
195
197
  } catch (error) {
198
+ markNotReady();
196
199
  logger.error("Error initializing project store", { error });
197
200
  process.exit(1);
198
201
  }
@@ -572,6 +575,8 @@ export class ProjectStore {
572
575
  projects: [] as Array<components["schemas"]["Project"]>,
573
576
  initialized: this.isInitialized,
574
577
  frozenConfig: isPublisherConfigFrozen(this.serverRootPath),
578
+ operationalState:
579
+ getOperationalState() as components["schemas"]["ServerStatus"]["operationalState"],
575
580
  };
576
581
 
577
582
  const projects = await this.listProjects(true);
@@ -1 +0,0 @@
1
- import{t as o,j as a,Q as e}from"./index-BoduKqUa.js";function n(){const t=o();return a.jsx(e,{onClickProject:t})}export{n as default};
@@ -1 +0,0 @@
1
- import{p as n,t,j as e,A as c,J as o}from"./index-BoduKqUa.js";function l(){const{projectName:s,packageName:a}=n(),r=t();if(s)if(a){const i=c({projectName:s,packageName:a});return e.jsx(o,{onClickPackageFile:r,resourceUri:i})}else return e.jsx("div",{children:e.jsx("h2",{children:"Missing package name"})});else return e.jsx("div",{children:e.jsx("h2",{children:"Missing project name"})})}export{l as default};
@@ -1 +0,0 @@
1
- import{t as a,p as n,j as e,A as c,E as o}from"./index-BoduKqUa.js";function j(){const t=a(),{projectName:s}=n();if(s){const r=c({projectName:s});return e.jsx(o,{onSelectPackage:t,resourceUri:r})}else return e.jsx("div",{children:e.jsx("h2",{children:"Missing project name"})})}export{j as default};
@@ -1 +0,0 @@
1
- import{F as o,j as r,z as s,S as n,q as t,T as a}from"./index-BoduKqUa.js";function x(){const e=o();return console.error(e),r.jsx(s,{maxWidth:"lg",component:"main",sx:{display:"flex",flexDirection:"column",my:2,gap:0},children:r.jsxs(n,{sx:{m:"auto",flexDirection:"column"},children:[r.jsx(t,{sx:{height:"300px"}}),r.jsx("img",{src:"/error.png"}),r.jsx(a,{variant:"subtitle1",children:"An unexpected error occurred"})]})})}export{x as default};