@malloy-publisher/server 0.0.195 → 0.0.197-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 +1352 -1310
  16. package/package.json +2 -2
  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.ts +175 -159
  48. package/src/service/connection.spec.ts +158 -133
  49. package/src/service/connection.ts +42 -39
  50. package/src/service/connection_config.spec.ts +13 -11
  51. package/src/service/connection_config.ts +28 -19
  52. package/src/service/connection_service.spec.ts +63 -43
  53. package/src/service/connection_service.ts +106 -89
  54. package/src/service/{project.ts → environment.ts} +92 -77
  55. package/src/service/{project_compile.spec.ts → environment_compile.spec.ts} +1 -1
  56. package/src/service/{project_store.spec.ts → environment_store.spec.ts} +99 -83
  57. package/src/service/{project_store.ts → environment_store.ts} +373 -327
  58. package/src/service/manifest_service.spec.ts +15 -15
  59. package/src/service/manifest_service.ts +26 -21
  60. package/src/service/materialization_service.spec.ts +93 -59
  61. package/src/service/materialization_service.ts +71 -62
  62. package/src/service/materialized_table_gc.spec.ts +15 -15
  63. package/src/service/materialized_table_gc.ts +3 -3
  64. package/src/service/model.ts +4 -4
  65. package/src/service/package.spec.ts +2 -2
  66. package/src/service/package.ts +23 -21
  67. package/src/service/resolve_environment.ts +15 -0
  68. package/src/storage/DatabaseInterface.ts +34 -25
  69. package/src/storage/StorageManager.mock.ts +3 -3
  70. package/src/storage/StorageManager.ts +64 -28
  71. package/src/storage/duckdb/ConnectionRepository.ts +13 -11
  72. package/src/storage/duckdb/DuckDBConnection.ts +1 -1
  73. package/src/storage/duckdb/DuckDBManifestStore.ts +6 -6
  74. package/src/storage/duckdb/DuckDBRepository.ts +47 -47
  75. package/src/storage/duckdb/{ProjectRepository.ts → EnvironmentRepository.ts} +35 -35
  76. package/src/storage/duckdb/ManifestRepository.ts +21 -20
  77. package/src/storage/duckdb/MaterializationRepository.ts +31 -28
  78. package/src/storage/duckdb/PackageRepository.ts +11 -11
  79. package/src/storage/duckdb/manifest_store.spec.ts +2 -2
  80. package/src/storage/duckdb/schema.ts +20 -20
  81. package/src/storage/ducklake/DuckLakeManifestStore.ts +20 -11
  82. package/tests/fixtures/publisher.config.json +1 -1
  83. package/tests/harness/e2e.ts +1 -1
  84. package/tests/harness/mcp_test_setup.ts +12 -24
  85. package/tests/harness/mocks.ts +10 -8
  86. package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
  87. package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +28 -49
  88. package/tests/integration/mcp/mcp_resource.integration.spec.ts +39 -47
  89. package/tests/integration/mcp/mcp_transport.integration.spec.ts +1 -1
  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
@@ -5,13 +5,14 @@ import * as sinon from "sinon";
5
5
  import { components } from "../api";
6
6
  import { isPublisherConfigFrozen } from "../config";
7
7
  import { TEMP_DIR_PATH } from "../constants";
8
- import { Project } from "./project";
9
- import { ProjectStore } from "./project_store";
8
+ import { Environment } from "./environment";
9
+ import { EnvironmentStore } from "./environment_store";
10
10
 
11
11
  type MockData = Record<string, unknown>;
12
12
 
13
13
  const initializeDuckLakeCalls: Array<{
14
- projectId: string;
14
+ environmentId: string;
15
+ environmentName: string;
15
16
  config: { catalogUrl: string; dataPath: string };
16
17
  }> = [];
17
18
 
@@ -22,19 +23,24 @@ mock.module("../storage/StorageManager", () => {
22
23
  return;
23
24
  }
24
25
 
25
- async initializeDuckLakeForProject(
26
- projectId: string,
26
+ async initializeDuckLakeForEnvironment(
27
+ environmentId: string,
28
+ environmentName: string,
27
29
  config: { catalogUrl: string; dataPath: string },
28
30
  ): Promise<void> {
29
- initializeDuckLakeCalls.push({ projectId, config });
31
+ initializeDuckLakeCalls.push({
32
+ environmentId,
33
+ environmentName,
34
+ config,
35
+ });
30
36
  }
31
37
 
32
38
  getRepository() {
33
39
  return {
34
40
  // ===== PROJECT METHODS =====
35
- listProjects: async (): Promise<unknown[]> => [],
41
+ listEnvironments: async (): Promise<unknown[]> => [],
36
42
 
37
- getProjectById: async (
43
+ getEnvironmentById: async (
38
44
  id: string,
39
45
  ): Promise<MockData | null> => ({
40
46
  id,
@@ -46,14 +52,16 @@ mock.module("../storage/StorageManager", () => {
46
52
  updatedAt: new Date(),
47
53
  }),
48
54
 
49
- getProjectByName: async (
55
+ getEnvironmentByName: async (
50
56
  _name: string,
51
57
  ): Promise<MockData | null> => {
52
58
  // Return null to simulate "project doesn't exist yet"
53
59
  return null;
54
60
  },
55
61
 
56
- createProject: async (data: MockData): Promise<MockData> => ({
62
+ createEnvironment: async (
63
+ data: MockData,
64
+ ): Promise<MockData> => ({
57
65
  id: "test-project-id",
58
66
  name: data.name,
59
67
  path: data.path,
@@ -63,7 +71,7 @@ mock.module("../storage/StorageManager", () => {
63
71
  updatedAt: new Date(),
64
72
  }),
65
73
 
66
- updateProject: async (
74
+ updateEnvironment: async (
67
75
  id: string,
68
76
  data: MockData,
69
77
  ): Promise<MockData> => ({
@@ -79,18 +87,18 @@ mock.module("../storage/StorageManager", () => {
79
87
  updatedAt: new Date(),
80
88
  }),
81
89
 
82
- deleteProject: async (_id: string): Promise<void> => {},
90
+ deleteEnvironment: async (_id: string): Promise<void> => {},
83
91
 
84
92
  // ===== PACKAGE METHODS =====
85
93
  listPackages: async (
86
- _projectId: string,
94
+ _environmentId: string,
87
95
  ): Promise<unknown[]> => [],
88
96
 
89
97
  getPackageById: async (
90
98
  id: string,
91
99
  ): Promise<MockData | null> => ({
92
100
  id,
93
- projectId: "test-project-id",
101
+ environmentId: "test-project-id",
94
102
  name: "test-package",
95
103
  description: "Test package",
96
104
  manifestPath: "/test/manifest.json",
@@ -100,13 +108,13 @@ mock.module("../storage/StorageManager", () => {
100
108
  }),
101
109
 
102
110
  getPackageByName: async (
103
- _projectId: string,
111
+ _environmentId: string,
104
112
  _name: string,
105
113
  ): Promise<MockData | null> => null,
106
114
 
107
115
  createPackage: async (data: MockData): Promise<MockData> => ({
108
116
  id: "test-package-id",
109
- projectId: data.projectId,
117
+ environmentId: data.environmentId,
110
118
  name: data.name,
111
119
  description: data.description,
112
120
  manifestPath: data.manifestPath,
@@ -120,7 +128,7 @@ mock.module("../storage/StorageManager", () => {
120
128
  data: MockData,
121
129
  ): Promise<MockData> => ({
122
130
  id,
123
- projectId: "test-project-id",
131
+ environmentId: "test-project-id",
124
132
  name: "test-package",
125
133
  description: data.description,
126
134
  manifestPath: "/test/manifest.json",
@@ -133,14 +141,14 @@ mock.module("../storage/StorageManager", () => {
133
141
 
134
142
  // ===== CONNECTION METHODS =====
135
143
  listConnections: async (
136
- _projectId: string,
144
+ _environmentId: string,
137
145
  ): Promise<unknown[]> => [],
138
146
 
139
147
  getConnectionById: async (
140
148
  id: string,
141
149
  ): Promise<MockData | null> => ({
142
150
  id,
143
- projectId: "test-project-id",
151
+ environmentId: "test-project-id",
144
152
  name: "test-connection",
145
153
  type: "postgres",
146
154
  config: {},
@@ -149,13 +157,13 @@ mock.module("../storage/StorageManager", () => {
149
157
  }),
150
158
 
151
159
  getConnectionByName: async (
152
- _projectId: string,
160
+ _environmentId: string,
153
161
  _name: string,
154
162
  ): Promise<MockData | null> => null,
155
163
 
156
164
  createConnection: async (data: MockData): Promise<MockData> => ({
157
165
  id: "test-connection-id",
158
- projectId: data.projectId,
166
+ environmentId: data.environmentId,
159
167
  name: data.name,
160
168
  type: data.type,
161
169
  config: data.config,
@@ -168,7 +176,7 @@ mock.module("../storage/StorageManager", () => {
168
176
  data: MockData,
169
177
  ): Promise<MockData> => ({
170
178
  id,
171
- projectId: "test-project-id",
179
+ environmentId: "test-project-id",
172
180
  name: "test-connection",
173
181
  type: "postgres",
174
182
  config: data.config || {},
@@ -194,8 +202,8 @@ const projectName = "organizationName-projectName";
194
202
 
195
203
  let sandbox: sinon.SinonSandbox;
196
204
 
197
- describe("ProjectStore Service", () => {
198
- let projectStore: ProjectStore;
205
+ describe("EnvironmentStore Service", () => {
206
+ let environmentStore: EnvironmentStore;
199
207
 
200
208
  beforeEach(async () => {
201
209
  // Clean up any existing test directory
@@ -212,7 +220,7 @@ describe("ProjectStore Service", () => {
212
220
  }));
213
221
 
214
222
  // Create project store after mocking
215
- projectStore = new ProjectStore(serverRootPath);
223
+ environmentStore = new EnvironmentStore(serverRootPath);
216
224
  });
217
225
 
218
226
  afterEach(async () => {
@@ -226,7 +234,7 @@ describe("ProjectStore Service", () => {
226
234
 
227
235
  it("should not load a package if the project does not exist", async () => {
228
236
  await expect(
229
- projectStore.getProject("non-existent-project"),
237
+ environmentStore.getEnvironment("non-existent-project"),
230
238
  ).rejects.toThrow();
231
239
  });
232
240
 
@@ -254,7 +262,7 @@ describe("ProjectStore Service", () => {
254
262
  publisherConfigPath,
255
263
  JSON.stringify({
256
264
  frozenConfig: false,
257
- projects: [
265
+ environments: [
258
266
  {
259
267
  name: projectName,
260
268
  packages: [
@@ -275,8 +283,8 @@ describe("ProjectStore Service", () => {
275
283
  );
276
284
 
277
285
  // Test that the project can be retrieved
278
- const project = await projectStore.getProject(projectName);
279
- expect(project).toBeInstanceOf(Project);
286
+ const project = await environmentStore.getEnvironment(projectName);
287
+ expect(project).toBeInstanceOf(Environment);
280
288
  expect(project.metadata.name).toBe(projectName);
281
289
  },
282
290
  { timeout: 30000 },
@@ -301,7 +309,7 @@ describe("ProjectStore Service", () => {
301
309
  publisherConfigPath,
302
310
  JSON.stringify({
303
311
  frozenConfig: false,
304
- projects: [
312
+ environments: [
305
313
  {
306
314
  name: projectName1,
307
315
  packages: [
@@ -338,11 +346,11 @@ describe("ProjectStore Service", () => {
338
346
  );
339
347
 
340
348
  // Create a new project store that will read the configuration
341
- const newProjectStore = new ProjectStore(serverRootPath);
342
- await newProjectStore.finishedInitialization;
349
+ const newEnvironmentStore = new EnvironmentStore(serverRootPath);
350
+ await newEnvironmentStore.finishedInitialization;
343
351
 
344
352
  // Test that both projects can be listed
345
- const projects = await newProjectStore.listProjects();
353
+ const projects = await newEnvironmentStore.listEnvironments();
346
354
  expect(projects).toBeInstanceOf(Array);
347
355
  expect(projects.length).toBe(2);
348
356
  expect(projects.map((p) => p.name)).toContain(projectName1);
@@ -380,7 +388,7 @@ describe("ProjectStore Service", () => {
380
388
  publisherConfigPath,
381
389
  JSON.stringify({
382
390
  frozenConfig: false,
383
- projects: [
391
+ environments: [
384
392
  {
385
393
  name: invalidProjectName,
386
394
  packages: [
@@ -411,13 +419,13 @@ describe("ProjectStore Service", () => {
411
419
  }),
412
420
  );
413
421
 
414
- const newProjectStore = new ProjectStore(serverRootPath);
415
- await newProjectStore.finishedInitialization;
422
+ const newEnvironmentStore = new EnvironmentStore(serverRootPath);
423
+ await newEnvironmentStore.finishedInitialization;
416
424
 
417
- const projects = await newProjectStore.listProjects();
425
+ const projects = await newEnvironmentStore.listEnvironments();
418
426
  expect(projects.map((p) => p.name)).toEqual([validProjectName]);
419
427
  await expect(
420
- newProjectStore.getProject(invalidProjectName),
428
+ newEnvironmentStore.getEnvironment(invalidProjectName),
421
429
  ).rejects.toThrow();
422
430
  });
423
431
 
@@ -442,7 +450,7 @@ describe("ProjectStore Service", () => {
442
450
  publisherConfigPath,
443
451
  JSON.stringify({
444
452
  frozenConfig: false,
445
- projects: [
453
+ environments: [
446
454
  {
447
455
  name: projectName,
448
456
  packages: [
@@ -456,10 +464,10 @@ describe("ProjectStore Service", () => {
456
464
  }),
457
465
  );
458
466
 
459
- await projectStore.finishedInitialization;
467
+ await environmentStore.finishedInitialization;
460
468
 
461
469
  // Get the project
462
- const project = await projectStore.getProject(projectName);
470
+ const project = await environmentStore.getEnvironment(projectName);
463
471
 
464
472
  // Update the project
465
473
  await project.update({
@@ -479,13 +487,13 @@ describe("ProjectStore Service", () => {
479
487
  expect(readmeContent).toBe("Updated README content");
480
488
  });
481
489
 
482
- it("should propagate materializationStorage on addProject for new project", async () => {
490
+ it("should propagate materializationStorage on addEnvironment for new environment", async () => {
483
491
  writeFileSync(
484
492
  path.join(serverRootPath, "publisher.config.json"),
485
- JSON.stringify({ frozenConfig: false, projects: [] }),
493
+ JSON.stringify({ frozenConfig: false, environments: [] }),
486
494
  );
487
495
 
488
- await projectStore.finishedInitialization;
496
+ await environmentStore.finishedInitialization;
489
497
 
490
498
  const materializationStorage = {
491
499
  catalogUrl:
@@ -494,7 +502,7 @@ describe("ProjectStore Service", () => {
494
502
  };
495
503
 
496
504
  initializeDuckLakeCalls.length = 0;
497
- const project = await projectStore.addProject({
505
+ const project = await environmentStore.addEnvironment({
498
506
  name: projectName,
499
507
  materializationStorage,
500
508
  });
@@ -517,7 +525,7 @@ describe("ProjectStore Service", () => {
517
525
  path.join(serverRootPath, "publisher.config.json"),
518
526
  JSON.stringify({
519
527
  frozenConfig: false,
520
- projects: [
528
+ environments: [
521
529
  {
522
530
  name: projectName,
523
531
  packages: [{ name: projectName, location: projectPath }],
@@ -526,8 +534,8 @@ describe("ProjectStore Service", () => {
526
534
  }),
527
535
  );
528
536
 
529
- await projectStore.finishedInitialization;
530
- const project = await projectStore.getProject(projectName);
537
+ await environmentStore.finishedInitialization;
538
+ const project = await environmentStore.getEnvironment(projectName);
531
539
 
532
540
  const materializationStorage = {
533
541
  catalogUrl:
@@ -565,7 +573,7 @@ describe("ProjectStore Service", () => {
565
573
  writeFileSync(
566
574
  publisherConfigPath,
567
575
  JSON.stringify({
568
- projects: [
576
+ environments: [
569
577
  {
570
578
  name: projectName,
571
579
  packages: [
@@ -580,13 +588,16 @@ describe("ProjectStore Service", () => {
580
588
  );
581
589
 
582
590
  // Get the project
583
- const project1 = await projectStore.getProject(projectName);
591
+ const project1 = await environmentStore.getEnvironment(projectName);
584
592
 
585
593
  // Get the project again with reload=true
586
- const project2 = await projectStore.getProject(projectName, true);
594
+ const project2 = await environmentStore.getEnvironment(
595
+ projectName,
596
+ true,
597
+ );
587
598
 
588
- expect(project1).toBeInstanceOf(Project);
589
- expect(project2).toBeInstanceOf(Project);
599
+ expect(project1).toBeInstanceOf(Environment);
600
+ expect(project2).toBeInstanceOf(Environment);
590
601
  expect(project1.metadata.name).toBe(project2.metadata.name as string);
591
602
  },
592
603
  { timeout: 30000 },
@@ -601,7 +612,7 @@ describe("ProjectStore Service", () => {
601
612
  writeFileSync(
602
613
  publisherConfigPath,
603
614
  JSON.stringify({
604
- projects: [
615
+ environments: [
605
616
  {
606
617
  name: projectName,
607
618
  packages: [
@@ -616,7 +627,9 @@ describe("ProjectStore Service", () => {
616
627
  );
617
628
 
618
629
  // Test that getting the project throws an error
619
- await expect(projectStore.getProject(projectName)).rejects.toThrow();
630
+ await expect(
631
+ environmentStore.getEnvironment(projectName),
632
+ ).rejects.toThrow();
620
633
  });
621
634
 
622
635
  it("should handle invalid publisher config", async () => {
@@ -628,11 +641,11 @@ describe("ProjectStore Service", () => {
628
641
  writeFileSync(publisherConfigPath, "invalid json");
629
642
 
630
643
  // Create a new project store that will read the invalid config
631
- const newProjectStore = new ProjectStore(serverRootPath);
644
+ const newEnvironmentStore = new EnvironmentStore(serverRootPath);
632
645
 
633
646
  // Test that the project store handles invalid JSON gracefully by falling back to empty config
634
- await newProjectStore.finishedInitialization;
635
- const projects = await newProjectStore.listProjects();
647
+ await newEnvironmentStore.finishedInitialization;
648
+ const projects = await newEnvironmentStore.listEnvironments();
636
649
  expect(projects).toEqual([]);
637
650
  });
638
651
 
@@ -646,7 +659,7 @@ describe("ProjectStore Service", () => {
646
659
  publisherConfigPath,
647
660
  JSON.stringify({
648
661
  frozenConfig: false,
649
- projects: [
662
+ environments: [
650
663
  {
651
664
  invalidKey1: "malloy-samples", // Invalid: should be "name"
652
665
  invalidKey2: [
@@ -669,11 +682,11 @@ describe("ProjectStore Service", () => {
669
682
  );
670
683
 
671
684
  // Create a new project store that will read the invalid config
672
- const newProjectStore = new ProjectStore(serverRootPath);
685
+ const newEnvironmentStore = new EnvironmentStore(serverRootPath);
673
686
 
674
687
  // Test that the project store handles invalid fields gracefully without crashing
675
- await newProjectStore.finishedInitialization;
676
- const projects = await newProjectStore.listProjects();
688
+ await newEnvironmentStore.finishedInitialization;
689
+ const projects = await newEnvironmentStore.listEnvironments();
677
690
 
678
691
  // Should not crash and should return empty array since invalid projects are filtered out
679
692
  expect(projects).toEqual([]);
@@ -699,7 +712,7 @@ describe("ProjectStore Service", () => {
699
712
  publisherConfigPath,
700
713
  JSON.stringify({
701
714
  frozenConfig: false,
702
- projects: [
715
+ environments: [
703
716
  {
704
717
  // Invalid project: missing "name" field
705
718
  packages: [
@@ -744,11 +757,11 @@ describe("ProjectStore Service", () => {
744
757
  );
745
758
 
746
759
  // Create a new project store that will read the config
747
- const newProjectStore = new ProjectStore(serverRootPath);
760
+ const newEnvironmentStore = new EnvironmentStore(serverRootPath);
748
761
 
749
762
  // Test that invalid projects are filtered out
750
- await newProjectStore.finishedInitialization;
751
- const projects = await newProjectStore.listProjects();
763
+ await newEnvironmentStore.finishedInitialization;
764
+ const projects = await newEnvironmentStore.listEnvironments();
752
765
 
753
766
  // Should only have the valid project
754
767
  expect(projects.length).toBe(1);
@@ -778,7 +791,7 @@ describe("ProjectStore Service", () => {
778
791
  publisherConfigPath,
779
792
  JSON.stringify({
780
793
  frozenConfig: false,
781
- projects: [
794
+ environments: [
782
795
  {
783
796
  name: projectName,
784
797
  packages: [
@@ -798,18 +811,18 @@ describe("ProjectStore Service", () => {
798
811
  }),
799
812
  );
800
813
 
801
- await projectStore.finishedInitialization;
814
+ await environmentStore.finishedInitialization;
802
815
 
803
816
  // Test concurrent access to the same project
804
817
  const promises = Array.from({ length: 5 }, () =>
805
- projectStore.getProject(projectName),
818
+ environmentStore.getEnvironment(projectName),
806
819
  );
807
820
 
808
821
  const projects = await Promise.all(promises);
809
822
 
810
823
  expect(projects).toHaveLength(5);
811
824
  projects.forEach((project) => {
812
- expect(project).toBeInstanceOf(Project);
825
+ expect(project).toBeInstanceOf(Environment);
813
826
  expect(project.metadata.name).toBe(projectName);
814
827
  });
815
828
  },
@@ -819,7 +832,7 @@ describe("ProjectStore Service", () => {
819
832
 
820
833
  describe("Project Service Error Recovery", () => {
821
834
  let sandbox: sinon.SinonSandbox;
822
- let projectStore: ProjectStore;
835
+ let environmentStore: EnvironmentStore;
823
836
  const serverRootPath = path.join(
824
837
  TEMP_DIR_PATH,
825
838
  "pathways-worker-publisher-error-recovery-test",
@@ -850,7 +863,7 @@ describe("Project Service Error Recovery", () => {
850
863
  }));
851
864
 
852
865
  // Create project store after mocking
853
- projectStore = new ProjectStore(serverRootPath);
866
+ environmentStore = new EnvironmentStore(serverRootPath);
854
867
  });
855
868
 
856
869
  afterEach(async () => {
@@ -870,7 +883,7 @@ describe("Project Service Error Recovery", () => {
870
883
  writeFileSync(
871
884
  publisherConfigPath,
872
885
  JSON.stringify({
873
- projects: [
886
+ environments: [
874
887
  {
875
888
  name: projectName,
876
889
  packages: [
@@ -888,7 +901,9 @@ describe("Project Service Error Recovery", () => {
888
901
  );
889
902
 
890
903
  // Test that the project store handles the missing directory
891
- await expect(projectStore.getProject(projectName)).rejects.toThrow();
904
+ await expect(
905
+ environmentStore.getEnvironment(projectName),
906
+ ).rejects.toThrow();
892
907
  });
893
908
 
894
909
  it(
@@ -921,7 +936,7 @@ describe("Project Service Error Recovery", () => {
921
936
  writeFileSync(
922
937
  publisherConfigPath,
923
938
  JSON.stringify({
924
- projects: [
939
+ environments: [
925
940
  {
926
941
  name: projectName,
927
942
  packages: [
@@ -937,8 +952,8 @@ describe("Project Service Error Recovery", () => {
937
952
 
938
953
  // Test that the project store handles corrupted connection files gracefully
939
954
  // (The current implementation loads the project even with corrupted connection files)
940
- const project = await projectStore.getProject(projectName);
941
- expect(project).toBeInstanceOf(Project);
955
+ const project = await environmentStore.getEnvironment(projectName);
956
+ expect(project).toBeInstanceOf(Environment);
942
957
  expect(project.metadata.name).toBe(projectName);
943
958
  },
944
959
  { timeout: 30000 },
@@ -972,7 +987,7 @@ describe("Project Service Error Recovery", () => {
972
987
  writeFileSync(
973
988
  publisherConfigPath,
974
989
  JSON.stringify({
975
- projects: [
990
+ environments: [
976
991
  {
977
992
  name: projectName,
978
993
  packages: [
@@ -987,17 +1002,18 @@ describe("Project Service Error Recovery", () => {
987
1002
  );
988
1003
 
989
1004
  // Get the project successfully
990
- const project = await projectStore.getProject(projectName);
991
- expect(project).toBeInstanceOf(Project);
1005
+ const project = await environmentStore.getEnvironment(projectName);
1006
+ expect(project).toBeInstanceOf(Environment);
992
1007
 
993
1008
  // Try to get a non-existent project
994
1009
  await expect(
995
- projectStore.getProject("non-existent"),
1010
+ environmentStore.getEnvironment("non-existent"),
996
1011
  ).rejects.toThrow();
997
1012
 
998
1013
  // Verify the original project is still accessible
999
- const projectAgain = await projectStore.getProject(projectName);
1000
- expect(projectAgain).toBeInstanceOf(Project);
1014
+ const projectAgain =
1015
+ await environmentStore.getEnvironment(projectName);
1016
+ expect(projectAgain).toBeInstanceOf(Environment);
1001
1017
  expect(projectAgain.metadata.name).toBe(projectName);
1002
1018
  },
1003
1019
  { timeout: 30000 },