@malloy-publisher/server 0.0.182 → 0.0.183-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/build.ts +7 -3
- package/dist/app/api-doc.yaml +423 -60
- package/dist/app/assets/HomePage-Dn3E4CuB.js +1 -0
- package/dist/app/assets/{MainPage-DINuSDg0.js → MainPage-BzB3yoqi.js} +1 -1
- package/dist/app/assets/{ModelPage-BMcaV1YQ.js → ModelPage-C9O_sAXT.js} +1 -1
- package/dist/app/assets/PackagePage-DcxKEjBX.js +1 -0
- package/dist/app/assets/ProjectPage-BDj307rF.js +1 -0
- package/dist/app/assets/{RouteError-r14osUo0.js → RouteError-DAShbVCG.js} +1 -1
- package/dist/app/assets/{WorkbookPage-HI39NTWs.js → WorkbookPage-Cs_XYEaB.js} +1 -1
- package/dist/app/assets/core-CjeTkq8O.es-BqRc6yhC.js +148 -0
- package/dist/app/assets/engine-oniguruma-C4vnmooL.es-jdkXmgTr.js +1 -0
- package/dist/app/assets/github-light-JYsPkUQd.es-DAi9KRSo.js +1 -0
- package/dist/app/assets/index-15BOvhp0.js +456 -0
- package/dist/app/assets/{index-Dd6uCk_C.js → index-Bb2jqquW.js} +1 -1
- package/dist/app/assets/{index-JqHhhRqY.js → index-D68X76-7.js} +98 -98
- package/dist/app/assets/{index.umd-lwkX_kFe.js → index.umd-DGBekgSu.js} +1 -1
- package/dist/app/assets/json-71t8ZF9g.es-BQoSv7ci.js +1 -0
- package/dist/app/assets/sql-DCkt643-.es-COK4E0Yg.js +1 -0
- package/dist/app/assets/typescript-buWNZFwO.es-Dj6nwHGl.js +1 -0
- package/dist/app/index.html +1 -1
- package/dist/{instrumentation.js → instrumentation.mjs} +10567 -10584
- package/dist/{server.js → server.mjs} +16642 -15332
- package/package.json +19 -17
- package/src/controller/connection.controller.ts +27 -20
- package/src/controller/manifest.controller.ts +29 -0
- package/src/controller/materialization.controller.ts +125 -0
- package/src/controller/model.controller.ts +0 -2
- package/src/controller/package.controller.ts +53 -2
- package/src/errors.ts +24 -0
- package/src/mcp/prompts/handlers.ts +1 -1
- package/src/server.ts +202 -15
- package/src/service/connection.ts +1 -4
- package/src/service/filter.spec.ts +55 -0
- package/src/service/filter.ts +8 -3
- package/src/service/filter_integration.spec.ts +203 -0
- package/src/service/manifest_service.spec.ts +201 -0
- package/src/service/manifest_service.ts +106 -0
- package/src/service/materialization_service.spec.ts +648 -0
- package/src/service/materialization_service.ts +929 -0
- package/src/service/materialized_table_gc.spec.ts +383 -0
- package/src/service/materialized_table_gc.ts +279 -0
- package/src/service/model.ts +54 -13
- package/src/service/package.ts +50 -0
- package/src/service/project_store.ts +21 -2
- package/src/service/quoting.ts +41 -0
- package/src/service/resolve_project.ts +13 -0
- package/src/storage/DatabaseInterface.ts +103 -1
- package/src/storage/{StorageManager.spec.ts → StorageManager.mock.ts} +9 -0
- package/src/storage/StorageManager.ts +119 -1
- package/src/storage/duckdb/DuckDBConnection.ts +1 -1
- package/src/storage/duckdb/DuckDBManifestStore.ts +70 -0
- package/src/storage/duckdb/DuckDBRepository.ts +99 -9
- package/src/storage/duckdb/ManifestRepository.ts +119 -0
- package/src/storage/duckdb/MaterializationRepository.ts +249 -0
- package/src/storage/duckdb/manifest_store.spec.ts +133 -0
- package/src/storage/duckdb/schema.ts +59 -1
- package/src/storage/ducklake/DuckLakeManifestStore.ts +146 -0
- package/tests/fixtures/persist-test/data/orders.csv +5 -0
- package/tests/fixtures/persist-test/persist_test.malloy +11 -0
- package/tests/fixtures/persist-test/publisher.json +5 -0
- package/tests/fixtures/publisher.config.json +15 -0
- package/tests/harness/rest_e2e.ts +68 -0
- package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +470 -0
- package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +2 -2
- package/tsconfig.json +1 -1
- package/dist/app/assets/HomePage-or6BbD5P.js +0 -1
- package/dist/app/assets/PackagePage-DXxlQcCj.js +0 -1
- package/dist/app/assets/ProjectPage-vfZc_Kvu.js +0 -1
- package/dist/app/assets/index-Bw1lh09G.js +0 -467
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@malloy-publisher/server",
|
|
3
3
|
"description": "Malloy Publisher Server",
|
|
4
|
-
"version": "0.0.
|
|
5
|
-
"main": "dist/server.
|
|
4
|
+
"version": "0.0.183-dev",
|
|
5
|
+
"main": "dist/server.mjs",
|
|
6
6
|
"bin": {
|
|
7
|
-
"malloy-publisher": "dist/server.
|
|
7
|
+
"malloy-publisher": "dist/server.mjs"
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -14,14 +14,16 @@
|
|
|
14
14
|
"access": "public"
|
|
15
15
|
},
|
|
16
16
|
"scripts": {
|
|
17
|
-
"test": "bun test
|
|
17
|
+
"test": "bun run test:unit && bun run test:integration",
|
|
18
|
+
"test:unit": "bun test --timeout 100000 src",
|
|
19
|
+
"test:integration": "bun test --timeout 100000 tests",
|
|
18
20
|
"build": "bun generate-api-types && bun build:app && NODE_ENV=production bun run build.ts",
|
|
19
21
|
"build:server-only": "bun generate-api-types && NODE_ENV=production bun run build.ts",
|
|
20
|
-
"start": "NODE_ENV=production
|
|
21
|
-
"start:init": "NODE_ENV=production
|
|
22
|
+
"start": "NODE_ENV=production bun run ./dist/server.mjs",
|
|
23
|
+
"start:init": "NODE_ENV=production bun run ./dist/server.mjs --init",
|
|
22
24
|
"start:dev": "NODE_ENV=development bun --watch src/server.ts",
|
|
23
25
|
"start:dev:init": "NODE_ENV=development bun --watch src/server.ts --init",
|
|
24
|
-
"start:instrumented": "
|
|
26
|
+
"start:instrumented": "bun --preload ./dist/instrumentation.mjs ./dist/server.mjs",
|
|
25
27
|
"lint": "bunx eslint \"./src/**/*.ts\"",
|
|
26
28
|
"format": "bunx prettier --write '**/*.{ts,tsx}'",
|
|
27
29
|
"build:app": "cd ../app && NODE_ENV=production bunx vite build",
|
|
@@ -32,15 +34,15 @@
|
|
|
32
34
|
"@azure/identity": "^4.13.0",
|
|
33
35
|
"@azure/storage-blob": "^12.26.0",
|
|
34
36
|
"@google-cloud/storage": "^7.16.0",
|
|
35
|
-
"@malloydata/db-bigquery": "^0.0.
|
|
36
|
-
"@malloydata/db-duckdb": "^0.0.
|
|
37
|
-
"@malloydata/db-mysql": "^0.0.
|
|
38
|
-
"@malloydata/db-postgres": "^0.0.
|
|
39
|
-
"@malloydata/db-snowflake": "^0.0.
|
|
40
|
-
"@malloydata/db-trino": "^0.0.
|
|
41
|
-
"@malloydata/malloy": "^0.0.
|
|
42
|
-
"@malloydata/malloy-sql": "^0.0.
|
|
43
|
-
"@malloydata/render-validator": "^0.0.
|
|
37
|
+
"@malloydata/db-bigquery": "^0.0.377",
|
|
38
|
+
"@malloydata/db-duckdb": "^0.0.377",
|
|
39
|
+
"@malloydata/db-mysql": "^0.0.377",
|
|
40
|
+
"@malloydata/db-postgres": "^0.0.377",
|
|
41
|
+
"@malloydata/db-snowflake": "^0.0.377",
|
|
42
|
+
"@malloydata/db-trino": "^0.0.377",
|
|
43
|
+
"@malloydata/malloy": "^0.0.377",
|
|
44
|
+
"@malloydata/malloy-sql": "^0.0.377",
|
|
45
|
+
"@malloydata/render-validator": "^0.0.377",
|
|
44
46
|
"@modelcontextprotocol/sdk": "^1.13.2",
|
|
45
47
|
"@opentelemetry/api": "^1.9.0",
|
|
46
48
|
"@opentelemetry/auto-instrumentations-node": "^0.57.0",
|
|
@@ -56,7 +58,7 @@
|
|
|
56
58
|
"class-transformer": "^0.5.1",
|
|
57
59
|
"class-validator": "^0.14.1",
|
|
58
60
|
"cors": "^2.8.5",
|
|
59
|
-
"duckdb": "1.4.
|
|
61
|
+
"duckdb": "1.4.4",
|
|
60
62
|
"express": "^4.21.0",
|
|
61
63
|
"globals": "^15.9.0",
|
|
62
64
|
"handlebars": "^4.7.8",
|
|
@@ -141,7 +141,10 @@ export class ConnectionController {
|
|
|
141
141
|
if (!source) {
|
|
142
142
|
throw new ConnectionError(`Table ${tablePath} not found`);
|
|
143
143
|
}
|
|
144
|
-
|
|
144
|
+
// BigQueryConnection returns `error.message` as a string on failure instead of throwing.
|
|
145
|
+
if (typeof source === "string") {
|
|
146
|
+
throw new ConnectionError(source);
|
|
147
|
+
}
|
|
145
148
|
return {
|
|
146
149
|
source: JSON.stringify(source),
|
|
147
150
|
resource: tablePath,
|
|
@@ -173,11 +176,11 @@ export class ConnectionController {
|
|
|
173
176
|
if (!projectName || !connectionName) {
|
|
174
177
|
throw new BadRequestError("Connection payload is required");
|
|
175
178
|
}
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
);
|
|
180
|
-
return
|
|
179
|
+
// Prefer the in-memory API connection (which was materialized by the
|
|
180
|
+
// project on load and carries `attributes`). The DB row stores the
|
|
181
|
+
// raw config and FK columns, which aren't the ApiConnection shape.
|
|
182
|
+
const project = await this.projectStore.getProject(projectName, false);
|
|
183
|
+
return project.getApiConnection(connectionName);
|
|
181
184
|
}
|
|
182
185
|
|
|
183
186
|
public async listConnections(projectName: string): Promise<ApiConnection[]> {
|
|
@@ -231,22 +234,26 @@ export class ConnectionController {
|
|
|
231
234
|
projectName,
|
|
232
235
|
connectionName,
|
|
233
236
|
);
|
|
234
|
-
|
|
235
237
|
try {
|
|
238
|
+
const schema = await (
|
|
239
|
+
malloyConnection as Connection & {
|
|
240
|
+
fetchSelectSchema: (params: {
|
|
241
|
+
connection: string;
|
|
242
|
+
selectStr: string;
|
|
243
|
+
}) => Promise<unknown>;
|
|
244
|
+
}
|
|
245
|
+
).fetchSelectSchema({
|
|
246
|
+
connection: connectionName,
|
|
247
|
+
selectStr: sqlStatement,
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
// BigQueryConnection returns `error.message` as a string on failure instead of throwing.
|
|
251
|
+
if (typeof schema === "string") {
|
|
252
|
+
throw new ConnectionError(schema);
|
|
253
|
+
}
|
|
254
|
+
|
|
236
255
|
return {
|
|
237
|
-
source: JSON.stringify(
|
|
238
|
-
await (
|
|
239
|
-
malloyConnection as Connection & {
|
|
240
|
-
fetchSelectSchema: (params: {
|
|
241
|
-
connection: string;
|
|
242
|
-
selectStr: string;
|
|
243
|
-
}) => Promise<unknown>;
|
|
244
|
-
}
|
|
245
|
-
).fetchSelectSchema({
|
|
246
|
-
connection: connectionName,
|
|
247
|
-
selectStr: sqlStatement,
|
|
248
|
-
}),
|
|
249
|
-
),
|
|
256
|
+
source: JSON.stringify(schema),
|
|
250
257
|
};
|
|
251
258
|
} catch (error) {
|
|
252
259
|
throw new ConnectionError((error as Error).message);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ManifestService } from "../service/manifest_service";
|
|
2
|
+
import { ProjectStore } from "../service/project_store";
|
|
3
|
+
import { resolveProjectId } from "../service/resolve_project";
|
|
4
|
+
|
|
5
|
+
export class ManifestController {
|
|
6
|
+
constructor(
|
|
7
|
+
private projectStore: ProjectStore,
|
|
8
|
+
private manifestService: ManifestService,
|
|
9
|
+
) {}
|
|
10
|
+
|
|
11
|
+
async getManifest(projectName: string, packageName: string) {
|
|
12
|
+
const repository = this.projectStore.storageManager.getRepository();
|
|
13
|
+
const projectId = await resolveProjectId(repository, projectName);
|
|
14
|
+
// Verify the package exists so we return 404 instead of an empty manifest.
|
|
15
|
+
const project = await this.projectStore.getProject(projectName, false);
|
|
16
|
+
await project.getPackage(packageName, false);
|
|
17
|
+
return this.manifestService.getManifest(projectId, packageName);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async reloadManifest(projectName: string, packageName: string) {
|
|
21
|
+
const repository = this.projectStore.storageManager.getRepository();
|
|
22
|
+
const projectId = await resolveProjectId(repository, projectName);
|
|
23
|
+
return this.manifestService.reloadManifest(
|
|
24
|
+
projectId,
|
|
25
|
+
packageName,
|
|
26
|
+
projectName,
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { BadRequestError } from "../errors";
|
|
2
|
+
import { MaterializationService } from "../service/materialization_service";
|
|
3
|
+
|
|
4
|
+
export class MaterializationController {
|
|
5
|
+
constructor(private materializationService: MaterializationService) {}
|
|
6
|
+
|
|
7
|
+
async createMaterialization(
|
|
8
|
+
projectName: string,
|
|
9
|
+
packageName: string,
|
|
10
|
+
body: Record<string, unknown>,
|
|
11
|
+
) {
|
|
12
|
+
const options = this.validateCreateBody(body);
|
|
13
|
+
return this.materializationService.createMaterialization(
|
|
14
|
+
projectName,
|
|
15
|
+
packageName,
|
|
16
|
+
options,
|
|
17
|
+
);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private validateCreateBody(body: Record<string, unknown>): {
|
|
21
|
+
forceRefresh?: boolean;
|
|
22
|
+
autoLoadManifest?: boolean;
|
|
23
|
+
} {
|
|
24
|
+
const result: { forceRefresh?: boolean; autoLoadManifest?: boolean } = {};
|
|
25
|
+
if (body.forceRefresh !== undefined) {
|
|
26
|
+
if (typeof body.forceRefresh !== "boolean") {
|
|
27
|
+
throw new BadRequestError("forceRefresh must be a boolean");
|
|
28
|
+
}
|
|
29
|
+
result.forceRefresh = body.forceRefresh;
|
|
30
|
+
}
|
|
31
|
+
if (body.autoLoadManifest !== undefined) {
|
|
32
|
+
if (typeof body.autoLoadManifest !== "boolean") {
|
|
33
|
+
throw new BadRequestError("autoLoadManifest must be a boolean");
|
|
34
|
+
}
|
|
35
|
+
result.autoLoadManifest = body.autoLoadManifest;
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async startMaterialization(
|
|
41
|
+
projectName: string,
|
|
42
|
+
packageName: string,
|
|
43
|
+
materializationId: string,
|
|
44
|
+
) {
|
|
45
|
+
return this.materializationService.startMaterialization(
|
|
46
|
+
projectName,
|
|
47
|
+
packageName,
|
|
48
|
+
materializationId,
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
async stopMaterialization(
|
|
53
|
+
projectName: string,
|
|
54
|
+
packageName: string,
|
|
55
|
+
materializationId: string,
|
|
56
|
+
) {
|
|
57
|
+
return this.materializationService.stopMaterialization(
|
|
58
|
+
projectName,
|
|
59
|
+
packageName,
|
|
60
|
+
materializationId,
|
|
61
|
+
);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
async listMaterializations(
|
|
65
|
+
projectName: string,
|
|
66
|
+
packageName: string,
|
|
67
|
+
options?: { limit?: number; offset?: number },
|
|
68
|
+
) {
|
|
69
|
+
return this.materializationService.listMaterializations(
|
|
70
|
+
projectName,
|
|
71
|
+
packageName,
|
|
72
|
+
options,
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async getMaterialization(
|
|
77
|
+
projectName: string,
|
|
78
|
+
packageName: string,
|
|
79
|
+
materializationId: string,
|
|
80
|
+
) {
|
|
81
|
+
return this.materializationService.getMaterialization(
|
|
82
|
+
projectName,
|
|
83
|
+
packageName,
|
|
84
|
+
materializationId,
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
async deleteMaterialization(
|
|
89
|
+
projectName: string,
|
|
90
|
+
packageName: string,
|
|
91
|
+
materializationId: string,
|
|
92
|
+
) {
|
|
93
|
+
return this.materializationService.deleteMaterialization(
|
|
94
|
+
projectName,
|
|
95
|
+
packageName,
|
|
96
|
+
materializationId,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async teardownPackage(
|
|
101
|
+
projectName: string,
|
|
102
|
+
packageName: string,
|
|
103
|
+
body: Record<string, unknown>,
|
|
104
|
+
) {
|
|
105
|
+
const options = this.validateTeardownBody(body);
|
|
106
|
+
return this.materializationService.teardownPackage(
|
|
107
|
+
projectName,
|
|
108
|
+
packageName,
|
|
109
|
+
options,
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
private validateTeardownBody(body: Record<string, unknown>): {
|
|
114
|
+
dryRun?: boolean;
|
|
115
|
+
} {
|
|
116
|
+
const options: { dryRun?: boolean } = {};
|
|
117
|
+
if (body.dryRun !== undefined) {
|
|
118
|
+
if (typeof body.dryRun !== "boolean") {
|
|
119
|
+
throw new BadRequestError("dryRun must be a boolean");
|
|
120
|
+
}
|
|
121
|
+
options.dryRun = body.dryRun;
|
|
122
|
+
}
|
|
123
|
+
return options;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
@@ -7,8 +7,6 @@ type ApiNotebook = components["schemas"]["Notebook"];
|
|
|
7
7
|
type ApiModel = components["schemas"]["Model"];
|
|
8
8
|
type ApiCompiledModel = components["schemas"]["CompiledModel"];
|
|
9
9
|
type ApiRawNotebook = components["schemas"]["RawNotebook"];
|
|
10
|
-
export type ListModelsFilterEnum =
|
|
11
|
-
components["parameters"]["ListModelsFilterEnum"];
|
|
12
10
|
export class ModelController {
|
|
13
11
|
private projectStore: ProjectStore;
|
|
14
12
|
|
|
@@ -2,15 +2,19 @@ import * as path from "path";
|
|
|
2
2
|
import { components } from "../api";
|
|
3
3
|
import { PUBLISHER_DATA_DIR } from "../constants";
|
|
4
4
|
import { BadRequestError, FrozenConfigError } from "../errors";
|
|
5
|
+
import { logger } from "../logger";
|
|
6
|
+
import { ManifestService } from "../service/manifest_service";
|
|
5
7
|
import { ProjectStore } from "../service/project_store";
|
|
6
8
|
|
|
7
9
|
type ApiPackage = components["schemas"]["Package"];
|
|
8
10
|
|
|
9
11
|
export class PackageController {
|
|
10
12
|
private projectStore: ProjectStore;
|
|
13
|
+
private manifestService: ManifestService;
|
|
11
14
|
|
|
12
|
-
constructor(projectStore: ProjectStore) {
|
|
15
|
+
constructor(projectStore: ProjectStore, manifestService: ManifestService) {
|
|
13
16
|
this.projectStore = projectStore;
|
|
17
|
+
this.manifestService = manifestService;
|
|
14
18
|
}
|
|
15
19
|
|
|
16
20
|
public async listPackages(projectName: string): Promise<ApiPackage[]> {
|
|
@@ -32,7 +36,11 @@ export class PackageController {
|
|
|
32
36
|
return _package.getPackageMetadata();
|
|
33
37
|
}
|
|
34
38
|
|
|
35
|
-
async addPackage(
|
|
39
|
+
async addPackage(
|
|
40
|
+
projectName: string,
|
|
41
|
+
body: ApiPackage,
|
|
42
|
+
options?: { autoLoadManifest?: boolean },
|
|
43
|
+
) {
|
|
36
44
|
if (this.projectStore.publisherConfigIsFrozen) {
|
|
37
45
|
throw new FrozenConfigError();
|
|
38
46
|
}
|
|
@@ -46,9 +54,52 @@ export class PackageController {
|
|
|
46
54
|
const result = await project.addPackage(body.name);
|
|
47
55
|
await this.projectStore.addPackageToDatabase(projectName, body.name);
|
|
48
56
|
|
|
57
|
+
if (options?.autoLoadManifest === true) {
|
|
58
|
+
await this.tryLoadExistingManifest(projectName, body.name);
|
|
59
|
+
}
|
|
60
|
+
|
|
49
61
|
return result;
|
|
50
62
|
}
|
|
51
63
|
|
|
64
|
+
/**
|
|
65
|
+
* If there are already manifest entries for this package (e.g. from a
|
|
66
|
+
* previous materialization run), reload all models with the manifest so
|
|
67
|
+
* persist references resolve to the materialized tables immediately.
|
|
68
|
+
*/
|
|
69
|
+
private async tryLoadExistingManifest(
|
|
70
|
+
projectName: string,
|
|
71
|
+
packageName: string,
|
|
72
|
+
): Promise<void> {
|
|
73
|
+
try {
|
|
74
|
+
const repository = this.projectStore.storageManager.getRepository();
|
|
75
|
+
const dbProject = await repository.getProjectByName(projectName);
|
|
76
|
+
if (!dbProject) return;
|
|
77
|
+
|
|
78
|
+
const manifest = await this.manifestService.getManifest(
|
|
79
|
+
dbProject.id,
|
|
80
|
+
packageName,
|
|
81
|
+
);
|
|
82
|
+
if (Object.keys(manifest.entries).length === 0) return;
|
|
83
|
+
|
|
84
|
+
await this.manifestService.reloadManifest(
|
|
85
|
+
dbProject.id,
|
|
86
|
+
packageName,
|
|
87
|
+
projectName,
|
|
88
|
+
);
|
|
89
|
+
logger.info("Auto-loaded existing manifest for added package", {
|
|
90
|
+
projectName,
|
|
91
|
+
packageName,
|
|
92
|
+
entryCount: Object.keys(manifest.entries).length,
|
|
93
|
+
});
|
|
94
|
+
} catch (error) {
|
|
95
|
+
logger.warn("Failed to auto-load manifest for package", {
|
|
96
|
+
projectName,
|
|
97
|
+
packageName,
|
|
98
|
+
error,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
52
103
|
public async deletePackage(projectName: string, packageName: string) {
|
|
53
104
|
if (this.projectStore.publisherConfigIsFrozen) {
|
|
54
105
|
throw new FrozenConfigError();
|
package/src/errors.ts
CHANGED
|
@@ -20,6 +20,12 @@ export function internalErrorToHttpError(error: Error) {
|
|
|
20
20
|
return httpError(424, error.message);
|
|
21
21
|
} else if (error instanceof ConnectionError) {
|
|
22
22
|
return httpError(502, error.message);
|
|
23
|
+
} else if (error instanceof MaterializationNotFoundError) {
|
|
24
|
+
return httpError(404, error.message);
|
|
25
|
+
} else if (error instanceof MaterializationConflictError) {
|
|
26
|
+
return httpError(409, error.message);
|
|
27
|
+
} else if (error instanceof InvalidStateTransitionError) {
|
|
28
|
+
return httpError(409, error.message);
|
|
23
29
|
} else {
|
|
24
30
|
return httpError(500, error.message);
|
|
25
31
|
}
|
|
@@ -90,3 +96,21 @@ export class FrozenConfigError extends Error {
|
|
|
90
96
|
super(message);
|
|
91
97
|
}
|
|
92
98
|
}
|
|
99
|
+
|
|
100
|
+
export class MaterializationNotFoundError extends Error {
|
|
101
|
+
constructor(message: string) {
|
|
102
|
+
super(message);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export class MaterializationConflictError extends Error {
|
|
107
|
+
constructor(message: string) {
|
|
108
|
+
super(message);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export class InvalidStateTransitionError extends Error {
|
|
113
|
+
constructor(message: string) {
|
|
114
|
+
super(message);
|
|
115
|
+
}
|
|
116
|
+
}
|