@malloy-publisher/server 0.0.195 → 0.0.196

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 (104) 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 +1976 -1322
  16. package/package.json +2 -2
  17. package/publisher.config.json +2 -2
  18. package/src/config.spec.ts +181 -66
  19. package/src/config.ts +68 -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 +1119 -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 -83
  58. package/src/service/{project_store.ts → environment_store.ts} +373 -327
  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 +4 -4
  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 +64 -28
  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 +61 -20
  82. package/src/storage/ducklake/DuckLakeManifestStore.ts +20 -11
  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 +12 -24
  86. package/tests/harness/mocks.ts +10 -8
  87. package/tests/harness/rest_e2e.ts +2 -2
  88. package/tests/integration/legacy_routes/legacy_routes.integration.spec.ts +259 -0
  89. package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
  90. package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +28 -49
  91. package/tests/integration/mcp/mcp_resource.integration.spec.ts +39 -47
  92. package/tests/integration/mcp/mcp_transport.integration.spec.ts +1 -1
  93. package/tests/unit/duckdb/attached_databases.test.ts +51 -33
  94. package/tests/unit/duckdb/legacy_schema_migration.test.ts +194 -0
  95. package/tests/unit/ducklake/ducklake.test.ts +24 -22
  96. package/tests/unit/mcp/prompt_happy.test.ts +8 -8
  97. package/dist/app/assets/HomePage-DbZS0N7G.js +0 -1
  98. package/dist/app/assets/MainPage-CBuWkbmr.js +0 -2
  99. package/dist/app/assets/ModelPage-Bt37smot.js +0 -1
  100. package/dist/app/assets/PackagePage-DLZe50WG.js +0 -1
  101. package/dist/app/assets/ProjectPage-FQTEPXP4.js +0 -1
  102. package/dist/app/assets/WorkbookPage-CkAo16ar.js +0 -1
  103. package/src/mcp/resources/project_resource.ts +0 -184
  104. package/src/service/resolve_project.ts +0 -13
@@ -7,12 +7,12 @@ import {
7
7
  ResourceRepository,
8
8
  } from "../storage/DatabaseInterface";
9
9
  import { ManifestService } from "./manifest_service";
10
- import { ProjectStore } from "./project_store";
10
+ import { EnvironmentStore } from "./environment_store";
11
11
 
12
12
  function makeEntry(overrides: Partial<ManifestEntry> = {}): ManifestEntry {
13
13
  return {
14
14
  id: "entry-1",
15
- projectId: "proj-1",
15
+ environmentId: "proj-1",
16
16
  packageName: "pkg",
17
17
  buildId: "build-abc",
18
18
  tableName: "my_table",
@@ -44,26 +44,26 @@ function createMocks() {
44
44
  reloadAllModels,
45
45
  };
46
46
 
47
- const project = {
47
+ const environment = {
48
48
  getPackage: sandbox.stub().resolves(pkg),
49
49
  };
50
50
 
51
- const projectStore = {
51
+ const environmentStore = {
52
52
  storageManager: {
53
- getManifestStore: (_projectId?: string) => manifestStore,
53
+ getManifestStore: (_environmentId?: string) => manifestStore,
54
54
  getRepository: () => repository,
55
55
  },
56
- getProject: sandbox.stub().resolves(project),
57
- } as unknown as ProjectStore;
56
+ getEnvironment: sandbox.stub().resolves(environment),
57
+ } as unknown as EnvironmentStore;
58
58
 
59
- const service = new ManifestService(projectStore);
59
+ const service = new ManifestService(environmentStore);
60
60
 
61
61
  return {
62
62
  sandbox,
63
63
  manifestStore,
64
64
  repository,
65
- projectStore,
66
- project,
65
+ environmentStore,
66
+ environment,
67
67
  pkg,
68
68
  reloadAllModels,
69
69
  service,
@@ -142,17 +142,17 @@ describe("ManifestService", () => {
142
142
  const result = await ctx.service.reloadManifest(
143
143
  "proj-1",
144
144
  "pkg",
145
- "my-project",
145
+ "my-environment",
146
146
  );
147
147
 
148
148
  expect(result).toEqual(manifest);
149
149
  expect(
150
- (ctx.projectStore.getProject as sinon.SinonStub).calledWith(
151
- "my-project",
150
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).calledWith(
151
+ "my-environment",
152
152
  false,
153
153
  ),
154
154
  ).toBe(true);
155
- expect(ctx.project.getPackage.calledWith("pkg", false)).toBe(true);
155
+ expect(ctx.environment.getPackage.calledWith("pkg", false)).toBe(true);
156
156
  expect(ctx.reloadAllModels.calledWith(manifest.entries)).toBe(true);
157
157
  });
158
158
 
@@ -166,7 +166,7 @@ describe("ManifestService", () => {
166
166
  const result = await ctx.service.reloadManifest(
167
167
  "proj-1",
168
168
  "pkg",
169
- "my-project",
169
+ "my-environment",
170
170
  );
171
171
 
172
172
  expect(result.entries).toEqual({});
@@ -4,7 +4,7 @@ import {
4
4
  ManifestEntry,
5
5
  ManifestStore,
6
6
  } from "../storage/DatabaseInterface";
7
- import { ProjectStore } from "./project_store";
7
+ import { EnvironmentStore } from "./environment_store";
8
8
 
9
9
  /**
10
10
  * Manages build manifests that map source names to materialized table names.
@@ -23,32 +23,34 @@ import { ProjectStore } from "./project_store";
23
23
  * is either the local DuckDB store (standalone) or DuckLake (orchestrated).
24
24
  */
25
25
  export class ManifestService {
26
- constructor(private projectStore: ProjectStore) {}
26
+ constructor(private environmentStore: EnvironmentStore) {}
27
27
 
28
- private manifestStoreFor(projectId: string): ManifestStore {
29
- return this.projectStore.storageManager.getManifestStore(projectId);
28
+ private manifestStoreFor(environmentId: string): ManifestStore {
29
+ return this.environmentStore.storageManager.getManifestStore(
30
+ environmentId,
31
+ );
30
32
  }
31
33
 
32
34
  async getManifest(
33
- projectId: string,
35
+ environmentId: string,
34
36
  packageName: string,
35
37
  ): Promise<BuildManifest> {
36
- return this.manifestStoreFor(projectId).getManifest(
37
- projectId,
38
+ return this.manifestStoreFor(environmentId).getManifest(
39
+ environmentId,
38
40
  packageName,
39
41
  );
40
42
  }
41
43
 
42
44
  async writeEntry(
43
- projectId: string,
45
+ environmentId: string,
44
46
  packageName: string,
45
47
  buildId: string,
46
48
  tableName: string,
47
49
  sourceName: string,
48
50
  connectionName: string,
49
51
  ): Promise<void> {
50
- await this.manifestStoreFor(projectId).writeEntry(
51
- projectId,
52
+ await this.manifestStoreFor(environmentId).writeEntry(
53
+ environmentId,
52
54
  packageName,
53
55
  buildId,
54
56
  tableName,
@@ -57,8 +59,8 @@ export class ManifestService {
57
59
  );
58
60
  }
59
61
 
60
- async deleteEntry(projectId: string, entryId: string): Promise<void> {
61
- await this.manifestStoreFor(projectId).deleteEntry(entryId);
62
+ async deleteEntry(environmentId: string, entryId: string): Promise<void> {
63
+ await this.manifestStoreFor(environmentId).deleteEntry(entryId);
62
64
  }
63
65
 
64
66
  /**
@@ -70,18 +72,21 @@ export class ManifestService {
70
72
  * storage — the worker pulls the manifest down and recompiles.
71
73
  */
72
74
  async reloadManifest(
73
- projectId: string,
75
+ environmentId: string,
74
76
  packageName: string,
75
- projectName: string,
77
+ environmentName: string,
76
78
  ): Promise<BuildManifest> {
77
- const manifest = await this.getManifest(projectId, packageName);
79
+ const manifest = await this.getManifest(environmentId, packageName);
78
80
 
79
- const project = await this.projectStore.getProject(projectName, false);
80
- const pkg = await project.getPackage(packageName, false);
81
+ const environment = await this.environmentStore.getEnvironment(
82
+ environmentName,
83
+ false,
84
+ );
85
+ const pkg = await environment.getPackage(packageName, false);
81
86
  await pkg.reloadAllModels(manifest.entries);
82
87
 
83
88
  logger.info("Reloaded manifest and recompiled models", {
84
- projectId,
89
+ environmentId,
85
90
  packageName,
86
91
  entryCount: Object.keys(manifest.entries).length,
87
92
  });
@@ -95,11 +100,11 @@ export class ManifestService {
95
100
  * catalog instead of the local DuckDB table.
96
101
  */
97
102
  async listEntries(
98
- projectId: string,
103
+ environmentId: string,
99
104
  packageName: string,
100
105
  ): Promise<ManifestEntry[]> {
101
- return this.manifestStoreFor(projectId).listEntries(
102
- projectId,
106
+ return this.manifestStoreFor(environmentId).listEntries(
107
+ environmentId,
103
108
  packageName,
104
109
  );
105
110
  }
@@ -2,32 +2,32 @@ import type { Connection } from "@malloydata/malloy";
2
2
  import { beforeEach, describe, expect, it } from "bun:test";
3
3
  import * as sinon from "sinon";
4
4
  import {
5
+ EnvironmentNotFoundError,
5
6
  InvalidStateTransitionError,
6
7
  MaterializationConflictError,
7
8
  MaterializationNotFoundError,
8
- ProjectNotFoundError,
9
9
  } from "../errors";
10
- import { DuplicateActiveMaterializationError } from "../storage/duckdb/MaterializationRepository";
11
10
  import {
12
11
  ManifestEntry,
13
12
  Materialization,
14
13
  MaterializationStatus,
15
14
  ResourceRepository,
16
15
  } from "../storage/DatabaseInterface";
16
+ import { DuplicateActiveMaterializationError } from "../storage/duckdb/MaterializationRepository";
17
+ import { EnvironmentStore } from "./environment_store";
17
18
  import { ManifestService } from "./manifest_service";
18
19
  import {
19
20
  manifestTableKey,
20
21
  MaterializationService,
21
22
  tablePhysicallyExists,
22
23
  } from "./materialization_service";
23
- import { ProjectStore } from "./project_store";
24
24
 
25
25
  function makeExecution(
26
26
  overrides: Partial<Materialization> = {},
27
27
  ): Materialization {
28
28
  return {
29
29
  id: "exec-1",
30
- projectId: "proj-1",
30
+ environmentId: "proj-1",
31
31
  packageName: "pkg",
32
32
  status: "PENDING",
33
33
  startedAt: null,
@@ -46,12 +46,12 @@ function createMocks() {
46
46
  const sandbox = sinon.createSandbox();
47
47
 
48
48
  const repository: MockRepo = {
49
- listProjects: sandbox.stub(),
50
- getProjectById: sandbox.stub(),
51
- getProjectByName: sandbox.stub(),
52
- createProject: sandbox.stub(),
53
- updateProject: sandbox.stub(),
54
- deleteProject: sandbox.stub(),
49
+ listEnvironments: sandbox.stub(),
50
+ getEnvironmentById: sandbox.stub(),
51
+ getEnvironmentByName: sandbox.stub(),
52
+ createEnvironment: sandbox.stub(),
53
+ updateEnvironment: sandbox.stub(),
54
+ deleteEnvironment: sandbox.stub(),
55
55
  listPackages: sandbox.stub(),
56
56
  getPackageById: sandbox.stub(),
57
57
  getPackageByName: sandbox.stub(),
@@ -80,10 +80,10 @@ function createMocks() {
80
80
  getManifestStore: sandbox.stub(),
81
81
  };
82
82
 
83
- const projectStore = {
83
+ const environmentStore = {
84
84
  storageManager,
85
- getProject: sandbox.stub(),
86
- } as unknown as ProjectStore;
85
+ getEnvironment: sandbox.stub(),
86
+ } as unknown as EnvironmentStore;
87
87
 
88
88
  const manifestService = {
89
89
  getManifest: sandbox.stub().resolves({ entries: {}, strict: false }),
@@ -94,20 +94,20 @@ function createMocks() {
94
94
  } as unknown as sinon.SinonStubbedInstance<ManifestService>;
95
95
 
96
96
  const service = new MaterializationService(
97
- projectStore,
97
+ environmentStore,
98
98
  manifestService as unknown as ManifestService,
99
99
  );
100
100
 
101
- // Default: resolveProjectId succeeds
102
- repository.getProjectByName.resolves({
101
+ // Default: resolveEnvironmentId succeeds
102
+ repository.getEnvironmentByName.resolves({
103
103
  id: "proj-1",
104
- name: "my-project",
104
+ name: "my-environment",
105
105
  path: "/test",
106
106
  createdAt: new Date(),
107
107
  updatedAt: new Date(),
108
108
  });
109
109
 
110
- return { sandbox, repository, projectStore, manifestService, service };
110
+ return { sandbox, repository, environmentStore, manifestService, service };
111
111
  }
112
112
 
113
113
  describe("MaterializationService", () => {
@@ -117,15 +117,15 @@ describe("MaterializationService", () => {
117
117
  ctx = createMocks();
118
118
  });
119
119
 
120
- // ==================== resolveProjectId ====================
120
+ // ==================== resolveEnvironmentId ====================
121
121
 
122
- describe("resolveProjectId (via listMaterializations)", () => {
123
- it("should throw ProjectNotFoundError when project is not in DB", async () => {
124
- ctx.repository.getProjectByName.resolves(null);
122
+ describe("resolveEnvironmentId (via listMaterializations)", () => {
123
+ it("should throw EnvironmentNotFoundError when environment is not in DB", async () => {
124
+ ctx.repository.getEnvironmentByName.resolves(null);
125
125
 
126
126
  await expect(
127
127
  ctx.service.listMaterializations("unknown", "pkg"),
128
- ).rejects.toThrow(ProjectNotFoundError);
128
+ ).rejects.toThrow(EnvironmentNotFoundError);
129
129
  });
130
130
  });
131
131
 
@@ -137,7 +137,7 @@ describe("MaterializationService", () => {
137
137
  ctx.repository.listMaterializations.resolves(builds);
138
138
 
139
139
  const result = await ctx.service.listMaterializations(
140
- "my-project",
140
+ "my-environment",
141
141
  "pkg",
142
142
  );
143
143
 
@@ -151,7 +151,7 @@ describe("MaterializationService", () => {
151
151
  ctx.repository.getMaterializationById.resolves(exec);
152
152
 
153
153
  const result = await ctx.service.getMaterialization(
154
- "my-project",
154
+ "my-environment",
155
155
  "pkg",
156
156
  "exec-1",
157
157
  );
@@ -163,7 +163,7 @@ describe("MaterializationService", () => {
163
163
  ctx.repository.getMaterializationById.resolves(null);
164
164
 
165
165
  await expect(
166
- ctx.service.getMaterialization("my-project", "pkg", "missing"),
166
+ ctx.service.getMaterialization("my-environment", "pkg", "missing"),
167
167
  ).rejects.toThrow(MaterializationNotFoundError);
168
168
  });
169
169
 
@@ -173,7 +173,7 @@ describe("MaterializationService", () => {
173
173
  );
174
174
 
175
175
  await expect(
176
- ctx.service.getMaterialization("my-project", "pkg", "exec-1"),
176
+ ctx.service.getMaterialization("my-environment", "pkg", "exec-1"),
177
177
  ).rejects.toThrow(MaterializationNotFoundError);
178
178
  });
179
179
  });
@@ -216,7 +216,7 @@ describe("MaterializationService", () => {
216
216
  // Trigger via stopMaterialization for RUNNING->CANCELLED (orphaned path)
217
217
  if (from === "RUNNING" && to === "CANCELLED") {
218
218
  const result = await ctx.service.stopMaterialization(
219
- "my-project",
219
+ "my-environment",
220
220
  "pkg",
221
221
  exec.id,
222
222
  );
@@ -242,7 +242,7 @@ describe("MaterializationService", () => {
242
242
 
243
243
  describe("createMaterialization", () => {
244
244
  it("should create a PENDING build", async () => {
245
- (ctx.projectStore.getProject as sinon.SinonStub).resolves({
245
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).resolves({
246
246
  getPackage: sinon.stub().resolves({}),
247
247
  });
248
248
  ctx.repository.getActiveMaterialization.resolves(null);
@@ -253,7 +253,7 @@ describe("MaterializationService", () => {
253
253
  ctx.repository.createMaterialization.resolves(pending);
254
254
 
255
255
  const result = await ctx.service.createMaterialization(
256
- "my-project",
256
+ "my-environment",
257
257
  "pkg",
258
258
  {
259
259
  autoLoadManifest: true,
@@ -276,7 +276,7 @@ describe("MaterializationService", () => {
276
276
  });
277
277
 
278
278
  it("should reject creation when an active materialization exists", async () => {
279
- (ctx.projectStore.getProject as sinon.SinonStub).resolves({
279
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).resolves({
280
280
  getPackage: sinon.stub().resolves({}),
281
281
  });
282
282
  ctx.repository.getActiveMaterialization.resolves(
@@ -284,12 +284,12 @@ describe("MaterializationService", () => {
284
284
  );
285
285
 
286
286
  await expect(
287
- ctx.service.createMaterialization("my-project", "pkg"),
287
+ ctx.service.createMaterialization("my-environment", "pkg"),
288
288
  ).rejects.toThrow(MaterializationConflictError);
289
289
  });
290
290
 
291
291
  it("should translate DuplicateActiveMaterializationError from a lost race", async () => {
292
- (ctx.projectStore.getProject as sinon.SinonStub).resolves({
292
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).resolves({
293
293
  getPackage: sinon.stub().resolves({}),
294
294
  });
295
295
  // The pre-check finds nothing (race is still possible), but the
@@ -305,7 +305,7 @@ describe("MaterializationService", () => {
305
305
  );
306
306
 
307
307
  await expect(
308
- ctx.service.createMaterialization("my-project", "pkg"),
308
+ ctx.service.createMaterialization("my-environment", "pkg"),
309
309
  ).rejects.toThrow(/winner/);
310
310
  });
311
311
  });
@@ -322,7 +322,7 @@ describe("MaterializationService", () => {
322
322
  ctx.repository.updateMaterialization.resolves(running);
323
323
 
324
324
  const result = await ctx.service.startMaterialization(
325
- "my-project",
325
+ "my-environment",
326
326
  "pkg",
327
327
  "exec-1",
328
328
  );
@@ -335,7 +335,7 @@ describe("MaterializationService", () => {
335
335
  ctx.repository.getMaterializationById.resolves(running);
336
336
 
337
337
  await expect(
338
- ctx.service.startMaterialization("my-project", "pkg", "exec-1"),
338
+ ctx.service.startMaterialization("my-environment", "pkg", "exec-1"),
339
339
  ).rejects.toThrow(InvalidStateTransitionError);
340
340
  });
341
341
 
@@ -350,7 +350,7 @@ describe("MaterializationService", () => {
350
350
  );
351
351
 
352
352
  await expect(
353
- ctx.service.startMaterialization("my-project", "pkg", "exec-1"),
353
+ ctx.service.startMaterialization("my-environment", "pkg", "exec-1"),
354
354
  ).rejects.toThrow(MaterializationConflictError);
355
355
  });
356
356
  });
@@ -364,7 +364,7 @@ describe("MaterializationService", () => {
364
364
  );
365
365
 
366
366
  const result = await ctx.service.stopMaterialization(
367
- "my-project",
367
+ "my-environment",
368
368
  "pkg",
369
369
  "exec-1",
370
370
  );
@@ -380,7 +380,7 @@ describe("MaterializationService", () => {
380
380
  );
381
381
 
382
382
  const result = await ctx.service.stopMaterialization(
383
- "my-project",
383
+ "my-environment",
384
384
  "pkg",
385
385
  "orphan",
386
386
  );
@@ -393,7 +393,7 @@ describe("MaterializationService", () => {
393
393
  ctx.repository.getMaterializationById.resolves(succeeded);
394
394
 
395
395
  await expect(
396
- ctx.service.stopMaterialization("my-project", "pkg", "exec-1"),
396
+ ctx.service.stopMaterialization("my-environment", "pkg", "exec-1"),
397
397
  ).rejects.toThrow(InvalidStateTransitionError);
398
398
  });
399
399
  });
@@ -406,7 +406,11 @@ describe("MaterializationService", () => {
406
406
  ctx.repository.getMaterializationById.resolves(succeeded);
407
407
  ctx.repository.deleteMaterialization.resolves();
408
408
 
409
- await ctx.service.deleteMaterialization("my-project", "pkg", "exec-1");
409
+ await ctx.service.deleteMaterialization(
410
+ "my-environment",
411
+ "pkg",
412
+ "exec-1",
413
+ );
410
414
 
411
415
  expect(ctx.repository.deleteMaterialization.calledOnce).toBe(true);
412
416
  expect(ctx.repository.deleteMaterialization.firstCall.args[0]).toBe(
@@ -419,7 +423,11 @@ describe("MaterializationService", () => {
419
423
  ctx.repository.getMaterializationById.resolves(failed);
420
424
  ctx.repository.deleteMaterialization.resolves();
421
425
 
422
- await ctx.service.deleteMaterialization("my-project", "pkg", "exec-1");
426
+ await ctx.service.deleteMaterialization(
427
+ "my-environment",
428
+ "pkg",
429
+ "exec-1",
430
+ );
423
431
 
424
432
  expect(ctx.repository.deleteMaterialization.calledOnce).toBe(true);
425
433
  });
@@ -429,7 +437,11 @@ describe("MaterializationService", () => {
429
437
  ctx.repository.getMaterializationById.resolves(cancelled);
430
438
  ctx.repository.deleteMaterialization.resolves();
431
439
 
432
- await ctx.service.deleteMaterialization("my-project", "pkg", "exec-1");
440
+ await ctx.service.deleteMaterialization(
441
+ "my-environment",
442
+ "pkg",
443
+ "exec-1",
444
+ );
433
445
 
434
446
  expect(ctx.repository.deleteMaterialization.calledOnce).toBe(true);
435
447
  });
@@ -439,7 +451,11 @@ describe("MaterializationService", () => {
439
451
  ctx.repository.getMaterializationById.resolves(pending);
440
452
 
441
453
  await expect(
442
- ctx.service.deleteMaterialization("my-project", "pkg", "exec-1"),
454
+ ctx.service.deleteMaterialization(
455
+ "my-environment",
456
+ "pkg",
457
+ "exec-1",
458
+ ),
443
459
  ).rejects.toThrow(InvalidStateTransitionError);
444
460
  });
445
461
 
@@ -448,7 +464,11 @@ describe("MaterializationService", () => {
448
464
  ctx.repository.getMaterializationById.resolves(running);
449
465
 
450
466
  await expect(
451
- ctx.service.deleteMaterialization("my-project", "pkg", "exec-1"),
467
+ ctx.service.deleteMaterialization(
468
+ "my-environment",
469
+ "pkg",
470
+ "exec-1",
471
+ ),
452
472
  ).rejects.toThrow(InvalidStateTransitionError);
453
473
  });
454
474
 
@@ -456,7 +476,11 @@ describe("MaterializationService", () => {
456
476
  ctx.repository.getMaterializationById.resolves(null);
457
477
 
458
478
  await expect(
459
- ctx.service.deleteMaterialization("my-project", "pkg", "missing"),
479
+ ctx.service.deleteMaterialization(
480
+ "my-environment",
481
+ "pkg",
482
+ "missing",
483
+ ),
460
484
  ).rejects.toThrow(MaterializationNotFoundError);
461
485
  });
462
486
  });
@@ -470,7 +494,7 @@ describe("MaterializationService", () => {
470
494
  );
471
495
 
472
496
  await expect(
473
- ctx.service.teardownPackage("my-project", "pkg"),
497
+ ctx.service.teardownPackage("my-environment", "pkg"),
474
498
  ).rejects.toThrow(MaterializationConflictError);
475
499
  });
476
500
 
@@ -486,14 +510,14 @@ describe("MaterializationService", () => {
486
510
  throw new Error(`unknown connection: ${name}`);
487
511
  },
488
512
  };
489
- (ctx.projectStore.getProject as sinon.SinonStub).resolves({
513
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).resolves({
490
514
  getPackage: sinon.stub().resolves(pkg),
491
515
  });
492
516
  ctx.repository.getActiveMaterialization.resolves(null);
493
517
  const entries: ManifestEntry[] = [
494
518
  {
495
519
  id: "entry-1",
496
- projectId: "proj-1",
520
+ environmentId: "proj-1",
497
521
  packageName: "pkg",
498
522
  buildId: "abcdef1234567890abcdef1234567890",
499
523
  tableName: "table_a",
@@ -504,7 +528,7 @@ describe("MaterializationService", () => {
504
528
  },
505
529
  {
506
530
  id: "entry-2",
507
- projectId: "proj-1",
531
+ environmentId: "proj-1",
508
532
  packageName: "pkg",
509
533
  buildId: "1234567890abcdef1234567890abcdef",
510
534
  tableName: "table_b",
@@ -516,7 +540,10 @@ describe("MaterializationService", () => {
516
540
  ];
517
541
  (ctx.manifestService.listEntries as sinon.SinonStub).resolves(entries);
518
542
 
519
- const result = await ctx.service.teardownPackage("my-project", "pkg");
543
+ const result = await ctx.service.teardownPackage(
544
+ "my-environment",
545
+ "pkg",
546
+ );
520
547
 
521
548
  expect(result.dropped).toHaveLength(2);
522
549
  expect(result.errors).toHaveLength(0);
@@ -543,14 +570,14 @@ describe("MaterializationService", () => {
543
570
  throw new Error(`unknown connection: ${name}`);
544
571
  },
545
572
  };
546
- (ctx.projectStore.getProject as sinon.SinonStub).resolves({
573
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).resolves({
547
574
  getPackage: sinon.stub().resolves(pkg),
548
575
  });
549
576
  ctx.repository.getActiveMaterialization.resolves(null);
550
577
  const entries: ManifestEntry[] = [
551
578
  {
552
579
  id: "entry-ghost",
553
- projectId: "proj-1",
580
+ environmentId: "proj-1",
554
581
  packageName: "pkg",
555
582
  buildId: "abcdef1234567890abcdef1234567890",
556
583
  tableName: "table_ghost",
@@ -562,7 +589,10 @@ describe("MaterializationService", () => {
562
589
  ];
563
590
  (ctx.manifestService.listEntries as sinon.SinonStub).resolves(entries);
564
591
 
565
- const result = await ctx.service.teardownPackage("my-project", "pkg");
592
+ const result = await ctx.service.teardownPackage(
593
+ "my-environment",
594
+ "pkg",
595
+ );
566
596
 
567
597
  expect(result.dropped).toHaveLength(1);
568
598
  expect(result.dropped[0].targetDropSkipped).toBe(true);
@@ -586,13 +616,13 @@ describe("MaterializationService", () => {
586
616
  throw new Error(`unknown connection: ${name}`);
587
617
  },
588
618
  };
589
- (ctx.projectStore.getProject as sinon.SinonStub).resolves({
619
+ (ctx.environmentStore.getEnvironment as sinon.SinonStub).resolves({
590
620
  getPackage: sinon.stub().resolves(pkg),
591
621
  });
592
622
  ctx.repository.getActiveMaterialization.resolves(null);
593
623
  const entry: ManifestEntry = {
594
624
  id: "entry-1",
595
- projectId: "proj-1",
625
+ environmentId: "proj-1",
596
626
  packageName: "pkg",
597
627
  buildId: "abcdef1234567890abcdef1234567890",
598
628
  tableName: "orphan",
@@ -603,9 +633,13 @@ describe("MaterializationService", () => {
603
633
  };
604
634
  (ctx.manifestService.listEntries as sinon.SinonStub).resolves([entry]);
605
635
 
606
- const result = await ctx.service.teardownPackage("my-project", "pkg", {
607
- dryRun: true,
608
- });
636
+ const result = await ctx.service.teardownPackage(
637
+ "my-environment",
638
+ "pkg",
639
+ {
640
+ dryRun: true,
641
+ },
642
+ );
609
643
 
610
644
  expect(result.dropped).toHaveLength(1);
611
645
  expect(result.dropped[0].tableName).toBe("orphan");