@malloy-publisher/server 0.0.196-dev → 0.0.198-dev

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.
Files changed (100) hide show
  1. package/dist/app/api-doc.yaml +213 -214
  2. package/dist/app/assets/EnvironmentPage-1j6QDWAy.js +1 -0
  3. package/dist/app/assets/HomePage-DMop21VG.js +1 -0
  4. package/dist/app/assets/MainPage-BbE8ETz1.js +2 -0
  5. package/dist/app/assets/ModelPage-D2jvfe3t.js +1 -0
  6. package/dist/app/assets/PackagePage-BbnhGoD3.js +1 -0
  7. package/dist/app/assets/{RouteError-DefbDO7F.js → RouteError-D3LGEZ3i.js} +1 -1
  8. package/dist/app/assets/WorkbookPage-DttVIj4u.js +1 -0
  9. package/dist/app/assets/{core-BrfQApxh.es-DnvCX4oH.js → core-w79IMXAG.es-Bd0UlzOL.js} +1 -1
  10. package/dist/app/assets/{index-Bu0ub036.js → index-5K9YjIxF.js} +117 -117
  11. package/dist/app/assets/{index-CkzK3JIl.js → index-C513UodQ.js} +1 -1
  12. package/dist/app/assets/{index-CoA6HIGS.js → index-DIgzgp69.js} +1 -1
  13. package/dist/app/assets/{index.umd-B6Ms2PpL.js → index.umd-BMeMPq_9.js} +1 -1
  14. package/dist/app/index.html +1 -1
  15. package/dist/server.mjs +1947 -1317
  16. package/package.json +1 -1
  17. package/publisher.config.json +2 -2
  18. package/src/config.spec.ts +74 -66
  19. package/src/config.ts +50 -47
  20. package/src/controller/compile.controller.ts +10 -7
  21. package/src/controller/connection.controller.ts +79 -58
  22. package/src/controller/database.controller.ts +10 -7
  23. package/src/controller/manifest.controller.ts +23 -14
  24. package/src/controller/materialization.controller.ts +14 -14
  25. package/src/controller/model.controller.ts +35 -20
  26. package/src/controller/package.controller.ts +83 -49
  27. package/src/controller/query.controller.ts +11 -8
  28. package/src/controller/watch-mode.controller.ts +35 -29
  29. package/src/errors.ts +2 -2
  30. package/src/mcp/error_messages.ts +2 -2
  31. package/src/mcp/handler_utils.ts +23 -20
  32. package/src/mcp/mcp_constants.ts +1 -1
  33. package/src/mcp/prompts/handlers.ts +3 -3
  34. package/src/mcp/prompts/prompt_service.ts +5 -5
  35. package/src/mcp/prompts/utils.ts +12 -12
  36. package/src/mcp/resource_metadata.ts +3 -3
  37. package/src/mcp/resources/environment_resource.ts +187 -0
  38. package/src/mcp/resources/model_resource.ts +19 -17
  39. package/src/mcp/resources/notebook_resource.ts +13 -13
  40. package/src/mcp/resources/package_resource.ts +30 -27
  41. package/src/mcp/resources/query_resource.ts +15 -10
  42. package/src/mcp/resources/source_resource.ts +10 -10
  43. package/src/mcp/resources/view_resource.ts +11 -11
  44. package/src/mcp/server.ts +16 -14
  45. package/src/mcp/tools/discovery_tools.ts +67 -49
  46. package/src/mcp/tools/execute_query_tool.ts +14 -14
  47. package/src/server-old.ts +1139 -0
  48. package/src/server.ts +191 -159
  49. package/src/service/connection.spec.ts +158 -133
  50. package/src/service/connection.ts +42 -39
  51. package/src/service/connection_config.spec.ts +13 -11
  52. package/src/service/connection_config.ts +28 -19
  53. package/src/service/connection_service.spec.ts +63 -43
  54. package/src/service/connection_service.ts +106 -89
  55. package/src/service/{project.ts → environment.ts} +92 -77
  56. package/src/service/{project_compile.spec.ts → environment_compile.spec.ts} +1 -1
  57. package/src/service/{project_store.spec.ts → environment_store.spec.ts} +99 -85
  58. package/src/service/{project_store.ts → environment_store.ts} +368 -326
  59. package/src/service/manifest_service.spec.ts +15 -15
  60. package/src/service/manifest_service.ts +26 -21
  61. package/src/service/materialization_service.spec.ts +93 -59
  62. package/src/service/materialization_service.ts +71 -62
  63. package/src/service/materialized_table_gc.spec.ts +15 -15
  64. package/src/service/materialized_table_gc.ts +3 -3
  65. package/src/service/model.ts +2 -2
  66. package/src/service/package.spec.ts +2 -2
  67. package/src/service/package.ts +23 -21
  68. package/src/service/resolve_environment.ts +15 -0
  69. package/src/storage/DatabaseInterface.ts +34 -25
  70. package/src/storage/StorageManager.mock.ts +3 -3
  71. package/src/storage/StorageManager.ts +24 -23
  72. package/src/storage/duckdb/ConnectionRepository.ts +13 -11
  73. package/src/storage/duckdb/DuckDBConnection.ts +1 -1
  74. package/src/storage/duckdb/DuckDBManifestStore.ts +6 -6
  75. package/src/storage/duckdb/DuckDBRepository.ts +47 -47
  76. package/src/storage/duckdb/{ProjectRepository.ts → EnvironmentRepository.ts} +35 -35
  77. package/src/storage/duckdb/ManifestRepository.ts +21 -20
  78. package/src/storage/duckdb/MaterializationRepository.ts +31 -28
  79. package/src/storage/duckdb/PackageRepository.ts +11 -11
  80. package/src/storage/duckdb/manifest_store.spec.ts +2 -2
  81. package/src/storage/duckdb/schema.ts +20 -20
  82. package/src/storage/ducklake/DuckLakeManifestStore.ts +14 -14
  83. package/tests/fixtures/publisher.config.json +1 -1
  84. package/tests/harness/e2e.ts +1 -1
  85. package/tests/harness/mcp_test_setup.ts +1 -1
  86. package/tests/harness/mocks.ts +10 -8
  87. package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
  88. package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +27 -48
  89. package/tests/integration/mcp/mcp_resource.integration.spec.ts +26 -35
  90. package/tests/unit/duckdb/attached_databases.test.ts +51 -33
  91. package/tests/unit/ducklake/ducklake.test.ts +24 -22
  92. package/tests/unit/mcp/prompt_happy.test.ts +8 -8
  93. package/dist/app/assets/HomePage-DbZS0N7G.js +0 -1
  94. package/dist/app/assets/MainPage-CBuWkbmr.js +0 -2
  95. package/dist/app/assets/ModelPage-Bt37smot.js +0 -1
  96. package/dist/app/assets/PackagePage-DLZe50WG.js +0 -1
  97. package/dist/app/assets/ProjectPage-FQTEPXP4.js +0 -1
  98. package/dist/app/assets/WorkbookPage-CkAo16ar.js +0 -1
  99. package/src/mcp/resources/project_resource.ts +0 -184
  100. package/src/service/resolve_project.ts +0 -13
package/src/server.ts CHANGED
@@ -36,9 +36,10 @@ import { logger, loggerMiddleware } from "./logger";
36
36
  import { ManifestController } from "./controller/manifest.controller";
37
37
  import { MaterializationController } from "./controller/materialization.controller";
38
38
  import { initializeMcpServer } from "./mcp/server";
39
+ import { registerLegacyRoutes } from "./server-old";
40
+ import { EnvironmentStore } from "./service/environment_store";
39
41
  import { ManifestService } from "./service/manifest_service";
40
42
  import { MaterializationService } from "./service/materialization_service";
41
- import { ProjectStore } from "./service/project_store";
42
43
 
43
44
  /** Normalize an Express query param into a string[] or undefined. */
44
45
  export function normalizeQueryArray(value: unknown): string[] | undefined {
@@ -132,24 +133,27 @@ const isDevelopment = process.env["NODE_ENV"] === "development";
132
133
  export const app = express();
133
134
  app.use(loggerMiddleware);
134
135
  app.use(httpMetricsMiddleware);
135
- const projectStore = new ProjectStore(SERVER_ROOT);
136
- const manifestService = new ManifestService(projectStore);
137
- const watchModeController = new WatchModeController(projectStore);
138
- const connectionController = new ConnectionController(projectStore);
139
- const modelController = new ModelController(projectStore);
140
- const packageController = new PackageController(projectStore, manifestService);
141
- const databaseController = new DatabaseController(projectStore);
142
- const queryController = new QueryController(projectStore);
143
- const compileController = new CompileController(projectStore);
136
+ const environmentStore = new EnvironmentStore(SERVER_ROOT);
137
+ const manifestService = new ManifestService(environmentStore);
138
+ const watchModeController = new WatchModeController(environmentStore);
139
+ const connectionController = new ConnectionController(environmentStore);
140
+ const modelController = new ModelController(environmentStore);
141
+ const packageController = new PackageController(
142
+ environmentStore,
143
+ manifestService,
144
+ );
145
+ const databaseController = new DatabaseController(environmentStore);
146
+ const queryController = new QueryController(environmentStore);
147
+ const compileController = new CompileController(environmentStore);
144
148
  const materializationService = new MaterializationService(
145
- projectStore,
149
+ environmentStore,
146
150
  manifestService,
147
151
  );
148
152
  const materializationController = new MaterializationController(
149
153
  materializationService,
150
154
  );
151
155
  const manifestController = new ManifestController(
152
- projectStore,
156
+ environmentStore,
153
157
  manifestService,
154
158
  );
155
159
 
@@ -181,7 +185,7 @@ mcpApp.all(MCP_ENDPOINT, async (req, res) => {
181
185
  });
182
186
  };
183
187
 
184
- const requestMcpServer = initializeMcpServer(projectStore);
188
+ const requestMcpServer = initializeMcpServer(environmentStore);
185
189
  await requestMcpServer.connect(transport);
186
190
 
187
191
  res.on("close", () => {
@@ -300,7 +304,7 @@ app.use(drainingGuard);
300
304
 
301
305
  app.get(`${API_PREFIX}/status`, async (_req, res) => {
302
306
  try {
303
- const status = await projectStore.getStatus();
307
+ const status = await environmentStore.getStatus();
304
308
  res.status(200).json(status);
305
309
  } catch (error) {
306
310
  logger.error("Error getting status", { error });
@@ -313,9 +317,9 @@ app.get(`${API_PREFIX}/watch-mode/status`, watchModeController.getWatchStatus);
313
317
  app.post(`${API_PREFIX}/watch-mode/start`, watchModeController.startWatching);
314
318
  app.post(`${API_PREFIX}/watch-mode/stop`, watchModeController.stopWatchMode);
315
319
 
316
- app.get(`${API_PREFIX}/projects`, async (_req, res) => {
320
+ app.get(`${API_PREFIX}/environments`, async (_req, res) => {
317
321
  try {
318
- res.status(200).json(await projectStore.listProjects());
322
+ res.status(200).json(await environmentStore.listEnvironments());
319
323
  } catch (error) {
320
324
  logger.error(error);
321
325
  const { json, status } = internalErrorToHttpError(error as Error);
@@ -323,11 +327,11 @@ app.get(`${API_PREFIX}/projects`, async (_req, res) => {
323
327
  }
324
328
  });
325
329
 
326
- app.post(`${API_PREFIX}/projects`, async (req, res) => {
330
+ app.post(`${API_PREFIX}/environments`, async (req, res) => {
327
331
  try {
328
- logger.info("Adding project", { body: req.body });
329
- const project = await projectStore.addProject(req.body);
330
- res.status(200).json(await project.serialize());
332
+ logger.info("Adding environment", { body: req.body });
333
+ const environment = await environmentStore.addEnvironment(req.body);
334
+ res.status(200).json(await environment.serialize());
331
335
  } catch (error) {
332
336
  logger.error(error);
333
337
  const { json, status } = internalErrorToHttpError(error as Error);
@@ -335,24 +339,13 @@ app.post(`${API_PREFIX}/projects`, async (req, res) => {
335
339
  }
336
340
  });
337
341
 
338
- app.get(`${API_PREFIX}/projects/:projectName`, async (req, res) => {
342
+ app.get(`${API_PREFIX}/environments/:environmentName`, async (req, res) => {
339
343
  try {
340
- const project = await projectStore.getProject(
341
- req.params.projectName,
344
+ const environment = await environmentStore.getEnvironment(
345
+ req.params.environmentName,
342
346
  req.query.reload === "true",
343
347
  );
344
- res.status(200).json(await project.serialize());
345
- } catch (error) {
346
- logger.error(error);
347
- const { json, status } = internalErrorToHttpError(error as Error);
348
- res.status(status).json(json);
349
- }
350
- });
351
-
352
- app.patch(`${API_PREFIX}/projects/:projectName`, async (req, res) => {
353
- try {
354
- const project = await projectStore.updateProject(req.body);
355
- res.status(200).json(await project.serialize());
348
+ res.status(200).json(await environment.serialize());
356
349
  } catch (error) {
357
350
  logger.error(error);
358
351
  const { json, status } = internalErrorToHttpError(error as Error);
@@ -360,10 +353,10 @@ app.patch(`${API_PREFIX}/projects/:projectName`, async (req, res) => {
360
353
  }
361
354
  });
362
355
 
363
- app.delete(`${API_PREFIX}/projects/:projectName`, async (req, res) => {
356
+ app.patch(`${API_PREFIX}/environments/:environmentName`, async (req, res) => {
364
357
  try {
365
- const project = await projectStore.deleteProject(req.params.projectName);
366
- res.status(200).json(await project?.serialize());
358
+ const environment = await environmentStore.updateEnvironment(req.body);
359
+ res.status(200).json(await environment.serialize());
367
360
  } catch (error) {
368
361
  logger.error(error);
369
362
  const { json, status } = internalErrorToHttpError(error as Error);
@@ -371,11 +364,12 @@ app.delete(`${API_PREFIX}/projects/:projectName`, async (req, res) => {
371
364
  }
372
365
  });
373
366
 
374
- app.get(`${API_PREFIX}/projects/:projectName/connections`, async (req, res) => {
367
+ app.delete(`${API_PREFIX}/environments/:environmentName`, async (req, res) => {
375
368
  try {
376
- res.status(200).json(
377
- await connectionController.listConnections(req.params.projectName),
369
+ const environment = await environmentStore.deleteEnvironment(
370
+ req.params.environmentName,
378
371
  );
372
+ res.status(200).json(await environment?.serialize());
379
373
  } catch (error) {
380
374
  logger.error(error);
381
375
  const { json, status } = internalErrorToHttpError(error as Error);
@@ -384,12 +378,29 @@ app.get(`${API_PREFIX}/projects/:projectName/connections`, async (req, res) => {
384
378
  });
385
379
 
386
380
  app.get(
387
- `${API_PREFIX}/projects/:projectName/connections/:connectionName`,
381
+ `${API_PREFIX}/environments/:environmentName/connections`,
382
+ async (req, res) => {
383
+ try {
384
+ res.status(200).json(
385
+ await connectionController.listConnections(
386
+ req.params.environmentName,
387
+ ),
388
+ );
389
+ } catch (error) {
390
+ logger.error(error);
391
+ const { json, status } = internalErrorToHttpError(error as Error);
392
+ res.status(status).json(json);
393
+ }
394
+ },
395
+ );
396
+
397
+ app.get(
398
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName`,
388
399
  async (req, res) => {
389
400
  try {
390
401
  res.status(200).json(
391
402
  await connectionController.getConnection(
392
- req.params.projectName,
403
+ req.params.environmentName,
393
404
  req.params.connectionName,
394
405
  ),
395
406
  );
@@ -402,11 +413,11 @@ app.get(
402
413
  );
403
414
 
404
415
  app.post(
405
- `${API_PREFIX}/projects/:projectName/connections/:connectionName`,
416
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName`,
406
417
  async (req, res) => {
407
418
  try {
408
419
  const result = await connectionController.addConnection(
409
- req.params.projectName,
420
+ req.params.environmentName,
410
421
  req.params.connectionName,
411
422
  req.body,
412
423
  );
@@ -420,11 +431,11 @@ app.post(
420
431
  );
421
432
 
422
433
  app.patch(
423
- `${API_PREFIX}/projects/:projectName/connections/:connectionName`,
434
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName`,
424
435
  async (req, res) => {
425
436
  try {
426
437
  const result = await connectionController.updateConnection(
427
- req.params.projectName,
438
+ req.params.environmentName,
428
439
  req.params.connectionName,
429
440
  req.body,
430
441
  );
@@ -438,11 +449,11 @@ app.patch(
438
449
  );
439
450
 
440
451
  app.delete(
441
- `${API_PREFIX}/projects/:projectName/connections/:connectionName`,
452
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName`,
442
453
  async (req, res) => {
443
454
  try {
444
455
  const result = await connectionController.deleteConnection(
445
- req.params.projectName,
456
+ req.params.environmentName,
446
457
  req.params.connectionName,
447
458
  );
448
459
  res.status(200).json(result);
@@ -467,12 +478,12 @@ app.post(`${API_PREFIX}/connections/test`, async (req, res) => {
467
478
  });
468
479
 
469
480
  app.get(
470
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/schemas`,
481
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/schemas`,
471
482
  async (req, res) => {
472
483
  try {
473
484
  res.status(200).json(
474
485
  await connectionController.listSchemas(
475
- req.params.projectName,
486
+ req.params.environmentName,
476
487
  req.params.connectionName,
477
488
  ),
478
489
  );
@@ -485,12 +496,12 @@ app.get(
485
496
  );
486
497
 
487
498
  app.get(
488
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/schemas/:schemaName/tables`,
499
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/schemas/:schemaName/tables`,
489
500
  async (req, res) => {
490
501
  logger.info("req.params", { params: req.params });
491
502
  try {
492
503
  const results = await connectionController.listTables(
493
- req.params.projectName,
504
+ req.params.environmentName,
494
505
  req.params.connectionName,
495
506
  req.params.schemaName,
496
507
  normalizeQueryArray(req.query.tableNames),
@@ -505,12 +516,12 @@ app.get(
505
516
  );
506
517
 
507
518
  app.get(
508
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/schemas/:schemaName/tables/:tablePath`,
519
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/schemas/:schemaName/tables/:tablePath`,
509
520
  async (req, res) => {
510
521
  logger.info("req.params", { params: req.params });
511
522
  try {
512
523
  const results = await connectionController.getTable(
513
- req.params.projectName,
524
+ req.params.environmentName,
514
525
  req.params.connectionName,
515
526
  req.params.schemaName,
516
527
  req.params.tablePath,
@@ -528,12 +539,12 @@ app.get(
528
539
  // `duckdb` is per-package; non-`duckdb` names fall through to the
529
540
  // project's connection registry via the package's MalloyConfig wrapper.
530
541
  app.get(
531
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/schemas`,
542
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/schemas`,
532
543
  async (req, res) => {
533
544
  try {
534
545
  res.status(200).json(
535
546
  await connectionController.listSchemas(
536
- req.params.projectName,
547
+ req.params.environmentName,
537
548
  req.params.connectionName,
538
549
  req.params.packageName,
539
550
  ),
@@ -547,12 +558,12 @@ app.get(
547
558
  );
548
559
 
549
560
  app.get(
550
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/schemas/:schemaName/tables`,
561
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/schemas/:schemaName/tables`,
551
562
  async (req, res) => {
552
563
  try {
553
564
  res.status(200).json(
554
565
  await connectionController.listTables(
555
- req.params.projectName,
566
+ req.params.environmentName,
556
567
  req.params.connectionName,
557
568
  req.params.schemaName,
558
569
  normalizeQueryArray(req.query.tableNames),
@@ -568,12 +579,12 @@ app.get(
568
579
  );
569
580
 
570
581
  app.get(
571
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/schemas/:schemaName/tables/:tablePath`,
582
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/schemas/:schemaName/tables/:tablePath`,
572
583
  async (req, res) => {
573
584
  try {
574
585
  res.status(200).json(
575
586
  await connectionController.getTable(
576
- req.params.projectName,
587
+ req.params.environmentName,
577
588
  req.params.connectionName,
578
589
  req.params.schemaName,
579
590
  req.params.tablePath,
@@ -589,15 +600,15 @@ app.get(
589
600
  );
590
601
 
591
602
  /**
592
- * @deprecated Use /projects/:projectName/connections/:connectionName/sqlSource POST method instead
603
+ * @deprecated Use /environments/:environmentName/connections/:connectionName/sqlSource POST method instead
593
604
  */
594
605
  app.get(
595
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/sqlSource`,
606
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/sqlSource`,
596
607
  async (req, res) => {
597
608
  try {
598
609
  res.status(200).json(
599
610
  await connectionController.getConnectionSqlSource(
600
- req.params.projectName,
611
+ req.params.environmentName,
601
612
  req.params.connectionName,
602
613
  req.query.sqlStatement as string,
603
614
  ),
@@ -611,12 +622,12 @@ app.get(
611
622
  );
612
623
 
613
624
  app.post(
614
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/sqlSource`,
625
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/sqlSource`,
615
626
  async (req, res) => {
616
627
  try {
617
628
  res.status(200).json(
618
629
  await connectionController.getConnectionSqlSource(
619
- req.params.projectName,
630
+ req.params.environmentName,
620
631
  req.params.connectionName,
621
632
  req.body.sqlStatement as string,
622
633
  ),
@@ -631,12 +642,12 @@ app.post(
631
642
 
632
643
  // Per-package versions
633
644
  app.get(
634
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlSource`,
645
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/sqlSource`,
635
646
  async (req, res) => {
636
647
  try {
637
648
  res.status(200).json(
638
649
  await connectionController.getConnectionSqlSource(
639
- req.params.projectName,
650
+ req.params.environmentName,
640
651
  req.params.connectionName,
641
652
  req.query.sqlStatement as string,
642
653
  req.params.packageName,
@@ -651,12 +662,12 @@ app.get(
651
662
  );
652
663
 
653
664
  app.post(
654
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlSource`,
665
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/sqlSource`,
655
666
  async (req, res) => {
656
667
  try {
657
668
  res.status(200).json(
658
669
  await connectionController.getConnectionSqlSource(
659
- req.params.projectName,
670
+ req.params.environmentName,
660
671
  req.params.connectionName,
661
672
  req.body.sqlStatement as string,
662
673
  req.params.packageName,
@@ -671,15 +682,15 @@ app.post(
671
682
  );
672
683
 
673
684
  /**
674
- * @deprecated Use /projects/:projectName/connections/:connectionName/sqlQuery POST method instead
685
+ * @deprecated Use /environments/:environmentName/connections/:connectionName/sqlQuery POST method instead
675
686
  */
676
687
  app.get(
677
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/queryData`,
688
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/queryData`,
678
689
  async (req, res) => {
679
690
  try {
680
691
  res.status(200).json(
681
692
  await connectionController.getConnectionQueryData(
682
- req.params.projectName,
693
+ req.params.environmentName,
683
694
  req.params.connectionName,
684
695
  req.query.sqlStatement as string,
685
696
  req.query.options as string,
@@ -694,15 +705,15 @@ app.get(
694
705
  );
695
706
 
696
707
  /**
697
- * @deprecated Use /projects/:projectName/packages/:packageName/connections/:connectionName/sqlQuery
708
+ * @deprecated Use /environments/:environmentName/packages/:packageName/connections/:connectionName/sqlQuery
698
709
  */
699
710
  app.get(
700
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/queryData`,
711
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/queryData`,
701
712
  async (req, res) => {
702
713
  try {
703
714
  res.status(200).json(
704
715
  await connectionController.getConnectionQueryData(
705
- req.params.projectName,
716
+ req.params.environmentName,
706
717
  req.params.connectionName,
707
718
  req.query.sqlStatement as string,
708
719
  req.query.options as string,
@@ -718,7 +729,7 @@ app.get(
718
729
  );
719
730
 
720
731
  app.post(
721
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/sqlQuery`,
732
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/sqlQuery`,
722
733
  async (req, res) => {
723
734
  try {
724
735
  let options: string | ParsedQs | (string | ParsedQs)[] | undefined;
@@ -732,7 +743,7 @@ app.post(
732
743
  }
733
744
  res.status(200).json(
734
745
  await connectionController.getConnectionQueryData(
735
- req.params.projectName,
746
+ req.params.environmentName,
736
747
  req.params.connectionName,
737
748
  req.body.sqlStatement as string,
738
749
  options as string,
@@ -747,7 +758,7 @@ app.post(
747
758
  );
748
759
 
749
760
  app.post(
750
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlQuery`,
761
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/sqlQuery`,
751
762
  async (req, res) => {
752
763
  try {
753
764
  let options: string | ParsedQs | (string | ParsedQs)[] | undefined;
@@ -758,7 +769,7 @@ app.post(
758
769
  }
759
770
  res.status(200).json(
760
771
  await connectionController.getConnectionQueryData(
761
- req.params.projectName,
772
+ req.params.environmentName,
762
773
  req.params.connectionName,
763
774
  req.body.sqlStatement as string,
764
775
  options as string,
@@ -774,15 +785,15 @@ app.post(
774
785
  );
775
786
 
776
787
  /**
777
- * @deprecated Use /projects/:projectName/connections/:connectionName/sqlTemporaryTable POST method instead
788
+ * @deprecated Use environments/:environmentName/connections/:connectionName/sqlTemporaryTable POST method instead
778
789
  */
779
790
  app.get(
780
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/temporaryTable`,
791
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/temporaryTable`,
781
792
  async (req, res) => {
782
793
  try {
783
794
  res.status(200).json(
784
795
  await connectionController.getConnectionTemporaryTable(
785
- req.params.projectName,
796
+ req.params.environmentName,
786
797
  req.params.connectionName,
787
798
  req.query.sqlStatement as string,
788
799
  ),
@@ -796,15 +807,15 @@ app.get(
796
807
  );
797
808
 
798
809
  /**
799
- * @deprecated Use /projects/:projectName/packages/:packageName/connections/:connectionName/sqlTemporaryTable
810
+ * @deprecated Use /environments/:environmentName/packages/:packageName/connections/:connectionName/sqlTemporaryTable
800
811
  */
801
812
  app.get(
802
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/temporaryTable`,
813
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/temporaryTable`,
803
814
  async (req, res) => {
804
815
  try {
805
816
  res.status(200).json(
806
817
  await connectionController.getConnectionTemporaryTable(
807
- req.params.projectName,
818
+ req.params.environmentName,
808
819
  req.params.connectionName,
809
820
  req.query.sqlStatement as string,
810
821
  req.params.packageName,
@@ -819,12 +830,12 @@ app.get(
819
830
  );
820
831
 
821
832
  app.post(
822
- `${API_PREFIX}/projects/:projectName/connections/:connectionName/sqlTemporaryTable`,
833
+ `${API_PREFIX}/environments/:environmentName/connections/:connectionName/sqlTemporaryTable`,
823
834
  async (req, res) => {
824
835
  try {
825
836
  res.status(200).json(
826
837
  await connectionController.getConnectionTemporaryTable(
827
- req.params.projectName,
838
+ req.params.environmentName,
828
839
  req.params.connectionName,
829
840
  req.body.sqlStatement as string,
830
841
  ),
@@ -838,12 +849,12 @@ app.post(
838
849
  );
839
850
 
840
851
  app.post(
841
- `${API_PREFIX}/projects/:projectName/packages/:packageName/connections/:connectionName/sqlTemporaryTable`,
852
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/connections/:connectionName/sqlTemporaryTable`,
842
853
  async (req, res) => {
843
854
  try {
844
855
  res.status(200).json(
845
856
  await connectionController.getConnectionTemporaryTable(
846
- req.params.projectName,
857
+ req.params.environmentName,
847
858
  req.params.connectionName,
848
859
  req.body.sqlStatement as string,
849
860
  req.params.packageName,
@@ -857,41 +868,47 @@ app.post(
857
868
  },
858
869
  );
859
870
 
860
- app.get(`${API_PREFIX}/projects/:projectName/packages`, async (req, res) => {
861
- if (req.query.versionId) {
862
- setVersionIdError(res);
863
- return;
864
- }
871
+ app.get(
872
+ `${API_PREFIX}/environments/:environmentName/packages`,
873
+ async (req, res) => {
874
+ if (req.query.versionId) {
875
+ setVersionIdError(res);
876
+ return;
877
+ }
865
878
 
866
- try {
867
- res.status(200).json(
868
- await packageController.listPackages(req.params.projectName),
869
- );
870
- } catch (error) {
871
- logger.error(error);
872
- const { json, status } = internalErrorToHttpError(error as Error);
873
- res.status(status).json(json);
874
- }
875
- });
879
+ try {
880
+ res.status(200).json(
881
+ await packageController.listPackages(req.params.environmentName),
882
+ );
883
+ } catch (error) {
884
+ logger.error(error);
885
+ const { json, status } = internalErrorToHttpError(error as Error);
886
+ res.status(status).json(json);
887
+ }
888
+ },
889
+ );
876
890
 
877
- app.post(`${API_PREFIX}/projects/:projectName/packages`, async (req, res) => {
878
- try {
879
- const autoLoadManifest = req.query.autoLoadManifest === "true";
880
- const _package = await packageController.addPackage(
881
- req.params.projectName,
882
- req.body,
883
- { autoLoadManifest },
884
- );
885
- res.status(200).json(_package?.getPackageMetadata());
886
- } catch (error) {
887
- logger.error(error);
888
- const { json, status } = internalErrorToHttpError(error as Error);
889
- res.status(status).json(json);
890
- }
891
- });
891
+ app.post(
892
+ `${API_PREFIX}/environments/:environmentName/packages`,
893
+ async (req, res) => {
894
+ try {
895
+ const autoLoadManifest = req.query.autoLoadManifest === "true";
896
+ const _package = await packageController.addPackage(
897
+ req.params.environmentName,
898
+ req.body,
899
+ { autoLoadManifest },
900
+ );
901
+ res.status(200).json(_package?.getPackageMetadata());
902
+ } catch (error) {
903
+ logger.error(error);
904
+ const { json, status } = internalErrorToHttpError(error as Error);
905
+ res.status(status).json(json);
906
+ }
907
+ },
908
+ );
892
909
 
893
910
  app.get(
894
- `${API_PREFIX}/projects/:projectName/packages/:packageName`,
911
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName`,
895
912
  async (req, res) => {
896
913
  if (req.query.versionId) {
897
914
  setVersionIdError(res);
@@ -901,7 +918,7 @@ app.get(
901
918
  try {
902
919
  res.status(200).json(
903
920
  await packageController.getPackage(
904
- req.params.projectName,
921
+ req.params.environmentName,
905
922
  req.params.packageName,
906
923
  req.query.reload === "true",
907
924
  ),
@@ -915,12 +932,12 @@ app.get(
915
932
  );
916
933
 
917
934
  app.patch(
918
- `${API_PREFIX}/projects/:projectName/packages/:packageName`,
935
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName`,
919
936
  async (req, res) => {
920
937
  try {
921
938
  res.status(200).json(
922
939
  await packageController.updatePackage(
923
- req.params.projectName,
940
+ req.params.environmentName,
924
941
  req.params.packageName,
925
942
  req.body,
926
943
  ),
@@ -934,12 +951,12 @@ app.patch(
934
951
  );
935
952
 
936
953
  app.delete(
937
- `${API_PREFIX}/projects/:projectName/packages/:packageName`,
954
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName`,
938
955
  async (req, res) => {
939
956
  try {
940
957
  res.status(200).json(
941
958
  await packageController.deletePackage(
942
- req.params.projectName,
959
+ req.params.environmentName,
943
960
  req.params.packageName,
944
961
  ),
945
962
  );
@@ -952,7 +969,7 @@ app.delete(
952
969
  );
953
970
 
954
971
  app.get(
955
- `${API_PREFIX}/projects/:projectName/packages/:packageName/models`,
972
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/models`,
956
973
  async (req, res) => {
957
974
  if (req.query.versionId) {
958
975
  setVersionIdError(res);
@@ -962,7 +979,7 @@ app.get(
962
979
  try {
963
980
  res.status(200).json(
964
981
  await modelController.listModels(
965
- req.params.projectName,
982
+ req.params.environmentName,
966
983
  req.params.packageName,
967
984
  ),
968
985
  );
@@ -975,7 +992,7 @@ app.get(
975
992
  );
976
993
 
977
994
  app.get(
978
- `${API_PREFIX}/projects/:projectName/packages/:packageName/models/*?`,
995
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/models/*?`,
979
996
  async (req, res) => {
980
997
  if (req.query.versionId) {
981
998
  setVersionIdError(res);
@@ -987,7 +1004,7 @@ app.get(
987
1004
  const modelPath = (req.params as Record<string, string>)["0"];
988
1005
  res.status(200).json(
989
1006
  await modelController.getModel(
990
- req.params.projectName,
1007
+ req.params.environmentName,
991
1008
  req.params.packageName,
992
1009
  modelPath,
993
1010
  ),
@@ -1001,7 +1018,7 @@ app.get(
1001
1018
  );
1002
1019
 
1003
1020
  app.get(
1004
- `${API_PREFIX}/projects/:projectName/packages/:packageName/notebooks`,
1021
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/notebooks`,
1005
1022
  async (req, res) => {
1006
1023
  if (req.query.versionId) {
1007
1024
  setVersionIdError(res);
@@ -1011,7 +1028,7 @@ app.get(
1011
1028
  try {
1012
1029
  res.status(200).json(
1013
1030
  await modelController.listNotebooks(
1014
- req.params.projectName,
1031
+ req.params.environmentName,
1015
1032
  req.params.packageName,
1016
1033
  ),
1017
1034
  );
@@ -1026,7 +1043,7 @@ app.get(
1026
1043
  // Execute notebook cell route must come BEFORE the general get notebook route
1027
1044
  // to avoid the wildcard matching incorrectly
1028
1045
  app.get(
1029
- `${API_PREFIX}/projects/:projectName/packages/:packageName/notebooks/*/cells/:cellIndex`,
1046
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/notebooks/*/cells/:cellIndex`,
1030
1047
  async (req, res) => {
1031
1048
  if (req.query.versionId) {
1032
1049
  setVersionIdError(res);
@@ -1062,7 +1079,7 @@ app.get(
1062
1079
 
1063
1080
  res.status(200).json(
1064
1081
  await modelController.executeNotebookCell(
1065
- req.params.projectName,
1082
+ req.params.environmentName,
1066
1083
  req.params.packageName,
1067
1084
  notebookPath,
1068
1085
  cellIndex,
@@ -1079,7 +1096,7 @@ app.get(
1079
1096
  );
1080
1097
 
1081
1098
  app.get(
1082
- `${API_PREFIX}/projects/:projectName/packages/:packageName/notebooks/*?`,
1099
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/notebooks/*?`,
1083
1100
  async (req, res) => {
1084
1101
  if (req.query.versionId) {
1085
1102
  setVersionIdError(res);
@@ -1091,7 +1108,7 @@ app.get(
1091
1108
  const notebookPath = (req.params as Record<string, string>)["0"];
1092
1109
  res.status(200).json(
1093
1110
  await modelController.getNotebook(
1094
- req.params.projectName,
1111
+ req.params.environmentName,
1095
1112
  req.params.packageName,
1096
1113
  notebookPath,
1097
1114
  ),
@@ -1105,7 +1122,7 @@ app.get(
1105
1122
  );
1106
1123
 
1107
1124
  app.post(
1108
- `${API_PREFIX}/projects/:projectName/packages/:packageName/models/*?/query`,
1125
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/models/*?/query`,
1109
1126
  async (req, res) => {
1110
1127
  if (req.body.versionId) {
1111
1128
  setVersionIdError(res);
@@ -1117,7 +1134,7 @@ app.post(
1117
1134
  const modelPath = (req.params as Record<string, string>)["0"];
1118
1135
  res.status(200).json(
1119
1136
  await queryController.getQuery(
1120
- req.params.projectName,
1137
+ req.params.environmentName,
1121
1138
  req.params.packageName,
1122
1139
  modelPath,
1123
1140
  req.body.sourceName as string,
@@ -1139,7 +1156,7 @@ app.post(
1139
1156
  );
1140
1157
 
1141
1158
  app.get(
1142
- `${API_PREFIX}/projects/:projectName/packages/:packageName/databases`,
1159
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/databases`,
1143
1160
  async (req, res) => {
1144
1161
  if (req.query.versionId) {
1145
1162
  setVersionIdError(res);
@@ -1149,7 +1166,7 @@ app.get(
1149
1166
  try {
1150
1167
  res.status(200).json(
1151
1168
  await databaseController.listDatabases(
1152
- req.params.projectName,
1169
+ req.params.environmentName,
1153
1170
  req.params.packageName,
1154
1171
  ),
1155
1172
  );
@@ -1162,11 +1179,11 @@ app.get(
1162
1179
  );
1163
1180
 
1164
1181
  app.post(
1165
- `${API_PREFIX}/projects/:projectName/packages/:packageName/models/:modelName/compile`,
1182
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/models/:modelName/compile`,
1166
1183
  async (req, res) => {
1167
1184
  try {
1168
1185
  const result = await compileController.compile(
1169
- req.params.projectName,
1186
+ req.params.environmentName,
1170
1187
  req.params.packageName,
1171
1188
  req.params.modelName,
1172
1189
  req.body.source,
@@ -1184,11 +1201,11 @@ app.post(
1184
1201
  // ==================== MATERIALIZATION ROUTES ====================
1185
1202
 
1186
1203
  app.post(
1187
- `${API_PREFIX}/projects/:projectName/packages/:packageName/materializations`,
1204
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/materializations`,
1188
1205
  async (req, res) => {
1189
1206
  try {
1190
1207
  const build = await materializationController.createMaterialization(
1191
- req.params.projectName,
1208
+ req.params.environmentName,
1192
1209
  req.params.packageName,
1193
1210
  req.body || {},
1194
1211
  );
@@ -1201,7 +1218,7 @@ app.post(
1201
1218
  );
1202
1219
 
1203
1220
  app.get(
1204
- `${API_PREFIX}/projects/:projectName/packages/:packageName/materializations`,
1221
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/materializations`,
1205
1222
  async (req, res) => {
1206
1223
  try {
1207
1224
  const limit = req.query.limit
@@ -1211,7 +1228,7 @@ app.get(
1211
1228
  ? parseInt(req.query.offset as string, 10)
1212
1229
  : undefined;
1213
1230
  const builds = await materializationController.listMaterializations(
1214
- req.params.projectName,
1231
+ req.params.environmentName,
1215
1232
  req.params.packageName,
1216
1233
  { limit, offset },
1217
1234
  );
@@ -1224,11 +1241,11 @@ app.get(
1224
1241
  );
1225
1242
 
1226
1243
  app.get(
1227
- `${API_PREFIX}/projects/:projectName/packages/:packageName/materializations/:materializationId`,
1244
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/materializations/:materializationId`,
1228
1245
  async (req, res) => {
1229
1246
  try {
1230
1247
  const build = await materializationController.getMaterialization(
1231
- req.params.projectName,
1248
+ req.params.environmentName,
1232
1249
  req.params.packageName,
1233
1250
  req.params.materializationId,
1234
1251
  );
@@ -1241,11 +1258,11 @@ app.get(
1241
1258
  );
1242
1259
 
1243
1260
  app.post(
1244
- `${API_PREFIX}/projects/:projectName/packages/:packageName/materializations/teardown`,
1261
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/materializations/teardown`,
1245
1262
  async (req, res) => {
1246
1263
  try {
1247
1264
  const result = await materializationController.teardownPackage(
1248
- req.params.projectName,
1265
+ req.params.environmentName,
1249
1266
  req.params.packageName,
1250
1267
  req.body || {},
1251
1268
  );
@@ -1258,20 +1275,20 @@ app.post(
1258
1275
  );
1259
1276
 
1260
1277
  app.post(
1261
- `${API_PREFIX}/projects/:projectName/packages/:packageName/materializations/:materializationId`,
1278
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/materializations/:materializationId`,
1262
1279
  async (req, res) => {
1263
1280
  try {
1264
1281
  const action = req.query.action;
1265
1282
  if (action === "start") {
1266
1283
  const build = await materializationController.startMaterialization(
1267
- req.params.projectName,
1284
+ req.params.environmentName,
1268
1285
  req.params.packageName,
1269
1286
  req.params.materializationId,
1270
1287
  );
1271
1288
  res.status(202).json(build);
1272
1289
  } else if (action === "stop") {
1273
1290
  const build = await materializationController.stopMaterialization(
1274
- req.params.projectName,
1291
+ req.params.environmentName,
1275
1292
  req.params.packageName,
1276
1293
  req.params.materializationId,
1277
1294
  );
@@ -1289,11 +1306,11 @@ app.post(
1289
1306
  );
1290
1307
 
1291
1308
  app.delete(
1292
- `${API_PREFIX}/projects/:projectName/packages/:packageName/materializations/:materializationId`,
1309
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/materializations/:materializationId`,
1293
1310
  async (req, res) => {
1294
1311
  try {
1295
1312
  await materializationController.deleteMaterialization(
1296
- req.params.projectName,
1313
+ req.params.environmentName,
1297
1314
  req.params.packageName,
1298
1315
  req.params.materializationId,
1299
1316
  );
@@ -1308,11 +1325,11 @@ app.delete(
1308
1325
  // ==================== MANIFEST ROUTES ====================
1309
1326
 
1310
1327
  app.get(
1311
- `${API_PREFIX}/projects/:projectName/packages/:packageName/manifest`,
1328
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/manifest`,
1312
1329
  async (req, res) => {
1313
1330
  try {
1314
1331
  const manifest = await manifestController.getManifest(
1315
- req.params.projectName,
1332
+ req.params.environmentName,
1316
1333
  req.params.packageName,
1317
1334
  );
1318
1335
  res.status(200).json(manifest);
@@ -1325,13 +1342,13 @@ app.get(
1325
1342
  );
1326
1343
 
1327
1344
  app.post(
1328
- `${API_PREFIX}/projects/:projectName/packages/:packageName/manifest`,
1345
+ `${API_PREFIX}/environments/:environmentName/packages/:packageName/manifest`,
1329
1346
  async (req, res) => {
1330
1347
  try {
1331
1348
  const action = req.query.action;
1332
1349
  if (action === "reload") {
1333
1350
  const manifest = await manifestController.reloadManifest(
1334
- req.params.projectName,
1351
+ req.params.environmentName,
1335
1352
  req.params.packageName,
1336
1353
  );
1337
1354
  res.status(200).json(manifest);
@@ -1348,6 +1365,21 @@ app.post(
1348
1365
  },
1349
1366
  );
1350
1367
 
1368
+ // Register legacy `/projects/...` routes for backwards compatibility with
1369
+ // clients that haven't migrated to `/environments/...` yet. Must be added
1370
+ // before the SPA catch-all below.
1371
+ registerLegacyRoutes(app, {
1372
+ environmentStore,
1373
+ connectionController,
1374
+ modelController,
1375
+ packageController,
1376
+ databaseController,
1377
+ queryController,
1378
+ compileController,
1379
+ materializationController,
1380
+ manifestController,
1381
+ });
1382
+
1351
1383
  // Modify the catch-all route to only serve index.html in production
1352
1384
  if (!isDevelopment) {
1353
1385
  app.get("*", (_req, res) => res.sendFile(path.resolve(ROOT, "index.html")));