@malloy-publisher/server 0.0.235 → 0.0.237
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 +83 -27
- package/dist/app/assets/{EnvironmentPage-BsAnavYN.js → EnvironmentPage-DaP6CpgK.js} +1 -1
- package/dist/app/assets/{HomePage-CADE138j.js → HomePage-C9yNw3iu.js} +1 -1
- package/dist/app/assets/{LightMode-Cfh7KzN8.js → LightMode-Be4-G-dX.js} +1 -1
- package/dist/app/assets/{MainPage-CO3pRlnV.js → MainPage-J_rU2SgI.js} +2 -2
- package/dist/app/assets/{MaterializationsPage-p9YjkRXZ.js → MaterializationsPage-DHgPI4MO.js} +1 -1
- package/dist/app/assets/ModelPage-BzXfjTu5.js +1 -0
- package/dist/app/assets/{PackagePage-e4kN75YR.js → PackagePage-ByoSTLJ4.js} +1 -1
- package/dist/app/assets/RouteError-CrSeKN2r.js +1 -0
- package/dist/app/assets/{ThemeEditorPage-CciagFTq.js → ThemeEditorPage-Btxnmhtk.js} +1 -1
- package/dist/app/assets/{WorkbookPage-DNWmkCXa.js → WorkbookPage-D6JLPnWO.js} +1 -1
- package/dist/app/assets/{core-Rj_4rRnA.es-BZyvITuO.js → core-BSRgt1mG.es-Bc_D2Lq4.js} +1 -1
- package/dist/app/assets/{index-CH2AcDzc.js → index-BRijWj6K.js} +15 -15
- package/dist/app/assets/{index-DQa463gC.js → index-BX4D94xw.js} +1 -1
- package/dist/app/assets/{index-VBbcc8s6.js → index-Cvy0xtb7.js} +1 -1
- package/dist/app/assets/{index-DQpV7MyA.js → index-DMAhIJNC.js} +1 -1
- package/dist/app/index.html +1 -1
- package/dist/package_load_worker.mjs +59 -20
- package/dist/server.mjs +1342 -616
- package/package.json +8 -2
- package/.eslintrc.json +0 -44
- package/.prettierignore +0 -1
- package/.prettierrc +0 -4
- package/build.ts +0 -97
- package/dist/app/assets/ModelPage-C1OSTv-x.js +0 -1
- package/dist/app/assets/RouteError-CzbfOkng.js +0 -1
- package/eslint.config.mjs +0 -76
- package/k6-tests/README.md +0 -144
- package/k6-tests/bun.lock +0 -797
- package/k6-tests/load-test/load-test-crud-connections.ts +0 -263
- package/k6-tests/load-test/load-test-crud-packages.ts +0 -461
- package/k6-tests/load-test/load-test-crud-projects.ts +0 -160
- package/k6-tests/load-test/load-test-crud.ts +0 -142
- package/k6-tests/load-test/load-test.ts +0 -784
- package/k6-tests/package.json +0 -27
- package/k6-tests/scripts/run-with-otel.sh +0 -50
- package/k6-tests/smoke-test/smoke-test.ts +0 -158
- package/k6-tests/tsconfig.json +0 -29
- package/k6-tests/utils/client_factory.ts +0 -128
- package/k6-tests/utils/common.ts +0 -489
- package/k6-tests/utils/logger.ts +0 -62
- package/k6-tests/utils/types.d.ts +0 -35
- package/malloy_mcp.dxt +0 -0
- package/publisher.config.example.bigquery.json +0 -33
- package/publisher.config.example.duckdb.json +0 -23
- package/publisher.config.json +0 -23
- package/scripts/bake-duckdb-extensions.js +0 -110
- package/src/config.spec.ts +0 -1535
- package/src/config.theme.spec.ts +0 -178
- package/src/config.ts +0 -1142
- package/src/constants.ts +0 -105
- package/src/controller/compile.controller.ts +0 -40
- package/src/controller/connection.controller.spec.ts +0 -849
- package/src/controller/connection.controller.ts +0 -901
- package/src/controller/database.controller.ts +0 -24
- package/src/controller/materialization.controller.spec.ts +0 -293
- package/src/controller/materialization.controller.ts +0 -319
- package/src/controller/model.controller.ts +0 -164
- package/src/controller/package.controller.spec.ts +0 -273
- package/src/controller/package.controller.ts +0 -306
- package/src/controller/query.controller.ts +0 -152
- package/src/controller/theme.controller.ts +0 -83
- package/src/controller/watch-mode.controller.ts +0 -243
- package/src/data_styles.ts +0 -71
- package/src/default-publisher.config.json +0 -23
- package/src/ducklake_version.spec.ts +0 -163
- package/src/ducklake_version.ts +0 -153
- package/src/errors.spec.ts +0 -119
- package/src/errors.ts +0 -237
- package/src/filter_deprecation.spec.ts +0 -64
- package/src/filter_deprecation.ts +0 -42
- package/src/health.spec.ts +0 -123
- package/src/health.ts +0 -233
- package/src/heap_check.spec.ts +0 -144
- package/src/heap_check.ts +0 -144
- package/src/instrumentation.ts +0 -214
- package/src/json_utils.spec.ts +0 -51
- package/src/json_utils.ts +0 -33
- package/src/logger.spec.ts +0 -210
- package/src/logger.ts +0 -251
- package/src/malloy_pin_prereqs.spec.ts +0 -25
- package/src/materialization_metrics.spec.ts +0 -169
- package/src/materialization_metrics.ts +0 -346
- package/src/mcp/error_messages.spec.ts +0 -35
- package/src/mcp/error_messages.ts +0 -183
- package/src/mcp/handler_utils.spec.ts +0 -108
- package/src/mcp/handler_utils.ts +0 -251
- package/src/mcp/mcp_constants.ts +0 -6
- package/src/mcp/query_envelope.spec.ts +0 -229
- package/src/mcp/query_envelope.ts +0 -240
- package/src/mcp/server.protocol.spec.ts +0 -250
- package/src/mcp/server.ts +0 -87
- package/src/mcp/skills/build_skills_bundle.spec.ts +0 -51
- package/src/mcp/skills/build_skills_bundle.ts +0 -176
- package/src/mcp/skills/skills_bundle.json +0 -1
- package/src/mcp/skills/skills_bundle.spec.ts +0 -171
- package/src/mcp/tool_response.spec.ts +0 -108
- package/src/mcp/tool_response.ts +0 -138
- package/src/mcp/tools/compile_tool.spec.ts +0 -315
- package/src/mcp/tools/compile_tool.ts +0 -208
- package/src/mcp/tools/docs_search/build_docs_index.ts +0 -132
- package/src/mcp/tools/docs_search/malloy_docs_index.json +0 -1
- package/src/mcp/tools/docs_search_tool.spec.ts +0 -32
- package/src/mcp/tools/docs_search_tool.ts +0 -128
- package/src/mcp/tools/embedding_index.spec.ts +0 -1236
- package/src/mcp/tools/embedding_index.ts +0 -808
- package/src/mcp/tools/execute_query_tool.spec.ts +0 -294
- package/src/mcp/tools/execute_query_tool.ts +0 -316
- package/src/mcp/tools/get_context_eval.ts +0 -275
- package/src/mcp/tools/get_context_tool.spec.ts +0 -592
- package/src/mcp/tools/get_context_tool.ts +0 -585
- package/src/mcp/tools/reload_package_tool.spec.ts +0 -232
- package/src/mcp/tools/reload_package_tool.ts +0 -132
- package/src/mcp_config.spec.ts +0 -919
- package/src/mcp_config.ts +0 -425
- package/src/oom_guards.integration.spec.ts +0 -269
- package/src/package_load/package_load_pool.spec.ts +0 -252
- package/src/package_load/package_load_pool.ts +0 -931
- package/src/package_load/package_load_worker.ts +0 -1034
- package/src/package_load/protocol.ts +0 -364
- package/src/package_load/rpc_wait_accountant.spec.ts +0 -109
- package/src/package_load/rpc_wait_accountant.ts +0 -76
- package/src/package_load_metrics.spec.ts +0 -114
- package/src/package_load_metrics.ts +0 -127
- package/src/path_safety.spec.ts +0 -158
- package/src/path_safety.ts +0 -146
- package/src/pg_helpers.spec.ts +0 -223
- package/src/pg_helpers.ts +0 -52
- package/src/query_cap_metrics.spec.ts +0 -89
- package/src/query_cap_metrics.ts +0 -116
- package/src/query_concurrency.spec.ts +0 -247
- package/src/query_concurrency.ts +0 -237
- package/src/query_metadata_metrics.ts +0 -49
- package/src/query_param_utils.ts +0 -29
- package/src/query_timeout.spec.ts +0 -224
- package/src/query_timeout.ts +0 -179
- package/src/runtime/publisher.js +0 -328
- package/src/server-old.ts +0 -988
- package/src/server.ts +0 -2059
- package/src/service/annotations.spec.ts +0 -118
- package/src/service/annotations.ts +0 -91
- package/src/service/authorize.spec.ts +0 -154
- package/src/service/authorize.ts +0 -498
- package/src/service/authorize_integration.spec.ts +0 -2041
- package/src/service/build_plan.spec.ts +0 -685
- package/src/service/build_plan.ts +0 -797
- package/src/service/compile_authorize.spec.ts +0 -85
- package/src/service/compile_fragment_techniques.spec.ts +0 -156
- package/src/service/connection.spec.ts +0 -2360
- package/src/service/connection.ts +0 -2187
- package/src/service/connection_config.spec.ts +0 -734
- package/src/service/connection_config.ts +0 -899
- package/src/service/connection_federation.spec.ts +0 -184
- package/src/service/connection_fingerprint.spec.ts +0 -102
- package/src/service/connection_service.spec.ts +0 -711
- package/src/service/connection_service.ts +0 -291
- package/src/service/cron_evaluator.spec.ts +0 -79
- package/src/service/cron_evaluator.ts +0 -105
- package/src/service/db_utils.spec.ts +0 -1085
- package/src/service/db_utils.ts +0 -1502
- package/src/service/duckdb_instance_isolation.spec.ts +0 -137
- package/src/service/ducklake_lazy_attach.spec.ts +0 -110
- package/src/service/embedding_provider.spec.ts +0 -329
- package/src/service/embedding_provider.ts +0 -236
- package/src/service/environment.ts +0 -2191
- package/src/service/environment_admission.spec.ts +0 -344
- package/src/service/environment_compile.spec.ts +0 -197
- package/src/service/environment_store.spec.ts +0 -2274
- package/src/service/environment_store.ts +0 -2434
- package/src/service/environment_store_anchoring.spec.ts +0 -107
- package/src/service/environment_store_clone.spec.ts +0 -350
- package/src/service/explore_visibility.spec.ts +0 -434
- package/src/service/exports_probe.spec.ts +0 -107
- package/src/service/extension_fetch_policy.spec.ts +0 -256
- package/src/service/filter.spec.ts +0 -458
- package/src/service/filter.ts +0 -341
- package/src/service/filter_bypass.spec.ts +0 -418
- package/src/service/filter_integration.spec.ts +0 -1004
- package/src/service/freshness.spec.ts +0 -183
- package/src/service/freshness.ts +0 -112
- package/src/service/gcs_s3_utils.ts +0 -427
- package/src/service/given.ts +0 -105
- package/src/service/givens_integration.spec.ts +0 -219
- package/src/service/manifest_loader.spec.ts +0 -189
- package/src/service/manifest_loader.ts +0 -156
- package/src/service/materialization_build_session.spec.ts +0 -435
- package/src/service/materialization_build_session.ts +0 -681
- package/src/service/materialization_config_validation.spec.ts +0 -99
- package/src/service/materialization_config_validation.ts +0 -120
- package/src/service/materialization_eligibility.spec.ts +0 -158
- package/src/service/materialization_eligibility.ts +0 -305
- package/src/service/materialization_schedule_surface.spec.ts +0 -256
- package/src/service/materialization_scheduler.spec.ts +0 -289
- package/src/service/materialization_scheduler.ts +0 -304
- package/src/service/materialization_serve_transform.spec.ts +0 -1003
- package/src/service/materialization_serve_transform.ts +0 -779
- package/src/service/materialization_service.spec.ts +0 -2373
- package/src/service/materialization_service.ts +0 -2342
- package/src/service/materialization_test_fixtures.ts +0 -249
- package/src/service/model.spec.ts +0 -1157
- package/src/service/model.ts +0 -3370
- package/src/service/model_limits.spec.ts +0 -209
- package/src/service/model_limits.ts +0 -131
- package/src/service/model_storage_serve.spec.ts +0 -193
- package/src/service/model_storage_serve_joins.spec.ts +0 -193
- package/src/service/package.spec.ts +0 -612
- package/src/service/package.ts +0 -1799
- package/src/service/package_manifest.spec.ts +0 -230
- package/src/service/package_manifest.ts +0 -241
- package/src/service/package_memory_governor.spec.ts +0 -173
- package/src/service/package_memory_governor.ts +0 -233
- package/src/service/package_quote_bound_tables.spec.ts +0 -171
- package/src/service/package_race.spec.ts +0 -208
- package/src/service/package_reload_safety.spec.ts +0 -193
- package/src/service/package_rollback.spec.ts +0 -190
- package/src/service/package_worker_path.spec.ts +0 -645
- package/src/service/path_injection.spec.ts +0 -39
- package/src/service/persist_annotation_validation.spec.ts +0 -89
- package/src/service/persist_annotation_validation.ts +0 -59
- package/src/service/persistence_policy.spec.ts +0 -374
- package/src/service/proxy.spec.ts +0 -414
- package/src/service/proxy.ts +0 -248
- package/src/service/query_boundary.spec.ts +0 -470
- package/src/service/query_metadata.spec.ts +0 -408
- package/src/service/query_metadata.ts +0 -492
- package/src/service/query_metadata_identity.spec.ts +0 -149
- package/src/service/query_text.spec.ts +0 -79
- package/src/service/query_text.ts +0 -43
- package/src/service/quoting.spec.ts +0 -135
- package/src/service/quoting.ts +0 -78
- package/src/service/resolve_environment.ts +0 -15
- package/src/service/restricted_mode.spec.ts +0 -299
- package/src/service/source_extraction.ts +0 -225
- package/src/service/theme_store.ts +0 -199
- package/src/storage/DatabaseInterface.ts +0 -198
- package/src/storage/StorageManager.ts +0 -113
- package/src/storage/duckdb/ConnectionRepository.ts +0 -143
- package/src/storage/duckdb/DuckDBConnection.ts +0 -123
- package/src/storage/duckdb/DuckDBRepository.ts +0 -208
- package/src/storage/duckdb/EnvironmentRepository.ts +0 -148
- package/src/storage/duckdb/MaterializationRepository.spec.ts +0 -191
- package/src/storage/duckdb/MaterializationRepository.ts +0 -336
- package/src/storage/duckdb/PackageRepository.ts +0 -135
- package/src/storage/duckdb/schema.ts +0 -229
- package/src/stream_helpers.spec.ts +0 -280
- package/src/stream_helpers.ts +0 -162
- package/src/telemetry.ts +0 -20
- package/src/test_helpers/metrics_harness.ts +0 -166
- package/src/theme_key_parity.spec.ts +0 -57
- package/src/utils.ts +0 -29
- package/tests/fixtures/authorize-compile/model.malloy +0 -9
- package/tests/fixtures/authorize-compile/publisher.json +0 -4
- package/tests/fixtures/html-pages-nopublic/model.malloy +0 -1
- package/tests/fixtures/html-pages-nopublic/publisher.json +0 -5
- package/tests/fixtures/html-pages-test/data.csv +0 -3
- package/tests/fixtures/html-pages-test/public/assets/app.css +0 -3
- package/tests/fixtures/html-pages-test/public/barehtml.html +0 -4
- package/tests/fixtures/html-pages-test/public/bodymeta.html +0 -8
- package/tests/fixtures/html-pages-test/public/data.json +0 -1
- package/tests/fixtures/html-pages-test/public/fitcomment.html +0 -11
- package/tests/fixtures/html-pages-test/public/index.html +0 -9
- package/tests/fixtures/html-pages-test/public/nohead.html +0 -8
- package/tests/fixtures/html-pages-test/public/notfit.html +0 -13
- package/tests/fixtures/html-pages-test/public/slides.html +0 -12
- package/tests/fixtures/html-pages-test/public/sub/page2.html +0 -9
- package/tests/fixtures/html-pages-test/public/unterminated.html +0 -10
- package/tests/fixtures/html-pages-test/publisher.json +0 -5
- package/tests/fixtures/html-pages-test/report.malloy +0 -1
- package/tests/fixtures/persist-multi-level/data/orders.csv +0 -5
- package/tests/fixtures/persist-multi-level/multi_level.malloy +0 -18
- package/tests/fixtures/persist-multi-level/publisher.json +0 -5
- package/tests/fixtures/persist-schedule-test/data/orders.csv +0 -5
- package/tests/fixtures/persist-schedule-test/persist_schedule_test.malloy +0 -11
- package/tests/fixtures/persist-schedule-test/publisher.json +0 -7
- package/tests/fixtures/persist-schedule-warn-test/data/orders.csv +0 -5
- package/tests/fixtures/persist-schedule-warn-test/persist_warn_test.malloy +0 -11
- package/tests/fixtures/persist-schedule-warn-test/publisher.json +0 -6
- package/tests/fixtures/persist-test/data/orders.csv +0 -5
- package/tests/fixtures/persist-test/persist_test.malloy +0 -11
- package/tests/fixtures/persist-test/publisher.json +0 -5
- package/tests/fixtures/publisher.config.json +0 -15
- package/tests/fixtures/query-givens/data/orders.csv +0 -7
- package/tests/fixtures/query-givens/model.malloy +0 -34
- package/tests/fixtures/query-givens/publisher.json +0 -5
- package/tests/fixtures/xlsx/database.xlsx +0 -0
- package/tests/harness/mcp_test_setup.ts +0 -332
- package/tests/harness/rest_e2e.ts +0 -68
- package/tests/integration/authorize/compile_authorize_http.integration.spec.ts +0 -92
- package/tests/integration/concurrent_package/concurrent_package.integration.spec.ts +0 -280
- package/tests/integration/duckdb_storage/duckdb_storage.integration.spec.ts +0 -138
- package/tests/integration/first_boot/readiness_line.integration.spec.ts +0 -177
- package/tests/integration/html_pages/html_pages.integration.spec.ts +0 -440
- package/tests/integration/legacy_routes/legacy_routes.integration.spec.ts +0 -259
- package/tests/integration/materialization/environment_list.integration.spec.ts +0 -133
- package/tests/integration/materialization/freshness_gate.integration.spec.ts +0 -292
- package/tests/integration/materialization/manifest_binding.integration.spec.ts +0 -430
- package/tests/integration/materialization/materialization_lifecycle.integration.spec.ts +0 -441
- package/tests/integration/materialization/orchestrated_rebind.integration.spec.ts +0 -150
- package/tests/integration/materialization/reference_manifest.integration.spec.ts +0 -251
- package/tests/integration/materialization/schedule_edit.integration.spec.ts +0 -126
- package/tests/integration/materialization/scheduler.integration.spec.ts +0 -200
- package/tests/integration/materialization/scheduler_recovery.integration.spec.ts +0 -172
- package/tests/integration/materialization/scheduler_transitions.integration.spec.ts +0 -256
- package/tests/integration/materialization/scheduler_wiring.integration.spec.ts +0 -143
- package/tests/integration/mcp/mcp_execute_query_tool.integration.spec.ts +0 -438
- package/tests/integration/mcp/mcp_get_context_semantic.integration.spec.ts +0 -235
- package/tests/integration/mcp/mcp_transport.integration.spec.ts +0 -98
- package/tests/integration/query_givens/query_givens.integration.spec.ts +0 -146
- package/tests/integration/query_givens/query_givens_authorize.integration.spec.ts +0 -121
- package/tests/integration/sdk_givens/sdk_givens.integration.spec.ts +0 -110
- package/tests/integration/watch-mode/watch_mode.integration.spec.ts +0 -421
- package/tests/unit/controller/theme.controller.spec.ts +0 -141
- package/tests/unit/duckdb/attached_databases.test.ts +0 -1243
- package/tests/unit/duckdb/duckdb_connection.test.ts +0 -181
- package/tests/unit/duckdb/legacy_schema_migration.test.ts +0 -197
- package/tests/unit/duckdb/repositories.test.ts +0 -208
- package/tests/unit/ducklake/ducklake.test.ts +0 -952
- package/tests/unit/service/theme_store.spec.ts +0 -139
- package/tsconfig.json +0 -32
|
@@ -1,164 +0,0 @@
|
|
|
1
|
-
import { components } from "../api";
|
|
2
|
-
import { getQueryTimeoutMs } from "../config";
|
|
3
|
-
import { ModelNotFoundError } from "../errors";
|
|
4
|
-
import { logger } from "../logger";
|
|
5
|
-
import { runWithQueryTimeout } from "../query_timeout";
|
|
6
|
-
import { EnvironmentStore } from "../service/environment_store";
|
|
7
|
-
import type { FilterParams } from "../service/filter";
|
|
8
|
-
import type { GivenValue } from "@malloydata/malloy";
|
|
9
|
-
|
|
10
|
-
type ApiNotebook = components["schemas"]["Notebook"];
|
|
11
|
-
type ApiModel = components["schemas"]["Model"];
|
|
12
|
-
type ApiCompiledModel = components["schemas"]["CompiledModel"];
|
|
13
|
-
type ApiRawNotebook = components["schemas"]["RawNotebook"];
|
|
14
|
-
export class ModelController {
|
|
15
|
-
private environmentStore: EnvironmentStore;
|
|
16
|
-
|
|
17
|
-
constructor(environmentStore: EnvironmentStore) {
|
|
18
|
-
this.environmentStore = environmentStore;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
public async listModels(
|
|
22
|
-
environmentName: string,
|
|
23
|
-
packageName: string,
|
|
24
|
-
): Promise<ApiModel[]> {
|
|
25
|
-
const environment = await this.environmentStore.getEnvironment(
|
|
26
|
-
environmentName,
|
|
27
|
-
false,
|
|
28
|
-
);
|
|
29
|
-
const p = await environment.getPackage(packageName, false);
|
|
30
|
-
return p.listModels();
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
public async listNotebooks(
|
|
34
|
-
environmentName: string,
|
|
35
|
-
packageName: string,
|
|
36
|
-
): Promise<ApiNotebook[]> {
|
|
37
|
-
const environment = await this.environmentStore.getEnvironment(
|
|
38
|
-
environmentName,
|
|
39
|
-
false,
|
|
40
|
-
);
|
|
41
|
-
const p = await environment.getPackage(packageName, false);
|
|
42
|
-
return p.listNotebooks();
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
public async getModel(
|
|
46
|
-
environmentName: string,
|
|
47
|
-
packageName: string,
|
|
48
|
-
modelPath: string,
|
|
49
|
-
): Promise<ApiCompiledModel> {
|
|
50
|
-
try {
|
|
51
|
-
const environment = await this.environmentStore.getEnvironment(
|
|
52
|
-
environmentName,
|
|
53
|
-
false,
|
|
54
|
-
);
|
|
55
|
-
const p = await environment.getPackage(packageName, false);
|
|
56
|
-
const model = p.getModel(modelPath);
|
|
57
|
-
if (!model) {
|
|
58
|
-
throw new ModelNotFoundError(`${modelPath} does not exist`);
|
|
59
|
-
}
|
|
60
|
-
if (model.getType() === "notebook") {
|
|
61
|
-
throw new ModelNotFoundError(`${modelPath} is a notebook`);
|
|
62
|
-
}
|
|
63
|
-
return await model.getModel();
|
|
64
|
-
} catch (error) {
|
|
65
|
-
// Re-throw ModelNotFoundError as-is
|
|
66
|
-
if (error instanceof ModelNotFoundError) {
|
|
67
|
-
throw error;
|
|
68
|
-
}
|
|
69
|
-
// Wrap other errors with more context
|
|
70
|
-
throw new Error(
|
|
71
|
-
`Failed to get model ${modelPath} from package ${packageName} in environment ${environmentName}: ${error}`,
|
|
72
|
-
);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
public async getNotebook(
|
|
77
|
-
environmentName: string,
|
|
78
|
-
packageName: string,
|
|
79
|
-
notebookPath: string,
|
|
80
|
-
): Promise<ApiRawNotebook> {
|
|
81
|
-
const environment = await this.environmentStore.getEnvironment(
|
|
82
|
-
environmentName,
|
|
83
|
-
false,
|
|
84
|
-
);
|
|
85
|
-
const p = await environment.getPackage(packageName, false);
|
|
86
|
-
const model = p.getModel(notebookPath);
|
|
87
|
-
if (!model) {
|
|
88
|
-
throw new ModelNotFoundError(`${notebookPath} does not exist`);
|
|
89
|
-
}
|
|
90
|
-
if (model.getType() === "model") {
|
|
91
|
-
throw new ModelNotFoundError(`${notebookPath} is a model`);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return model.getNotebook();
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public async executeNotebookCell(
|
|
98
|
-
environmentName: string,
|
|
99
|
-
packageName: string,
|
|
100
|
-
notebookPath: string,
|
|
101
|
-
cellIndex: number,
|
|
102
|
-
filterParams?: FilterParams,
|
|
103
|
-
bypassFilters?: boolean,
|
|
104
|
-
givens?: Record<string, GivenValue>,
|
|
105
|
-
): Promise<{
|
|
106
|
-
type: "code" | "markdown";
|
|
107
|
-
text: string;
|
|
108
|
-
queryName?: string;
|
|
109
|
-
result?: string;
|
|
110
|
-
newSources?: string[];
|
|
111
|
-
}> {
|
|
112
|
-
const environment = await this.environmentStore.getEnvironment(
|
|
113
|
-
environmentName,
|
|
114
|
-
false,
|
|
115
|
-
);
|
|
116
|
-
// Shed load before any disk / DB work; same rationale as
|
|
117
|
-
// QueryController.getQuery — already-loaded packages bypass the
|
|
118
|
-
// package-load admission gate.
|
|
119
|
-
environment.assertCanAdmitQuery();
|
|
120
|
-
const p = await environment.getPackage(packageName, false);
|
|
121
|
-
const model = p.getModel(notebookPath);
|
|
122
|
-
if (!model) {
|
|
123
|
-
throw new ModelNotFoundError(`${notebookPath} does not exist`);
|
|
124
|
-
}
|
|
125
|
-
if (model.getType() === "model") {
|
|
126
|
-
throw new ModelNotFoundError(`${notebookPath} is a model`);
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
return runWithQueryTimeout(
|
|
130
|
-
(abortSignal) =>
|
|
131
|
-
model.executeNotebookCell(
|
|
132
|
-
cellIndex,
|
|
133
|
-
filterParams,
|
|
134
|
-
bypassFilters,
|
|
135
|
-
givens,
|
|
136
|
-
abortSignal,
|
|
137
|
-
{
|
|
138
|
-
environment: environmentName,
|
|
139
|
-
// The environment owns the connection configs, so the default
|
|
140
|
-
// and enforced layers are read here rather than from the model.
|
|
141
|
-
connectionMetadata: (connectionName) => {
|
|
142
|
-
try {
|
|
143
|
-
const connection =
|
|
144
|
-
environment.getApiConnection(connectionName);
|
|
145
|
-
return {
|
|
146
|
-
default: connection.queryMetadata,
|
|
147
|
-
enforced: connection.queryMetadataEnforced,
|
|
148
|
-
};
|
|
149
|
-
} catch (error) {
|
|
150
|
-
// Fails open, and says so: what an unreadable
|
|
151
|
-
// connection costs is the enforced layer.
|
|
152
|
-
logger.debug(
|
|
153
|
-
"No query-metadata layers for connection",
|
|
154
|
-
{ connectionName, error },
|
|
155
|
-
);
|
|
156
|
-
return null;
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
},
|
|
160
|
-
),
|
|
161
|
-
getQueryTimeoutMs(),
|
|
162
|
-
);
|
|
163
|
-
}
|
|
164
|
-
}
|
|
@@ -1,273 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, it } from "bun:test";
|
|
2
|
-
import sinon from "sinon";
|
|
3
|
-
|
|
4
|
-
import { BadRequestError } from "../errors";
|
|
5
|
-
import type { EnvironmentStore } from "../service/environment_store";
|
|
6
|
-
import { PackageController } from "./package.controller";
|
|
7
|
-
|
|
8
|
-
describe("PackageController.addPackage explores validation", () => {
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
sinon.restore();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("no-location: rejects invalid explores and rolls back via unloadPackage (NOT deletePackage)", async () => {
|
|
14
|
-
// The no-location path registers a PRE-EXISTING user directory, so a bad
|
|
15
|
-
// manifest must unload it from memory — never deletePackage, which would
|
|
16
|
-
// delete the user's files.
|
|
17
|
-
const invalidMsg =
|
|
18
|
-
"Invalid explores entry 'missing.malloy' in publisher.json: file not found";
|
|
19
|
-
const mockPackage = {
|
|
20
|
-
formatInvalidExplores: () => invalidMsg,
|
|
21
|
-
formatInvalidPersistencePolicy: () => "",
|
|
22
|
-
formatPersistenceCollisionRejections: () => "",
|
|
23
|
-
};
|
|
24
|
-
const unloadPackage = sinon.stub().resolves(undefined);
|
|
25
|
-
const deletePackage = sinon.stub().resolves(undefined);
|
|
26
|
-
const addPackage = sinon.stub().resolves(mockPackage);
|
|
27
|
-
const environment = { addPackage, unloadPackage, deletePackage };
|
|
28
|
-
const getEnvironment = sinon.stub().resolves(environment);
|
|
29
|
-
const addPackageToDatabase = sinon.stub().resolves(undefined);
|
|
30
|
-
const environmentStore = {
|
|
31
|
-
publisherConfigIsFrozen: false,
|
|
32
|
-
getEnvironment,
|
|
33
|
-
addPackageToDatabase,
|
|
34
|
-
} as unknown as EnvironmentStore;
|
|
35
|
-
|
|
36
|
-
const controller = new PackageController(environmentStore);
|
|
37
|
-
|
|
38
|
-
await expect(
|
|
39
|
-
controller.addPackage("env", {
|
|
40
|
-
name: "pkg",
|
|
41
|
-
description: "test",
|
|
42
|
-
explores: ["missing.malloy"],
|
|
43
|
-
}),
|
|
44
|
-
).rejects.toBeInstanceOf(BadRequestError);
|
|
45
|
-
|
|
46
|
-
expect(unloadPackage.calledOnceWith("pkg")).toBe(true);
|
|
47
|
-
expect(deletePackage.called).toBe(false);
|
|
48
|
-
expect(addPackageToDatabase.called).toBe(false);
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
it("location: validation runs inside installPackage's rollback window, not as a controller delete", async () => {
|
|
52
|
-
// For the location path the tree was freshly downloaded, so validation is
|
|
53
|
-
// delegated to installPackage (which rolls the swap back on failure). The
|
|
54
|
-
// controller passes a validator and does NOT call delete/unload itself.
|
|
55
|
-
const invalidMsg =
|
|
56
|
-
"Invalid explores entry 'missing.malloy' in publisher.json: file not found";
|
|
57
|
-
const mockPackage = {
|
|
58
|
-
formatInvalidExplores: () => invalidMsg,
|
|
59
|
-
formatInvalidPersistencePolicy: () => "",
|
|
60
|
-
formatPersistenceCollisionRejections: () => "",
|
|
61
|
-
};
|
|
62
|
-
// installPackage mimics the real contract: invoke the validator and, if it
|
|
63
|
-
// returns a message, throw BadRequestError (after its internal rollback).
|
|
64
|
-
const installPackage = sinon
|
|
65
|
-
.stub()
|
|
66
|
-
.callsFake(
|
|
67
|
-
async (
|
|
68
|
-
_name: string,
|
|
69
|
-
_downloader: unknown,
|
|
70
|
-
validate?: (pkg: unknown) => string | undefined,
|
|
71
|
-
) => {
|
|
72
|
-
const msg = validate?.(mockPackage);
|
|
73
|
-
if (msg) throw new BadRequestError(msg);
|
|
74
|
-
return mockPackage;
|
|
75
|
-
},
|
|
76
|
-
);
|
|
77
|
-
const unloadPackage = sinon.stub().resolves(undefined);
|
|
78
|
-
const deletePackage = sinon.stub().resolves(undefined);
|
|
79
|
-
const environment = { installPackage, unloadPackage, deletePackage };
|
|
80
|
-
const getEnvironment = sinon.stub().resolves(environment);
|
|
81
|
-
const addPackageToDatabase = sinon.stub().resolves(undefined);
|
|
82
|
-
const environmentStore = {
|
|
83
|
-
publisherConfigIsFrozen: false,
|
|
84
|
-
getEnvironment,
|
|
85
|
-
addPackageToDatabase,
|
|
86
|
-
} as unknown as EnvironmentStore;
|
|
87
|
-
|
|
88
|
-
const controller = new PackageController(environmentStore);
|
|
89
|
-
|
|
90
|
-
await expect(
|
|
91
|
-
controller.addPackage("env", {
|
|
92
|
-
name: "pkg",
|
|
93
|
-
description: "test",
|
|
94
|
-
location: "gs://bucket/pkg.zip",
|
|
95
|
-
explores: ["missing.malloy"],
|
|
96
|
-
}),
|
|
97
|
-
).rejects.toBeInstanceOf(BadRequestError);
|
|
98
|
-
|
|
99
|
-
expect(installPackage.calledOnce).toBe(true);
|
|
100
|
-
expect(typeof installPackage.firstCall.args[2]).toBe("function");
|
|
101
|
-
expect(deletePackage.called).toBe(false);
|
|
102
|
-
expect(unloadPackage.called).toBe(false);
|
|
103
|
-
expect(addPackageToDatabase.called).toBe(false);
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
it("persists when explores are valid (no-location)", async () => {
|
|
107
|
-
const mockPackage = {
|
|
108
|
-
formatInvalidExplores: () => "",
|
|
109
|
-
formatInvalidPersistencePolicy: () => "",
|
|
110
|
-
formatPersistenceCollisionRejections: () => "",
|
|
111
|
-
};
|
|
112
|
-
const addPackage = sinon.stub().resolves(mockPackage);
|
|
113
|
-
const getEnvironment = sinon.stub().resolves({ addPackage });
|
|
114
|
-
const addPackageToDatabase = sinon.stub().resolves(undefined);
|
|
115
|
-
const environmentStore = {
|
|
116
|
-
publisherConfigIsFrozen: false,
|
|
117
|
-
getEnvironment,
|
|
118
|
-
addPackageToDatabase,
|
|
119
|
-
} as unknown as EnvironmentStore;
|
|
120
|
-
|
|
121
|
-
const controller = new PackageController(environmentStore);
|
|
122
|
-
|
|
123
|
-
await controller.addPackage("env", {
|
|
124
|
-
name: "pkg",
|
|
125
|
-
description: "test",
|
|
126
|
-
explores: ["index.malloy"],
|
|
127
|
-
});
|
|
128
|
-
|
|
129
|
-
expect(addPackageToDatabase.calledOnceWith("env", "pkg")).toBe(true);
|
|
130
|
-
});
|
|
131
|
-
});
|
|
132
|
-
|
|
133
|
-
describe("PackageController.addPackage persistence policy validation", () => {
|
|
134
|
-
afterEach(() => {
|
|
135
|
-
sinon.restore();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("rejects a publish whose persistence policy is invalid (no-location path)", async () => {
|
|
139
|
-
// Valid explores but an invalid persistence policy (e.g. a schedule on a
|
|
140
|
-
// package-scoped package): the publish must still 400 (strict-at-publish,
|
|
141
|
-
// same split as explores — load merely warns) and roll back via
|
|
142
|
-
// unloadPackage.
|
|
143
|
-
const cronMsg =
|
|
144
|
-
'materialization.schedule (cron) in publisher.json requires "scope": ' +
|
|
145
|
-
'"version".';
|
|
146
|
-
const mockPackage = {
|
|
147
|
-
formatInvalidExplores: () => "",
|
|
148
|
-
formatInvalidPersistencePolicy: () => cronMsg,
|
|
149
|
-
formatPersistenceCollisionRejections: () => "",
|
|
150
|
-
};
|
|
151
|
-
const unloadPackage = sinon.stub().resolves(undefined);
|
|
152
|
-
const addPackage = sinon.stub().resolves(mockPackage);
|
|
153
|
-
const environment = { addPackage, unloadPackage };
|
|
154
|
-
const getEnvironment = sinon.stub().resolves(environment);
|
|
155
|
-
const addPackageToDatabase = sinon.stub().resolves(undefined);
|
|
156
|
-
const environmentStore = {
|
|
157
|
-
publisherConfigIsFrozen: false,
|
|
158
|
-
getEnvironment,
|
|
159
|
-
addPackageToDatabase,
|
|
160
|
-
} as unknown as EnvironmentStore;
|
|
161
|
-
|
|
162
|
-
const controller = new PackageController(environmentStore);
|
|
163
|
-
|
|
164
|
-
await expect(
|
|
165
|
-
controller.addPackage("env", { name: "pkg", description: "test" }),
|
|
166
|
-
).rejects.toThrow(cronMsg);
|
|
167
|
-
|
|
168
|
-
expect(unloadPackage.calledOnceWith("pkg")).toBe(true);
|
|
169
|
-
expect(addPackageToDatabase.called).toBe(false);
|
|
170
|
-
});
|
|
171
|
-
|
|
172
|
-
it("location path: the persistence-policy gate runs inside installPackage's rollback window", async () => {
|
|
173
|
-
const cronMsg =
|
|
174
|
-
'materialization.schedule (cron) in publisher.json requires "scope": ' +
|
|
175
|
-
'"version".';
|
|
176
|
-
const mockPackage = {
|
|
177
|
-
formatInvalidExplores: () => "",
|
|
178
|
-
formatInvalidPersistencePolicy: () => cronMsg,
|
|
179
|
-
formatPersistenceCollisionRejections: () => "",
|
|
180
|
-
};
|
|
181
|
-
const installPackage = sinon
|
|
182
|
-
.stub()
|
|
183
|
-
.callsFake(
|
|
184
|
-
async (
|
|
185
|
-
_name: string,
|
|
186
|
-
_downloader: unknown,
|
|
187
|
-
validate?: (pkg: unknown) => string | undefined,
|
|
188
|
-
) => {
|
|
189
|
-
const msg = validate?.(mockPackage);
|
|
190
|
-
if (msg) throw new BadRequestError(msg);
|
|
191
|
-
return mockPackage;
|
|
192
|
-
},
|
|
193
|
-
);
|
|
194
|
-
const environment = { installPackage };
|
|
195
|
-
const getEnvironment = sinon.stub().resolves(environment);
|
|
196
|
-
const addPackageToDatabase = sinon.stub().resolves(undefined);
|
|
197
|
-
const environmentStore = {
|
|
198
|
-
publisherConfigIsFrozen: false,
|
|
199
|
-
getEnvironment,
|
|
200
|
-
addPackageToDatabase,
|
|
201
|
-
} as unknown as EnvironmentStore;
|
|
202
|
-
|
|
203
|
-
const controller = new PackageController(environmentStore);
|
|
204
|
-
|
|
205
|
-
await expect(
|
|
206
|
-
controller.addPackage("env", {
|
|
207
|
-
name: "pkg",
|
|
208
|
-
description: "test",
|
|
209
|
-
location: "gs://bucket/pkg.zip",
|
|
210
|
-
}),
|
|
211
|
-
).rejects.toThrow(cronMsg);
|
|
212
|
-
|
|
213
|
-
expect(addPackageToDatabase.called).toBe(false);
|
|
214
|
-
});
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
describe("PackageController.updatePackage explores validation", () => {
|
|
218
|
-
afterEach(() => {
|
|
219
|
-
sinon.restore();
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it("location update: validates the EFFECTIVE explores (body override) before the swap commits", async () => {
|
|
223
|
-
// body.location triggers a reinstall (atomic swap). The effective explores
|
|
224
|
-
// — the body override here — must be validated inside installPackage so a
|
|
225
|
-
// bad update rolls back to the previous tree instead of swapping in the
|
|
226
|
-
// rejected one and 400-ing after the fact.
|
|
227
|
-
const invalidMsg =
|
|
228
|
-
"Invalid explores entry 'nope.malloy' in publisher.json: file not found";
|
|
229
|
-
// The mock package validates whatever override it's handed.
|
|
230
|
-
const mockPackage = {
|
|
231
|
-
formatInvalidExplores: (override?: string[]) =>
|
|
232
|
-
override?.includes("nope.malloy") ? invalidMsg : "",
|
|
233
|
-
formatInvalidPersistencePolicy: () => "",
|
|
234
|
-
formatPersistenceCollisionRejections: () => "",
|
|
235
|
-
};
|
|
236
|
-
const installPackage = sinon
|
|
237
|
-
.stub()
|
|
238
|
-
.callsFake(
|
|
239
|
-
async (
|
|
240
|
-
_name: string,
|
|
241
|
-
_downloader: unknown,
|
|
242
|
-
validate?: (pkg: unknown) => string | undefined,
|
|
243
|
-
) => {
|
|
244
|
-
const msg = validate?.(mockPackage);
|
|
245
|
-
if (msg) throw new BadRequestError(msg);
|
|
246
|
-
return mockPackage;
|
|
247
|
-
},
|
|
248
|
-
);
|
|
249
|
-
const updatePackage = sinon.stub().resolves(mockPackage);
|
|
250
|
-
const environment = { installPackage, updatePackage };
|
|
251
|
-
const getEnvironment = sinon.stub().resolves(environment);
|
|
252
|
-
const addPackageToDatabase = sinon.stub().resolves(undefined);
|
|
253
|
-
const environmentStore = {
|
|
254
|
-
publisherConfigIsFrozen: false,
|
|
255
|
-
getEnvironment,
|
|
256
|
-
addPackageToDatabase,
|
|
257
|
-
} as unknown as EnvironmentStore;
|
|
258
|
-
|
|
259
|
-
const controller = new PackageController(environmentStore);
|
|
260
|
-
|
|
261
|
-
await expect(
|
|
262
|
-
controller.updatePackage("env", "pkg", {
|
|
263
|
-
name: "pkg",
|
|
264
|
-
location: "gs://bucket/pkg.zip",
|
|
265
|
-
explores: ["nope.malloy"],
|
|
266
|
-
}),
|
|
267
|
-
).rejects.toBeInstanceOf(BadRequestError);
|
|
268
|
-
|
|
269
|
-
// The rejected swap never reached the metadata-apply / persist steps.
|
|
270
|
-
expect(updatePackage.called).toBe(false);
|
|
271
|
-
expect(addPackageToDatabase.called).toBe(false);
|
|
272
|
-
});
|
|
273
|
-
});
|