@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,184 +0,0 @@
|
|
|
1
|
-
// Unit contract for the build-scoped credential primitives: the SQL a build
|
|
2
|
-
// session issues to (a) RW-attach a destination DuckLake and (b) federate a
|
|
3
|
-
// source warehouse for a native query-passthrough. `runSQL` is stubbed so no
|
|
4
|
-
// live warehouse / catalog is touched — this pins the SQL *shape* (handles,
|
|
5
|
-
// secret scoping, read-only-ness, escaping); live behavior is the measured
|
|
6
|
-
// spike's job.
|
|
7
|
-
import { DuckDBConnection } from "@malloydata/db-duckdb";
|
|
8
|
-
import { describe, expect, it } from "bun:test";
|
|
9
|
-
import * as sinon from "sinon";
|
|
10
|
-
import type { components } from "../api";
|
|
11
|
-
import {
|
|
12
|
-
attachDuckLakeReadWrite,
|
|
13
|
-
federateSourceForPassthrough,
|
|
14
|
-
} from "./connection";
|
|
15
|
-
|
|
16
|
-
/** A real in-memory DuckDB connection with runSQL stubbed to capture SQL. */
|
|
17
|
-
function stubbedConnection(): { conn: DuckDBConnection; sql: string[] } {
|
|
18
|
-
const conn = new DuckDBConnection("build", ":memory:");
|
|
19
|
-
const sql: string[] = [];
|
|
20
|
-
sinon.stub(conn, "runSQL").callsFake(async (q: string) => {
|
|
21
|
-
sql.push(q);
|
|
22
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
23
|
-
return { rows: [], totalRows: 0, runStats: {} } as any;
|
|
24
|
-
});
|
|
25
|
-
return { conn, sql };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const SERVICE_ACCOUNT = JSON.stringify({
|
|
29
|
-
type: "service_account",
|
|
30
|
-
project_id: "sa-project",
|
|
31
|
-
private_key: "-----BEGIN PRIVATE KEY-----\nabc\n-----END PRIVATE KEY-----",
|
|
32
|
-
client_email: "svc@sa-project.iam.gserviceaccount.com",
|
|
33
|
-
});
|
|
34
|
-
|
|
35
|
-
describe("federateSourceForPassthrough", () => {
|
|
36
|
-
it("bigquery: creates a project-scoped SECRET and returns the project id as handle", async () => {
|
|
37
|
-
const { conn, sql } = stubbedConnection();
|
|
38
|
-
const result = await federateSourceForPassthrough(conn, "bigquery", {
|
|
39
|
-
name: "src_bq",
|
|
40
|
-
bigqueryConnection: {
|
|
41
|
-
defaultProjectId: "cfg-project",
|
|
42
|
-
serviceAccountKeyJson: SERVICE_ACCOUNT,
|
|
43
|
-
} as components["schemas"]["BigqueryConnection"],
|
|
44
|
-
});
|
|
45
|
-
expect(result).toEqual({ handle: "sa-project", sourceType: "bigquery" });
|
|
46
|
-
const secret = sql.find((s) => s.includes("CREATE OR REPLACE SECRET"));
|
|
47
|
-
expect(secret).toBeDefined();
|
|
48
|
-
expect(secret).toContain("TYPE BIGQUERY");
|
|
49
|
-
expect(secret).toContain("SCOPE 'bq://sa-project'");
|
|
50
|
-
expect(secret).toContain("SERVICE_ACCOUNT_JSON");
|
|
51
|
-
// Never ATTACH for a bigquery passthrough.
|
|
52
|
-
expect(sql.some((s) => s.includes("ATTACH"))).toBe(false);
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("snowflake: creates a SECRET and returns the secret name as handle (no ATTACH)", async () => {
|
|
56
|
-
const { conn, sql } = stubbedConnection();
|
|
57
|
-
const result = await federateSourceForPassthrough(conn, "snowflake", {
|
|
58
|
-
name: "src_sf",
|
|
59
|
-
snowflakeConnection: {
|
|
60
|
-
account: "acct",
|
|
61
|
-
username: "user",
|
|
62
|
-
password: "p'wd",
|
|
63
|
-
database: "DB",
|
|
64
|
-
warehouse: "WH",
|
|
65
|
-
} as components["schemas"]["SnowflakeConnection"],
|
|
66
|
-
});
|
|
67
|
-
expect(result.sourceType).toBe("snowflake");
|
|
68
|
-
expect(result.handle).toBe("secret_snowflake_src_sf");
|
|
69
|
-
const secret = sql.find((s) => s.includes("CREATE OR REPLACE SECRET"));
|
|
70
|
-
expect(secret).toContain("TYPE snowflake");
|
|
71
|
-
expect(secret).toContain("ACCOUNT 'acct'");
|
|
72
|
-
// Single quotes in a value are doubled (escapeSQL).
|
|
73
|
-
expect(secret).toContain("PASSWORD 'p''wd'");
|
|
74
|
-
expect(sql.some((s) => s.includes("ATTACH"))).toBe(false);
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
it("postgres: ATTACHes READ_ONLY and returns the alias as handle", async () => {
|
|
78
|
-
const { conn, sql } = stubbedConnection();
|
|
79
|
-
const result = await federateSourceForPassthrough(conn, "postgres", {
|
|
80
|
-
name: "src_pg",
|
|
81
|
-
postgresConnection: {
|
|
82
|
-
host: "h",
|
|
83
|
-
port: 5432,
|
|
84
|
-
databaseName: "d",
|
|
85
|
-
userName: "u",
|
|
86
|
-
password: "pw",
|
|
87
|
-
} as components["schemas"]["PostgresConnection"],
|
|
88
|
-
});
|
|
89
|
-
expect(result).toEqual({ handle: "src_pg", sourceType: "postgres" });
|
|
90
|
-
const attach = sql.find((s) => s.startsWith("ATTACH"));
|
|
91
|
-
expect(attach).toBeDefined();
|
|
92
|
-
// OR REPLACE for within-session idempotency (a re-attach of the identical
|
|
93
|
-
// source on one session is a no-op rebind). Cross-build/cross-tenant alias
|
|
94
|
-
// collisions are prevented upstream by each build running on its OWN
|
|
95
|
-
// private DuckDB instance (createIsolatedBuildSession); this is just
|
|
96
|
-
// belt-and-suspenders.
|
|
97
|
-
expect(attach).toStartWith("ATTACH OR REPLACE ");
|
|
98
|
-
// The ATTACH alias is dialect-quoted; the handle stays the raw name (it
|
|
99
|
-
// becomes the postgres_query string literal, which matches the catalog).
|
|
100
|
-
expect(attach).toContain('AS "src_pg" (TYPE postgres, READ_ONLY)');
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
it("postgres: re-federating the same source on one session is idempotent (no 'already exists')", async () => {
|
|
104
|
-
// Within one session, federating the same source twice must not throw:
|
|
105
|
-
// both attaches use OR REPLACE (a no-op rebind to the identical source).
|
|
106
|
-
// (A real DuckDB would raise "database ... already exists" on a plain
|
|
107
|
-
// re-ATTACH; here runSQL is stubbed, so we pin the SQL contract.)
|
|
108
|
-
const { conn, sql } = stubbedConnection();
|
|
109
|
-
const cfg = {
|
|
110
|
-
name: "src_pg",
|
|
111
|
-
postgresConnection: {
|
|
112
|
-
host: "h",
|
|
113
|
-
port: 5432,
|
|
114
|
-
databaseName: "d",
|
|
115
|
-
userName: "u",
|
|
116
|
-
password: "pw",
|
|
117
|
-
} as components["schemas"]["PostgresConnection"],
|
|
118
|
-
};
|
|
119
|
-
await federateSourceForPassthrough(conn, "postgres", cfg);
|
|
120
|
-
await federateSourceForPassthrough(conn, "postgres", cfg);
|
|
121
|
-
const attaches = sql.filter((s) => s.startsWith("ATTACH"));
|
|
122
|
-
expect(attaches).toHaveLength(2);
|
|
123
|
-
for (const a of attaches) expect(a).toStartWith("ATTACH OR REPLACE ");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("postgres: dialect-quotes an alias that needs quoting (e.g. a hyphen)", async () => {
|
|
127
|
-
const { conn, sql } = stubbedConnection();
|
|
128
|
-
const result = await federateSourceForPassthrough(conn, "postgres", {
|
|
129
|
-
name: "my-pg",
|
|
130
|
-
postgresConnection: {
|
|
131
|
-
host: "h",
|
|
132
|
-
port: 5432,
|
|
133
|
-
databaseName: "d",
|
|
134
|
-
userName: "u",
|
|
135
|
-
password: "pw",
|
|
136
|
-
} as components["schemas"]["PostgresConnection"],
|
|
137
|
-
});
|
|
138
|
-
expect(result.handle).toBe("my-pg");
|
|
139
|
-
const attach = sql.find((s) => s.startsWith("ATTACH"));
|
|
140
|
-
expect(attach).toContain('AS "my-pg" (TYPE postgres, READ_ONLY)');
|
|
141
|
-
});
|
|
142
|
-
|
|
143
|
-
it("rejects a source type with no native passthrough", async () => {
|
|
144
|
-
const { conn } = stubbedConnection();
|
|
145
|
-
await expect(
|
|
146
|
-
federateSourceForPassthrough(conn, "mysql" as unknown as "postgres", {
|
|
147
|
-
name: "x",
|
|
148
|
-
}),
|
|
149
|
-
).rejects.toThrow(/no native query-passthrough/i);
|
|
150
|
-
});
|
|
151
|
-
|
|
152
|
-
it("fails loud when the configured credentials are missing", async () => {
|
|
153
|
-
const { conn } = stubbedConnection();
|
|
154
|
-
await expect(
|
|
155
|
-
federateSourceForPassthrough(conn, "bigquery", { name: "x" }),
|
|
156
|
-
).rejects.toThrow(/BigQuery connection configuration missing/i);
|
|
157
|
-
});
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
describe("attachDuckLakeReadWrite", () => {
|
|
161
|
-
const ducklakeConfig = {
|
|
162
|
-
catalog: {
|
|
163
|
-
postgresConnection: {
|
|
164
|
-
host: "cat-host",
|
|
165
|
-
port: 5432,
|
|
166
|
-
databaseName: "ducklake",
|
|
167
|
-
userName: "ducklake",
|
|
168
|
-
password: "secret",
|
|
169
|
-
},
|
|
170
|
-
},
|
|
171
|
-
storage: { bucketUrl: "gs://org-env-ducklake/prefix" },
|
|
172
|
-
} as unknown as components["schemas"]["DucklakeConnection"];
|
|
173
|
-
|
|
174
|
-
it("attaches read-write: no READ_ONLY, no AUTOMATIC_MIGRATION, keeps OVERRIDE_DATA_PATH", async () => {
|
|
175
|
-
const { conn, sql } = stubbedConnection();
|
|
176
|
-
await attachDuckLakeReadWrite(conn, "lake", ducklakeConfig);
|
|
177
|
-
const attach = sql.find((s) => s.includes("ATTACH OR REPLACE"));
|
|
178
|
-
expect(attach).toBeDefined();
|
|
179
|
-
expect(attach).toContain("OVERRIDE_DATA_PATH true");
|
|
180
|
-
expect(attach).not.toContain("READ_ONLY");
|
|
181
|
-
expect(attach).not.toContain("AUTOMATIC_MIGRATION");
|
|
182
|
-
expect(attach).toContain("AS lake");
|
|
183
|
-
});
|
|
184
|
-
});
|
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "bun:test";
|
|
2
|
-
import { components } from "../api";
|
|
3
|
-
import {
|
|
4
|
-
buildEnvironmentMalloyConfig,
|
|
5
|
-
EnvironmentMalloyConfig,
|
|
6
|
-
} from "./connection";
|
|
7
|
-
|
|
8
|
-
type ApiConnection = components["schemas"]["Connection"];
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* The connection `fingerprint` seam: when a connection carries an API
|
|
12
|
-
* fingerprint, the resolved Malloy connection's getDigest() must return it
|
|
13
|
-
* verbatim. Every consumer of a connection's identity — build planning, the
|
|
14
|
-
* package-load worker's digest RPC, and Malloy's serve-time manifest
|
|
15
|
-
* resolution — reads getDigest() off a connection resolved through the same
|
|
16
|
-
* environment lookup wrapper, so this one seam is what keeps build-time and
|
|
17
|
-
* serve-time source ids in agreement.
|
|
18
|
-
*
|
|
19
|
-
* Uses a postgres connection because it is constructed lazily (no network I/O
|
|
20
|
-
* until a query runs), so digests can be read offline.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
function pgConnection(overrides: Partial<ApiConnection> = {}): ApiConnection {
|
|
24
|
-
return {
|
|
25
|
-
name: "pg",
|
|
26
|
-
type: "postgres",
|
|
27
|
-
postgresConnection: {
|
|
28
|
-
host: "db.example.com",
|
|
29
|
-
port: 5432,
|
|
30
|
-
databaseName: "analytics",
|
|
31
|
-
userName: "svc_user",
|
|
32
|
-
password: "hunter2",
|
|
33
|
-
},
|
|
34
|
-
...overrides,
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
async function digestOf(connection: ApiConnection): Promise<string> {
|
|
39
|
-
let config: EnvironmentMalloyConfig | undefined;
|
|
40
|
-
try {
|
|
41
|
-
config = buildEnvironmentMalloyConfig([connection]);
|
|
42
|
-
const resolved = await config.malloyConfig.connections.lookupConnection(
|
|
43
|
-
connection.name,
|
|
44
|
-
);
|
|
45
|
-
return resolved.getDigest();
|
|
46
|
-
} finally {
|
|
47
|
-
await config?.releaseConnections();
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
describe("connection fingerprint", () => {
|
|
52
|
-
it("uses the fingerprint verbatim as the connection digest", async () => {
|
|
53
|
-
const digest = await digestOf(
|
|
54
|
-
pgConnection({ fingerprint: "fp-opaque-token-1" }),
|
|
55
|
-
);
|
|
56
|
-
expect(digest).toBe("fp-opaque-token-1");
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("keeps the digest stable across a credential rotation", async () => {
|
|
60
|
-
const before = await digestOf(pgConnection({ fingerprint: "fp-stable" }));
|
|
61
|
-
const after = await digestOf(
|
|
62
|
-
pgConnection({
|
|
63
|
-
fingerprint: "fp-stable",
|
|
64
|
-
postgresConnection: {
|
|
65
|
-
host: "db.example.com",
|
|
66
|
-
port: 5432,
|
|
67
|
-
databaseName: "analytics",
|
|
68
|
-
userName: "rotated_user",
|
|
69
|
-
password: "rotated-password",
|
|
70
|
-
},
|
|
71
|
-
}),
|
|
72
|
-
);
|
|
73
|
-
expect(after).toBe(before);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
it("changes the digest when the fingerprint changes", async () => {
|
|
77
|
-
const one = await digestOf(pgConnection({ fingerprint: "fp-1" }));
|
|
78
|
-
const two = await digestOf(pgConnection({ fingerprint: "fp-2" }));
|
|
79
|
-
expect(one).not.toBe(two);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
it("falls back to the locally derived digest when omitted", async () => {
|
|
83
|
-
const digest = await digestOf(pgConnection());
|
|
84
|
-
expect(typeof digest).toBe("string");
|
|
85
|
-
expect(digest.length).toBeGreaterThan(0);
|
|
86
|
-
// Behavior is unchanged from before the fingerprint existed: the digest
|
|
87
|
-
// is the connection's own derivation, deterministic for one config.
|
|
88
|
-
expect(await digestOf(pgConnection())).toBe(digest);
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("round-trips the fingerprint on the API connection", async () => {
|
|
92
|
-
const config = buildEnvironmentMalloyConfig([
|
|
93
|
-
pgConnection({ fingerprint: "fp-round-trip" }),
|
|
94
|
-
]);
|
|
95
|
-
try {
|
|
96
|
-
const api = config.apiConnections.find((c) => c.name === "pg");
|
|
97
|
-
expect(api?.fingerprint).toBe("fp-round-trip");
|
|
98
|
-
} finally {
|
|
99
|
-
await config.releaseConnections();
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
});
|