@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.
- package/dist/app/api-doc.yaml +213 -214
- package/dist/app/assets/EnvironmentPage-1j6QDWAy.js +1 -0
- package/dist/app/assets/HomePage-DMop21VG.js +1 -0
- package/dist/app/assets/MainPage-BbE8ETz1.js +2 -0
- package/dist/app/assets/ModelPage-D2jvfe3t.js +1 -0
- package/dist/app/assets/PackagePage-BbnhGoD3.js +1 -0
- package/dist/app/assets/{RouteError-DefbDO7F.js → RouteError-D3LGEZ3i.js} +1 -1
- package/dist/app/assets/WorkbookPage-DttVIj4u.js +1 -0
- package/dist/app/assets/{core-BrfQApxh.es-DnvCX4oH.js → core-w79IMXAG.es-Bd0UlzOL.js} +1 -1
- package/dist/app/assets/{index-Bu0ub036.js → index-5K9YjIxF.js} +117 -117
- package/dist/app/assets/{index-CkzK3JIl.js → index-C513UodQ.js} +1 -1
- package/dist/app/assets/{index-CoA6HIGS.js → index-DIgzgp69.js} +1 -1
- package/dist/app/assets/{index.umd-B6Ms2PpL.js → index.umd-BMeMPq_9.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/server.mjs +1947 -1317
- package/package.json +1 -1
- package/publisher.config.json +2 -2
- package/src/config.spec.ts +74 -66
- package/src/config.ts +50 -47
- package/src/controller/compile.controller.ts +10 -7
- package/src/controller/connection.controller.ts +79 -58
- package/src/controller/database.controller.ts +10 -7
- package/src/controller/manifest.controller.ts +23 -14
- package/src/controller/materialization.controller.ts +14 -14
- package/src/controller/model.controller.ts +35 -20
- package/src/controller/package.controller.ts +83 -49
- package/src/controller/query.controller.ts +11 -8
- package/src/controller/watch-mode.controller.ts +35 -29
- package/src/errors.ts +2 -2
- package/src/mcp/error_messages.ts +2 -2
- package/src/mcp/handler_utils.ts +23 -20
- package/src/mcp/mcp_constants.ts +1 -1
- package/src/mcp/prompts/handlers.ts +3 -3
- package/src/mcp/prompts/prompt_service.ts +5 -5
- package/src/mcp/prompts/utils.ts +12 -12
- package/src/mcp/resource_metadata.ts +3 -3
- package/src/mcp/resources/environment_resource.ts +187 -0
- package/src/mcp/resources/model_resource.ts +19 -17
- package/src/mcp/resources/notebook_resource.ts +13 -13
- package/src/mcp/resources/package_resource.ts +30 -27
- package/src/mcp/resources/query_resource.ts +15 -10
- package/src/mcp/resources/source_resource.ts +10 -10
- package/src/mcp/resources/view_resource.ts +11 -11
- package/src/mcp/server.ts +16 -14
- package/src/mcp/tools/discovery_tools.ts +67 -49
- package/src/mcp/tools/execute_query_tool.ts +14 -14
- package/src/server-old.ts +1139 -0
- package/src/server.ts +191 -159
- package/src/service/connection.spec.ts +158 -133
- package/src/service/connection.ts +42 -39
- package/src/service/connection_config.spec.ts +13 -11
- package/src/service/connection_config.ts +28 -19
- package/src/service/connection_service.spec.ts +63 -43
- package/src/service/connection_service.ts +106 -89
- package/src/service/{project.ts → environment.ts} +92 -77
- package/src/service/{project_compile.spec.ts → environment_compile.spec.ts} +1 -1
- package/src/service/{project_store.spec.ts → environment_store.spec.ts} +99 -85
- package/src/service/{project_store.ts → environment_store.ts} +368 -326
- package/src/service/manifest_service.spec.ts +15 -15
- package/src/service/manifest_service.ts +26 -21
- package/src/service/materialization_service.spec.ts +93 -59
- package/src/service/materialization_service.ts +71 -62
- package/src/service/materialized_table_gc.spec.ts +15 -15
- package/src/service/materialized_table_gc.ts +3 -3
- package/src/service/model.ts +2 -2
- package/src/service/package.spec.ts +2 -2
- package/src/service/package.ts +23 -21
- package/src/service/resolve_environment.ts +15 -0
- package/src/storage/DatabaseInterface.ts +34 -25
- package/src/storage/StorageManager.mock.ts +3 -3
- package/src/storage/StorageManager.ts +24 -23
- package/src/storage/duckdb/ConnectionRepository.ts +13 -11
- package/src/storage/duckdb/DuckDBConnection.ts +1 -1
- package/src/storage/duckdb/DuckDBManifestStore.ts +6 -6
- package/src/storage/duckdb/DuckDBRepository.ts +47 -47
- package/src/storage/duckdb/{ProjectRepository.ts → EnvironmentRepository.ts} +35 -35
- package/src/storage/duckdb/ManifestRepository.ts +21 -20
- package/src/storage/duckdb/MaterializationRepository.ts +31 -28
- package/src/storage/duckdb/PackageRepository.ts +11 -11
- package/src/storage/duckdb/manifest_store.spec.ts +2 -2
- package/src/storage/duckdb/schema.ts +20 -20
- package/src/storage/ducklake/DuckLakeManifestStore.ts +14 -14
- package/tests/fixtures/publisher.config.json +1 -1
- package/tests/harness/e2e.ts +1 -1
- package/tests/harness/mcp_test_setup.ts +1 -1
- package/tests/harness/mocks.ts +10 -8
- package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +4 -4
- package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +27 -48
- package/tests/integration/mcp/mcp_resource.integration.spec.ts +26 -35
- package/tests/unit/duckdb/attached_databases.test.ts +51 -33
- package/tests/unit/ducklake/ducklake.test.ts +24 -22
- package/tests/unit/mcp/prompt_happy.test.ts +8 -8
- package/dist/app/assets/HomePage-DbZS0N7G.js +0 -1
- package/dist/app/assets/MainPage-CBuWkbmr.js +0 -2
- package/dist/app/assets/ModelPage-Bt37smot.js +0 -1
- package/dist/app/assets/PackagePage-DLZe50WG.js +0 -1
- package/dist/app/assets/ProjectPage-FQTEPXP4.js +0 -1
- package/dist/app/assets/WorkbookPage-CkAo16ar.js +0 -1
- package/src/mcp/resources/project_resource.ts +0 -184
- package/src/service/resolve_project.ts +0 -13
|
@@ -1,28 +1,28 @@
|
|
|
1
1
|
import { afterEach, beforeEach, describe, expect, it } from "bun:test";
|
|
2
2
|
import sinon from "sinon";
|
|
3
|
-
import { FrozenConfigError, ConnectionNotFoundError } from "../errors";
|
|
4
|
-
import { ConnectionService } from "./connection_service";
|
|
5
|
-
import { ProjectStore } from "./project_store";
|
|
6
3
|
import { components } from "../api";
|
|
4
|
+
import { ConnectionNotFoundError, FrozenConfigError } from "../errors";
|
|
5
|
+
import { ConnectionService } from "./connection_service";
|
|
6
|
+
import { EnvironmentStore } from "./environment_store";
|
|
7
7
|
|
|
8
8
|
type ApiConnection = components["schemas"]["Connection"];
|
|
9
9
|
|
|
10
10
|
describe("service/connection_service", () => {
|
|
11
11
|
let connectionService: ConnectionService;
|
|
12
|
-
let
|
|
12
|
+
let mockEnvironmentStore: Record<string, unknown>;
|
|
13
13
|
let mockRepository: Record<string, unknown>;
|
|
14
14
|
|
|
15
15
|
beforeEach(() => {
|
|
16
16
|
mockRepository = {
|
|
17
|
-
|
|
17
|
+
getEnvironmentByName: sinon.stub(),
|
|
18
18
|
getConnectionByName: sinon.stub(),
|
|
19
19
|
deleteConnection: sinon.stub(),
|
|
20
20
|
};
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
mockEnvironmentStore = {
|
|
23
23
|
finishedInitialization: Promise.resolve(),
|
|
24
24
|
publisherConfigIsFrozen: false,
|
|
25
|
-
|
|
25
|
+
getEnvironment: sinon.stub(),
|
|
26
26
|
updateConnection: sinon.stub(),
|
|
27
27
|
addConnection: sinon.stub(),
|
|
28
28
|
storageManager: {
|
|
@@ -31,7 +31,7 @@ describe("service/connection_service", () => {
|
|
|
31
31
|
};
|
|
32
32
|
|
|
33
33
|
connectionService = new ConnectionService(
|
|
34
|
-
|
|
34
|
+
mockEnvironmentStore as unknown as EnvironmentStore,
|
|
35
35
|
);
|
|
36
36
|
});
|
|
37
37
|
|
|
@@ -51,7 +51,7 @@ describe("service/connection_service", () => {
|
|
|
51
51
|
|
|
52
52
|
const mockDbConnection = {
|
|
53
53
|
id: "conn-123",
|
|
54
|
-
|
|
54
|
+
environmentId: "project-123",
|
|
55
55
|
name: "test-connection",
|
|
56
56
|
type: "postgres" as const,
|
|
57
57
|
config: {},
|
|
@@ -66,7 +66,7 @@ describe("service/connection_service", () => {
|
|
|
66
66
|
},
|
|
67
67
|
};
|
|
68
68
|
|
|
69
|
-
(mockRepository.
|
|
69
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
70
70
|
mockDbProject,
|
|
71
71
|
);
|
|
72
72
|
(mockRepository.getConnectionByName as sinon.SinonStub).resolves(
|
|
@@ -78,17 +78,19 @@ describe("service/connection_service", () => {
|
|
|
78
78
|
"test-connection",
|
|
79
79
|
);
|
|
80
80
|
|
|
81
|
-
expect(result.
|
|
81
|
+
expect(result.dbEnvironment).toEqual(mockDbProject);
|
|
82
82
|
expect(result.dbConnection).toEqual(mockDbConnection);
|
|
83
83
|
expect(result.repository).toBeDefined();
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
it("should throw error when project not found", async () => {
|
|
87
|
-
(mockRepository.
|
|
87
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
88
|
+
null,
|
|
89
|
+
);
|
|
88
90
|
|
|
89
91
|
await expect(
|
|
90
92
|
connectionService.getConnection("non-existent", "test-connection"),
|
|
91
|
-
).rejects.toThrow('
|
|
93
|
+
).rejects.toThrow('Environment "non-existent" not found in database');
|
|
92
94
|
});
|
|
93
95
|
|
|
94
96
|
it("should throw ConnectionNotFoundError when connection not found", async () => {
|
|
@@ -100,7 +102,7 @@ describe("service/connection_service", () => {
|
|
|
100
102
|
updatedAt: new Date(),
|
|
101
103
|
};
|
|
102
104
|
|
|
103
|
-
(mockRepository.
|
|
105
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
104
106
|
mockDbProject,
|
|
105
107
|
);
|
|
106
108
|
(mockRepository.getConnectionByName as sinon.SinonStub).resolves(null);
|
|
@@ -139,11 +141,13 @@ describe("service/connection_service", () => {
|
|
|
139
141
|
metadata: { location: "/test/path" },
|
|
140
142
|
};
|
|
141
143
|
|
|
142
|
-
(mockRepository.
|
|
144
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
143
145
|
mockDbProject,
|
|
144
146
|
);
|
|
145
147
|
(mockRepository.getConnectionByName as sinon.SinonStub).resolves(null);
|
|
146
|
-
(
|
|
148
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
149
|
+
mockProject,
|
|
150
|
+
);
|
|
147
151
|
|
|
148
152
|
await connectionService.addConnection(
|
|
149
153
|
"test-project",
|
|
@@ -152,13 +156,13 @@ describe("service/connection_service", () => {
|
|
|
152
156
|
);
|
|
153
157
|
|
|
154
158
|
expect(
|
|
155
|
-
(
|
|
159
|
+
(mockEnvironmentStore.addConnection as sinon.SinonStub).called,
|
|
156
160
|
).toBe(true);
|
|
157
161
|
expect(mockProject.updateConnections.called).toBe(true);
|
|
158
162
|
});
|
|
159
163
|
|
|
160
164
|
it("should throw FrozenConfigError when config is frozen", async () => {
|
|
161
|
-
|
|
165
|
+
mockEnvironmentStore.publisherConfigIsFrozen = true;
|
|
162
166
|
|
|
163
167
|
await expect(
|
|
164
168
|
connectionService.addConnection("test-project", "new-connection", {
|
|
@@ -169,14 +173,16 @@ describe("service/connection_service", () => {
|
|
|
169
173
|
});
|
|
170
174
|
|
|
171
175
|
it("should throw error when project not found", async () => {
|
|
172
|
-
(mockRepository.
|
|
176
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
177
|
+
null,
|
|
178
|
+
);
|
|
173
179
|
|
|
174
180
|
await expect(
|
|
175
181
|
connectionService.addConnection("non-existent", "new-connection", {
|
|
176
182
|
name: "new-connection",
|
|
177
183
|
type: "postgres",
|
|
178
184
|
} as ApiConnection),
|
|
179
|
-
).rejects.toThrow('
|
|
185
|
+
).rejects.toThrow('Environment "non-existent" not found in database');
|
|
180
186
|
});
|
|
181
187
|
|
|
182
188
|
it("should throw error when connection already exists", async () => {
|
|
@@ -193,7 +199,7 @@ describe("service/connection_service", () => {
|
|
|
193
199
|
name: "existing-connection",
|
|
194
200
|
};
|
|
195
201
|
|
|
196
|
-
(mockRepository.
|
|
202
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
197
203
|
mockDbProject,
|
|
198
204
|
);
|
|
199
205
|
(mockRepository.getConnectionByName as sinon.SinonStub).resolves(
|
|
@@ -210,7 +216,7 @@ describe("service/connection_service", () => {
|
|
|
210
216
|
} as ApiConnection,
|
|
211
217
|
),
|
|
212
218
|
).rejects.toThrow(
|
|
213
|
-
'Connection "existing-connection" already exists in
|
|
219
|
+
'Connection "existing-connection" already exists in environment "test-project"',
|
|
214
220
|
);
|
|
215
221
|
});
|
|
216
222
|
|
|
@@ -249,11 +255,13 @@ describe("service/connection_service", () => {
|
|
|
249
255
|
metadata: { location: "/test/path" },
|
|
250
256
|
};
|
|
251
257
|
|
|
252
|
-
(mockRepository.
|
|
258
|
+
(mockRepository.getEnvironmentByName as sinon.SinonStub).resolves(
|
|
253
259
|
mockDbProject,
|
|
254
260
|
);
|
|
255
261
|
(mockRepository.getConnectionByName as sinon.SinonStub).resolves(null);
|
|
256
|
-
(
|
|
262
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
263
|
+
mockProject,
|
|
264
|
+
);
|
|
257
265
|
|
|
258
266
|
await connectionService.addConnection(
|
|
259
267
|
"test-project",
|
|
@@ -310,14 +318,16 @@ describe("service/connection_service", () => {
|
|
|
310
318
|
"getConnection",
|
|
311
319
|
);
|
|
312
320
|
getConnectionStub.resolves({
|
|
313
|
-
|
|
321
|
+
dbEnvironment: mockDbProject,
|
|
314
322
|
dbConnection: mockDbConnection,
|
|
315
323
|
repository: mockRepository,
|
|
316
324
|
} as unknown as Awaited<
|
|
317
325
|
ReturnType<typeof connectionService.getConnection>
|
|
318
326
|
>);
|
|
319
327
|
|
|
320
|
-
(
|
|
328
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
329
|
+
mockProject,
|
|
330
|
+
);
|
|
321
331
|
|
|
322
332
|
const updates: Partial<ApiConnection> = {
|
|
323
333
|
type: "postgres",
|
|
@@ -341,7 +351,7 @@ describe("service/connection_service", () => {
|
|
|
341
351
|
).toBe(true);
|
|
342
352
|
|
|
343
353
|
expect(
|
|
344
|
-
(
|
|
354
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).calledWith(
|
|
345
355
|
"test-project",
|
|
346
356
|
false,
|
|
347
357
|
),
|
|
@@ -350,17 +360,17 @@ describe("service/connection_service", () => {
|
|
|
350
360
|
expect(mockProject.updateConnections.called).toBe(true);
|
|
351
361
|
|
|
352
362
|
expect(
|
|
353
|
-
(
|
|
363
|
+
(mockEnvironmentStore.updateConnection as sinon.SinonStub).called,
|
|
354
364
|
).toBe(true);
|
|
355
365
|
const updateCall = (
|
|
356
|
-
|
|
366
|
+
mockEnvironmentStore.updateConnection as sinon.SinonStub
|
|
357
367
|
).getCall(0);
|
|
358
368
|
expect(updateCall.args[0].name).toBe("test-connection");
|
|
359
369
|
expect(updateCall.args[1]).toBe("project-123");
|
|
360
370
|
});
|
|
361
371
|
|
|
362
372
|
it("should throw FrozenConfigError when config is frozen", async () => {
|
|
363
|
-
|
|
373
|
+
mockEnvironmentStore.publisherConfigIsFrozen = true;
|
|
364
374
|
|
|
365
375
|
await expect(
|
|
366
376
|
connectionService.updateConnection(
|
|
@@ -414,14 +424,16 @@ describe("service/connection_service", () => {
|
|
|
414
424
|
"getConnection",
|
|
415
425
|
);
|
|
416
426
|
getConnectionStub.resolves({
|
|
417
|
-
|
|
427
|
+
dbEnvironment: mockDbProject,
|
|
418
428
|
dbConnection: connection1,
|
|
419
429
|
repository: mockRepository,
|
|
420
430
|
} as unknown as Awaited<
|
|
421
431
|
ReturnType<typeof connectionService.getConnection>
|
|
422
432
|
>);
|
|
423
433
|
|
|
424
|
-
(
|
|
434
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
435
|
+
mockProject,
|
|
436
|
+
);
|
|
425
437
|
|
|
426
438
|
await connectionService.updateConnection("test-project", "conn-1", {
|
|
427
439
|
type: "postgres",
|
|
@@ -471,14 +483,16 @@ describe("service/connection_service", () => {
|
|
|
471
483
|
"getConnection",
|
|
472
484
|
);
|
|
473
485
|
getConnectionStub.resolves({
|
|
474
|
-
|
|
486
|
+
dbEnvironment: mockDbProject,
|
|
475
487
|
dbConnection: existingConnection,
|
|
476
488
|
repository: mockRepository,
|
|
477
489
|
} as unknown as Awaited<
|
|
478
490
|
ReturnType<typeof connectionService.getConnection>
|
|
479
491
|
>);
|
|
480
492
|
|
|
481
|
-
(
|
|
493
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
494
|
+
mockProject,
|
|
495
|
+
);
|
|
482
496
|
|
|
483
497
|
const partialUpdate: Partial<ApiConnection> = {
|
|
484
498
|
type: "postgres",
|
|
@@ -498,10 +512,10 @@ describe("service/connection_service", () => {
|
|
|
498
512
|
);
|
|
499
513
|
|
|
500
514
|
expect(
|
|
501
|
-
(
|
|
515
|
+
(mockEnvironmentStore.updateConnection as sinon.SinonStub).called,
|
|
502
516
|
).toBe(true);
|
|
503
517
|
const updateCall = (
|
|
504
|
-
|
|
518
|
+
mockEnvironmentStore.updateConnection as sinon.SinonStub
|
|
505
519
|
).getCall(0);
|
|
506
520
|
const updatedConn = updateCall.args[0];
|
|
507
521
|
|
|
@@ -541,14 +555,16 @@ describe("service/connection_service", () => {
|
|
|
541
555
|
"getConnection",
|
|
542
556
|
);
|
|
543
557
|
getConnectionStub.resolves({
|
|
544
|
-
|
|
558
|
+
dbEnvironment: mockDbProject,
|
|
545
559
|
dbConnection: dbConnection,
|
|
546
560
|
repository: mockRepository,
|
|
547
561
|
} as unknown as Awaited<
|
|
548
562
|
ReturnType<typeof connectionService.getConnection>
|
|
549
563
|
>);
|
|
550
564
|
|
|
551
|
-
(
|
|
565
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
566
|
+
mockProject,
|
|
567
|
+
);
|
|
552
568
|
|
|
553
569
|
await connectionService.updateConnection("test-project", "test-conn", {
|
|
554
570
|
type: "postgres",
|
|
@@ -564,7 +580,7 @@ describe("service/connection_service", () => {
|
|
|
564
580
|
expect(getConnectionStub.calledOnce).toBe(true);
|
|
565
581
|
|
|
566
582
|
const updateCall = (
|
|
567
|
-
|
|
583
|
+
mockEnvironmentStore.updateConnection as sinon.SinonStub
|
|
568
584
|
).getCall(0);
|
|
569
585
|
expect(updateCall.args[0].name).toBe("test-conn");
|
|
570
586
|
expect(updateCall.args[0].type).toBe("postgres");
|
|
@@ -594,7 +610,9 @@ describe("service/connection_service", () => {
|
|
|
594
610
|
ReturnType<typeof connectionService.getConnection>
|
|
595
611
|
>);
|
|
596
612
|
|
|
597
|
-
(
|
|
613
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
614
|
+
mockProject,
|
|
615
|
+
);
|
|
598
616
|
|
|
599
617
|
await connectionService.deleteConnection(
|
|
600
618
|
"test-project",
|
|
@@ -643,7 +661,9 @@ describe("service/connection_service", () => {
|
|
|
643
661
|
} as unknown as Awaited<
|
|
644
662
|
ReturnType<typeof connectionService.getConnection>
|
|
645
663
|
>);
|
|
646
|
-
(
|
|
664
|
+
(mockEnvironmentStore.getEnvironment as sinon.SinonStub).resolves(
|
|
665
|
+
mockProject,
|
|
666
|
+
);
|
|
647
667
|
|
|
648
668
|
await connectionService.deleteConnection(
|
|
649
669
|
"test-project",
|
|
@@ -662,7 +682,7 @@ describe("service/connection_service", () => {
|
|
|
662
682
|
});
|
|
663
683
|
|
|
664
684
|
it("should throw FrozenConfigError when config is frozen", async () => {
|
|
665
|
-
|
|
685
|
+
mockEnvironmentStore.publisherConfigIsFrozen = true;
|
|
666
686
|
|
|
667
687
|
await expect(
|
|
668
688
|
connectionService.deleteConnection(
|
|
@@ -679,7 +699,7 @@ describe("service/connection_service", () => {
|
|
|
679
699
|
);
|
|
680
700
|
getConnectionStub.rejects(
|
|
681
701
|
new ConnectionNotFoundError(
|
|
682
|
-
'Connection "non-existent" not found in
|
|
702
|
+
'Connection "non-existent" not found in environment "test-project"',
|
|
683
703
|
),
|
|
684
704
|
);
|
|
685
705
|
|