@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,29 +1,38 @@
|
|
|
1
|
+
import { EnvironmentStore } from "../service/environment_store";
|
|
1
2
|
import { ManifestService } from "../service/manifest_service";
|
|
2
|
-
import {
|
|
3
|
-
import { resolveProjectId } from "../service/resolve_project";
|
|
3
|
+
import { resolveEnvironmentId } from "../service/resolve_environment";
|
|
4
4
|
|
|
5
5
|
export class ManifestController {
|
|
6
6
|
constructor(
|
|
7
|
-
private
|
|
7
|
+
private environmentStore: EnvironmentStore,
|
|
8
8
|
private manifestService: ManifestService,
|
|
9
9
|
) {}
|
|
10
10
|
|
|
11
|
-
async getManifest(
|
|
12
|
-
const repository = this.
|
|
13
|
-
const
|
|
11
|
+
async getManifest(environmentName: string, packageName: string) {
|
|
12
|
+
const repository = this.environmentStore.storageManager.getRepository();
|
|
13
|
+
const environmentId = await resolveEnvironmentId(
|
|
14
|
+
repository,
|
|
15
|
+
environmentName,
|
|
16
|
+
);
|
|
14
17
|
// Verify the package exists so we return 404 instead of an empty manifest.
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
19
|
+
environmentName,
|
|
20
|
+
false,
|
|
21
|
+
);
|
|
22
|
+
await environment.getPackage(packageName, false);
|
|
23
|
+
return this.manifestService.getManifest(environmentId, packageName);
|
|
18
24
|
}
|
|
19
25
|
|
|
20
|
-
async reloadManifest(
|
|
21
|
-
const repository = this.
|
|
22
|
-
const
|
|
26
|
+
async reloadManifest(environmentName: string, packageName: string) {
|
|
27
|
+
const repository = this.environmentStore.storageManager.getRepository();
|
|
28
|
+
const environmentId = await resolveEnvironmentId(
|
|
29
|
+
repository,
|
|
30
|
+
environmentName,
|
|
31
|
+
);
|
|
23
32
|
return this.manifestService.reloadManifest(
|
|
24
|
-
|
|
33
|
+
environmentId,
|
|
25
34
|
packageName,
|
|
26
|
-
|
|
35
|
+
environmentName,
|
|
27
36
|
);
|
|
28
37
|
}
|
|
29
38
|
}
|
|
@@ -5,13 +5,13 @@ export class MaterializationController {
|
|
|
5
5
|
constructor(private materializationService: MaterializationService) {}
|
|
6
6
|
|
|
7
7
|
async createMaterialization(
|
|
8
|
-
|
|
8
|
+
environmentName: string,
|
|
9
9
|
packageName: string,
|
|
10
10
|
body: Record<string, unknown>,
|
|
11
11
|
) {
|
|
12
12
|
const options = this.validateCreateBody(body);
|
|
13
13
|
return this.materializationService.createMaterialization(
|
|
14
|
-
|
|
14
|
+
environmentName,
|
|
15
15
|
packageName,
|
|
16
16
|
options,
|
|
17
17
|
);
|
|
@@ -38,73 +38,73 @@ export class MaterializationController {
|
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
async startMaterialization(
|
|
41
|
-
|
|
41
|
+
environmentName: string,
|
|
42
42
|
packageName: string,
|
|
43
43
|
materializationId: string,
|
|
44
44
|
) {
|
|
45
45
|
return this.materializationService.startMaterialization(
|
|
46
|
-
|
|
46
|
+
environmentName,
|
|
47
47
|
packageName,
|
|
48
48
|
materializationId,
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
async stopMaterialization(
|
|
53
|
-
|
|
53
|
+
environmentName: string,
|
|
54
54
|
packageName: string,
|
|
55
55
|
materializationId: string,
|
|
56
56
|
) {
|
|
57
57
|
return this.materializationService.stopMaterialization(
|
|
58
|
-
|
|
58
|
+
environmentName,
|
|
59
59
|
packageName,
|
|
60
60
|
materializationId,
|
|
61
61
|
);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
async listMaterializations(
|
|
65
|
-
|
|
65
|
+
environmentName: string,
|
|
66
66
|
packageName: string,
|
|
67
67
|
options?: { limit?: number; offset?: number },
|
|
68
68
|
) {
|
|
69
69
|
return this.materializationService.listMaterializations(
|
|
70
|
-
|
|
70
|
+
environmentName,
|
|
71
71
|
packageName,
|
|
72
72
|
options,
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
async getMaterialization(
|
|
77
|
-
|
|
77
|
+
environmentName: string,
|
|
78
78
|
packageName: string,
|
|
79
79
|
materializationId: string,
|
|
80
80
|
) {
|
|
81
81
|
return this.materializationService.getMaterialization(
|
|
82
|
-
|
|
82
|
+
environmentName,
|
|
83
83
|
packageName,
|
|
84
84
|
materializationId,
|
|
85
85
|
);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
async deleteMaterialization(
|
|
89
|
-
|
|
89
|
+
environmentName: string,
|
|
90
90
|
packageName: string,
|
|
91
91
|
materializationId: string,
|
|
92
92
|
) {
|
|
93
93
|
return this.materializationService.deleteMaterialization(
|
|
94
|
-
|
|
94
|
+
environmentName,
|
|
95
95
|
packageName,
|
|
96
96
|
materializationId,
|
|
97
97
|
);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
100
|
async teardownPackage(
|
|
101
|
-
|
|
101
|
+
environmentName: string,
|
|
102
102
|
packageName: string,
|
|
103
103
|
body: Record<string, unknown>,
|
|
104
104
|
) {
|
|
105
105
|
const options = this.validateTeardownBody(body);
|
|
106
106
|
return this.materializationService.teardownPackage(
|
|
107
|
-
|
|
107
|
+
environmentName,
|
|
108
108
|
packageName,
|
|
109
109
|
options,
|
|
110
110
|
);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { components } from "../api";
|
|
2
2
|
import { ModelNotFoundError } from "../errors";
|
|
3
|
-
import {
|
|
3
|
+
import { EnvironmentStore } from "../service/environment_store";
|
|
4
4
|
import type { FilterParams } from "../service/filter";
|
|
5
5
|
|
|
6
6
|
type ApiNotebook = components["schemas"]["Notebook"];
|
|
@@ -8,38 +8,47 @@ type ApiModel = components["schemas"]["Model"];
|
|
|
8
8
|
type ApiCompiledModel = components["schemas"]["CompiledModel"];
|
|
9
9
|
type ApiRawNotebook = components["schemas"]["RawNotebook"];
|
|
10
10
|
export class ModelController {
|
|
11
|
-
private
|
|
11
|
+
private environmentStore: EnvironmentStore;
|
|
12
12
|
|
|
13
|
-
constructor(
|
|
14
|
-
this.
|
|
13
|
+
constructor(environmentStore: EnvironmentStore) {
|
|
14
|
+
this.environmentStore = environmentStore;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
public async listModels(
|
|
18
|
-
|
|
18
|
+
environmentName: string,
|
|
19
19
|
packageName: string,
|
|
20
20
|
): Promise<ApiModel[]> {
|
|
21
|
-
const
|
|
22
|
-
|
|
21
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
22
|
+
environmentName,
|
|
23
|
+
false,
|
|
24
|
+
);
|
|
25
|
+
const p = await environment.getPackage(packageName, false);
|
|
23
26
|
return p.listModels();
|
|
24
27
|
}
|
|
25
28
|
|
|
26
29
|
public async listNotebooks(
|
|
27
|
-
|
|
30
|
+
environmentName: string,
|
|
28
31
|
packageName: string,
|
|
29
32
|
): Promise<ApiNotebook[]> {
|
|
30
|
-
const
|
|
31
|
-
|
|
33
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
34
|
+
environmentName,
|
|
35
|
+
false,
|
|
36
|
+
);
|
|
37
|
+
const p = await environment.getPackage(packageName, false);
|
|
32
38
|
return p.listNotebooks();
|
|
33
39
|
}
|
|
34
40
|
|
|
35
41
|
public async getModel(
|
|
36
|
-
|
|
42
|
+
environmentName: string,
|
|
37
43
|
packageName: string,
|
|
38
44
|
modelPath: string,
|
|
39
45
|
): Promise<ApiCompiledModel> {
|
|
40
46
|
try {
|
|
41
|
-
const
|
|
42
|
-
|
|
47
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
48
|
+
environmentName,
|
|
49
|
+
false,
|
|
50
|
+
);
|
|
51
|
+
const p = await environment.getPackage(packageName, false);
|
|
43
52
|
const model = p.getModel(modelPath);
|
|
44
53
|
if (!model) {
|
|
45
54
|
throw new ModelNotFoundError(`${modelPath} does not exist`);
|
|
@@ -55,18 +64,21 @@ export class ModelController {
|
|
|
55
64
|
}
|
|
56
65
|
// Wrap other errors with more context
|
|
57
66
|
throw new Error(
|
|
58
|
-
`Failed to get model ${modelPath} from package ${packageName} in
|
|
67
|
+
`Failed to get model ${modelPath} from package ${packageName} in environment ${environmentName}: ${error}`,
|
|
59
68
|
);
|
|
60
69
|
}
|
|
61
70
|
}
|
|
62
71
|
|
|
63
72
|
public async getNotebook(
|
|
64
|
-
|
|
73
|
+
environmentName: string,
|
|
65
74
|
packageName: string,
|
|
66
75
|
notebookPath: string,
|
|
67
76
|
): Promise<ApiRawNotebook> {
|
|
68
|
-
const
|
|
69
|
-
|
|
77
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
78
|
+
environmentName,
|
|
79
|
+
false,
|
|
80
|
+
);
|
|
81
|
+
const p = await environment.getPackage(packageName, false);
|
|
70
82
|
const model = p.getModel(notebookPath);
|
|
71
83
|
if (!model) {
|
|
72
84
|
throw new ModelNotFoundError(`${notebookPath} does not exist`);
|
|
@@ -79,7 +91,7 @@ export class ModelController {
|
|
|
79
91
|
}
|
|
80
92
|
|
|
81
93
|
public async executeNotebookCell(
|
|
82
|
-
|
|
94
|
+
environmentName: string,
|
|
83
95
|
packageName: string,
|
|
84
96
|
notebookPath: string,
|
|
85
97
|
cellIndex: number,
|
|
@@ -92,8 +104,11 @@ export class ModelController {
|
|
|
92
104
|
result?: string;
|
|
93
105
|
newSources?: string[];
|
|
94
106
|
}> {
|
|
95
|
-
const
|
|
96
|
-
|
|
107
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
108
|
+
environmentName,
|
|
109
|
+
false,
|
|
110
|
+
);
|
|
111
|
+
const p = await environment.getPackage(packageName, false);
|
|
97
112
|
const model = p.getModel(notebookPath);
|
|
98
113
|
if (!model) {
|
|
99
114
|
throw new ModelNotFoundError(`${notebookPath} does not exist`);
|
|
@@ -3,59 +3,78 @@ import { components } from "../api";
|
|
|
3
3
|
import { PUBLISHER_DATA_DIR } from "../constants";
|
|
4
4
|
import { BadRequestError, FrozenConfigError } from "../errors";
|
|
5
5
|
import { logger } from "../logger";
|
|
6
|
+
import { EnvironmentStore } from "../service/environment_store";
|
|
6
7
|
import { ManifestService } from "../service/manifest_service";
|
|
7
|
-
import { ProjectStore } from "../service/project_store";
|
|
8
8
|
|
|
9
9
|
type ApiPackage = components["schemas"]["Package"];
|
|
10
10
|
|
|
11
11
|
export class PackageController {
|
|
12
|
-
private
|
|
12
|
+
private environmentStore: EnvironmentStore;
|
|
13
13
|
private manifestService: ManifestService;
|
|
14
14
|
|
|
15
|
-
constructor(
|
|
16
|
-
|
|
15
|
+
constructor(
|
|
16
|
+
environmentStore: EnvironmentStore,
|
|
17
|
+
manifestService: ManifestService,
|
|
18
|
+
) {
|
|
19
|
+
this.environmentStore = environmentStore;
|
|
17
20
|
this.manifestService = manifestService;
|
|
18
21
|
}
|
|
19
22
|
|
|
20
|
-
public async listPackages(
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
+
public async listPackages(environmentName: string): Promise<ApiPackage[]> {
|
|
24
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
25
|
+
environmentName,
|
|
26
|
+
false,
|
|
27
|
+
);
|
|
28
|
+
return environment.listPackages();
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
public async getPackage(
|
|
26
|
-
|
|
32
|
+
environmentName: string,
|
|
27
33
|
packageName: string,
|
|
28
34
|
reload: boolean,
|
|
29
35
|
): Promise<ApiPackage> {
|
|
30
|
-
const
|
|
31
|
-
|
|
36
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
37
|
+
environmentName,
|
|
38
|
+
false,
|
|
39
|
+
);
|
|
40
|
+
const _package = await environment.getPackage(packageName, reload);
|
|
32
41
|
const packageLocation = _package.getPackageMetadata().location;
|
|
33
42
|
if (reload && packageLocation) {
|
|
34
|
-
await this.downloadPackage(
|
|
43
|
+
await this.downloadPackage(
|
|
44
|
+
environmentName,
|
|
45
|
+
packageName,
|
|
46
|
+
packageLocation,
|
|
47
|
+
);
|
|
35
48
|
}
|
|
36
49
|
return _package.getPackageMetadata();
|
|
37
50
|
}
|
|
38
51
|
|
|
39
52
|
async addPackage(
|
|
40
|
-
|
|
53
|
+
environmentName: string,
|
|
41
54
|
body: ApiPackage,
|
|
42
55
|
options?: { autoLoadManifest?: boolean },
|
|
43
56
|
) {
|
|
44
|
-
if (this.
|
|
57
|
+
if (this.environmentStore.publisherConfigIsFrozen) {
|
|
45
58
|
throw new FrozenConfigError();
|
|
46
59
|
}
|
|
47
60
|
if (!body.name) {
|
|
48
61
|
throw new BadRequestError("Package name is required");
|
|
49
62
|
}
|
|
50
|
-
const
|
|
63
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
64
|
+
environmentName,
|
|
65
|
+
false,
|
|
66
|
+
);
|
|
51
67
|
if (body.location) {
|
|
52
|
-
await this.downloadPackage(
|
|
68
|
+
await this.downloadPackage(environmentName, body.name, body.location);
|
|
53
69
|
}
|
|
54
|
-
const result = await
|
|
55
|
-
await this.
|
|
70
|
+
const result = await environment.addPackage(body.name);
|
|
71
|
+
await this.environmentStore.addPackageToDatabase(
|
|
72
|
+
environmentName,
|
|
73
|
+
body.name,
|
|
74
|
+
);
|
|
56
75
|
|
|
57
76
|
if (options?.autoLoadManifest === true) {
|
|
58
|
-
await this.tryLoadExistingManifest(
|
|
77
|
+
await this.tryLoadExistingManifest(environmentName, body.name);
|
|
59
78
|
}
|
|
60
79
|
|
|
61
80
|
return result;
|
|
@@ -67,47 +86,52 @@ export class PackageController {
|
|
|
67
86
|
* persist references resolve to the materialized tables immediately.
|
|
68
87
|
*/
|
|
69
88
|
private async tryLoadExistingManifest(
|
|
70
|
-
|
|
89
|
+
environmentName: string,
|
|
71
90
|
packageName: string,
|
|
72
91
|
): Promise<void> {
|
|
73
92
|
try {
|
|
74
|
-
const repository =
|
|
75
|
-
|
|
76
|
-
|
|
93
|
+
const repository =
|
|
94
|
+
this.environmentStore.storageManager.getRepository();
|
|
95
|
+
const dbEnvironment =
|
|
96
|
+
await repository.getEnvironmentByName(environmentName);
|
|
97
|
+
if (!dbEnvironment) return;
|
|
77
98
|
|
|
78
99
|
const manifest = await this.manifestService.getManifest(
|
|
79
|
-
|
|
100
|
+
dbEnvironment.id,
|
|
80
101
|
packageName,
|
|
81
102
|
);
|
|
82
103
|
if (Object.keys(manifest.entries).length === 0) return;
|
|
83
104
|
|
|
84
105
|
await this.manifestService.reloadManifest(
|
|
85
|
-
|
|
106
|
+
dbEnvironment.id,
|
|
86
107
|
packageName,
|
|
87
|
-
|
|
108
|
+
environmentName,
|
|
88
109
|
);
|
|
89
110
|
logger.info("Auto-loaded existing manifest for added package", {
|
|
90
|
-
|
|
111
|
+
environmentName,
|
|
91
112
|
packageName,
|
|
92
113
|
entryCount: Object.keys(manifest.entries).length,
|
|
93
114
|
});
|
|
94
115
|
} catch (error) {
|
|
95
116
|
logger.warn("Failed to auto-load manifest for package", {
|
|
96
|
-
|
|
117
|
+
environmentName,
|
|
97
118
|
packageName,
|
|
98
119
|
error,
|
|
99
120
|
});
|
|
100
121
|
}
|
|
101
122
|
}
|
|
102
123
|
|
|
103
|
-
public async deletePackage(
|
|
104
|
-
if (this.
|
|
124
|
+
public async deletePackage(environmentName: string, packageName: string) {
|
|
125
|
+
if (this.environmentStore.publisherConfigIsFrozen) {
|
|
105
126
|
throw new FrozenConfigError();
|
|
106
127
|
}
|
|
107
|
-
const
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
128
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
129
|
+
environmentName,
|
|
130
|
+
false,
|
|
131
|
+
);
|
|
132
|
+
const result = await environment.deletePackage(packageName);
|
|
133
|
+
await this.environmentStore.deletePackageFromDatabase(
|
|
134
|
+
environmentName,
|
|
111
135
|
packageName,
|
|
112
136
|
);
|
|
113
137
|
|
|
@@ -115,32 +139,42 @@ export class PackageController {
|
|
|
115
139
|
}
|
|
116
140
|
|
|
117
141
|
public async updatePackage(
|
|
118
|
-
|
|
142
|
+
environmentName: string,
|
|
119
143
|
packageName: string,
|
|
120
144
|
body: ApiPackage,
|
|
121
145
|
) {
|
|
122
|
-
if (this.
|
|
146
|
+
if (this.environmentStore.publisherConfigIsFrozen) {
|
|
123
147
|
throw new FrozenConfigError();
|
|
124
148
|
}
|
|
125
|
-
const
|
|
149
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
150
|
+
environmentName,
|
|
151
|
+
false,
|
|
152
|
+
);
|
|
126
153
|
if (body.location) {
|
|
127
|
-
await this.downloadPackage(
|
|
154
|
+
await this.downloadPackage(
|
|
155
|
+
environmentName,
|
|
156
|
+
packageName,
|
|
157
|
+
body.location,
|
|
158
|
+
);
|
|
128
159
|
}
|
|
129
|
-
const result = await
|
|
130
|
-
await this.
|
|
160
|
+
const result = await environment.updatePackage(packageName, body);
|
|
161
|
+
await this.environmentStore.addPackageToDatabase(
|
|
162
|
+
environmentName,
|
|
163
|
+
packageName,
|
|
164
|
+
);
|
|
131
165
|
|
|
132
166
|
return result;
|
|
133
167
|
}
|
|
134
168
|
|
|
135
169
|
private async downloadPackage(
|
|
136
|
-
|
|
170
|
+
environmentName: string,
|
|
137
171
|
packageName: string,
|
|
138
172
|
packageLocation: string,
|
|
139
173
|
) {
|
|
140
174
|
const absoluteTargetPath = path.join(
|
|
141
|
-
this.
|
|
175
|
+
this.environmentStore.serverRootPath,
|
|
142
176
|
PUBLISHER_DATA_DIR,
|
|
143
|
-
|
|
177
|
+
environmentName,
|
|
144
178
|
packageName,
|
|
145
179
|
);
|
|
146
180
|
const isCompressedFile = packageLocation.endsWith(".zip");
|
|
@@ -148,21 +182,21 @@ export class PackageController {
|
|
|
148
182
|
packageLocation.startsWith("https://") ||
|
|
149
183
|
packageLocation.startsWith("git@")
|
|
150
184
|
) {
|
|
151
|
-
await this.
|
|
185
|
+
await this.environmentStore.downloadGitHubDirectory(
|
|
152
186
|
packageLocation,
|
|
153
187
|
absoluteTargetPath,
|
|
154
188
|
);
|
|
155
189
|
} else if (packageLocation.startsWith("gs://")) {
|
|
156
|
-
await this.
|
|
190
|
+
await this.environmentStore.downloadGcsDirectory(
|
|
157
191
|
packageLocation,
|
|
158
|
-
|
|
192
|
+
environmentName,
|
|
159
193
|
absoluteTargetPath,
|
|
160
194
|
isCompressedFile,
|
|
161
195
|
);
|
|
162
196
|
} else if (packageLocation.startsWith("s3://")) {
|
|
163
|
-
await this.
|
|
197
|
+
await this.environmentStore.downloadS3Directory(
|
|
164
198
|
packageLocation,
|
|
165
|
-
|
|
199
|
+
environmentName,
|
|
166
200
|
absoluteTargetPath,
|
|
167
201
|
isCompressedFile,
|
|
168
202
|
);
|
|
@@ -171,10 +205,10 @@ export class PackageController {
|
|
|
171
205
|
if (packageLocation.startsWith("/")) {
|
|
172
206
|
// Absolute paths from the publisher.config could be placed outside of /etc/publisher,
|
|
173
207
|
// so we need to mount them on the right place.
|
|
174
|
-
await this.
|
|
208
|
+
await this.environmentStore.mountLocalDirectory(
|
|
175
209
|
packageLocation,
|
|
176
210
|
absoluteTargetPath,
|
|
177
|
-
|
|
211
|
+
environmentName,
|
|
178
212
|
packageName,
|
|
179
213
|
);
|
|
180
214
|
}
|
|
@@ -2,7 +2,7 @@ import { validateRenderTags } from "@malloydata/render-validator";
|
|
|
2
2
|
import { components } from "../api";
|
|
3
3
|
import { API_PREFIX } from "../constants";
|
|
4
4
|
import { ModelNotFoundError } from "../errors";
|
|
5
|
-
import {
|
|
5
|
+
import { EnvironmentStore } from "../service/environment_store";
|
|
6
6
|
import type { FilterParams } from "../service/filter";
|
|
7
7
|
|
|
8
8
|
type ApiQuery = components["schemas"]["QueryResult"];
|
|
@@ -16,14 +16,14 @@ function bigIntReplacer(_key: string, value: unknown): unknown {
|
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export class QueryController {
|
|
19
|
-
private
|
|
19
|
+
private environmentStore: EnvironmentStore;
|
|
20
20
|
|
|
21
|
-
constructor(
|
|
22
|
-
this.
|
|
21
|
+
constructor(environmentStore: EnvironmentStore) {
|
|
22
|
+
this.environmentStore = environmentStore;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
public async getQuery(
|
|
26
|
-
|
|
26
|
+
environmentName: string,
|
|
27
27
|
packageName: string,
|
|
28
28
|
modelPath: string,
|
|
29
29
|
sourceName: string,
|
|
@@ -33,8 +33,11 @@ export class QueryController {
|
|
|
33
33
|
filterParams?: FilterParams,
|
|
34
34
|
bypassFilters?: boolean,
|
|
35
35
|
): Promise<ApiQuery> {
|
|
36
|
-
const
|
|
37
|
-
|
|
36
|
+
const environment = await this.environmentStore.getEnvironment(
|
|
37
|
+
environmentName,
|
|
38
|
+
false,
|
|
39
|
+
);
|
|
40
|
+
const p = await environment.getPackage(packageName, false);
|
|
38
41
|
const model = p.getModel(modelPath);
|
|
39
42
|
|
|
40
43
|
if (!model) {
|
|
@@ -52,7 +55,7 @@ export class QueryController {
|
|
|
52
55
|
result: compactJson
|
|
53
56
|
? JSON.stringify(compactResult, bigIntReplacer)
|
|
54
57
|
: JSON.stringify(result),
|
|
55
|
-
resource: `${API_PREFIX}/
|
|
58
|
+
resource: `${API_PREFIX}/environments/${environmentName}/packages/${packageName}/models/${modelPath}/query`,
|
|
56
59
|
renderLogs: renderLogs.length > 0 ? renderLogs : undefined,
|
|
57
60
|
} as ApiQuery;
|
|
58
61
|
}
|