@malloy-publisher/server 0.9.11 → 0.9.13

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.
Files changed (27) hide show
  1. package/dist/app/api-doc.yaml +259 -4
  2. package/dist/app/assets/EnvironmentPage-BxJoHBPQ.js +1 -0
  3. package/dist/app/assets/HomePage-CtB5QVol.js +1 -0
  4. package/dist/app/assets/{MainPage-BpE_5WuW.js → MainPage-1nhjUUzl.js} +1 -1
  5. package/dist/app/assets/{ModelPage-ftyDI1tw.js → ModelPage-D8aucAvE.js} +2 -2
  6. package/dist/app/assets/{PackagePage-QGnFwlHu.js → PackagePage-DBSA4TbT.js} +1 -1
  7. package/dist/app/assets/{RenderedResult-Cmx8sX8d.es-du-Qe1x0.js → RenderedResult-DnBtf-cI.es-DalkcU9E.js} +2 -2
  8. package/dist/app/assets/{RouteError-zM4SSZaU.js → RouteError-BVLp9Ogi.js} +1 -1
  9. package/dist/app/assets/{ThemeEditorPage-DhZJXGJm.js → ThemeEditorPage-D6bvkrka.js} +1 -1
  10. package/dist/app/assets/{ToggleButtonGroup-TKxhg0Mg.js → ToggleButtonGroup-CWY9-__R.js} +1 -1
  11. package/dist/app/assets/{documentRoutes-D4TbSIi5.js → documentRoutes-QL_YE88h.js} +1 -1
  12. package/dist/app/assets/{editPageMounted-0kzl2sgg.js → editPageMounted-BT7ByBX-.js} +2 -2
  13. package/dist/app/assets/{index-Bzi4YH8Y.js → index-BRzP9bJe.js} +1 -1
  14. package/dist/app/assets/{index-CS4mmuDD.js → index-CHfG8VAW.js} +1 -1
  15. package/dist/app/assets/{index-B-qJVEXn.js → index-DM7_2PYo.js} +1 -1
  16. package/dist/app/assets/index-Dgqan3mQ.js +481 -0
  17. package/dist/app/assets/index.es-BBmXDZRJ.js +143 -0
  18. package/dist/app/index.html +1 -1
  19. package/dist/package_load_worker.mjs +112 -8
  20. package/dist/server.mjs +1498 -767
  21. package/dist/sshcrypto-cqb52edz.node +0 -0
  22. package/package.json +2 -1
  23. package/dist/app/assets/EnvironmentPage-tIGzymgb.js +0 -1
  24. package/dist/app/assets/HomePage-7QkNvQ_3.js +0 -1
  25. package/dist/app/assets/index-gQEuz0Cg.js +0 -480
  26. package/dist/app/assets/index.es-B3P9tIm3.js +0 -143
  27. package/dist/cpufeatures-1yrn0vtw.node +0 -0
@@ -16,7 +16,7 @@ SPDX-License-Identifier: MIT
16
16
  href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
17
17
  />
18
18
  <title>Malloy Publisher</title>
19
- <script type="module" crossorigin src="/assets/index-gQEuz0Cg.js"></script>
19
+ <script type="module" crossorigin src="/assets/index-Dgqan3mQ.js"></script>
20
20
  <link rel="stylesheet" crossorigin href="/assets/index-DUqldpo0.css">
21
21
  </head>
22
22
  <body>
@@ -13053,15 +13053,36 @@ function filesystemAccessFailure(error) {
13053
13053
  function isMysqlConfigFault(code) {
13054
13054
  return typeof code === "string" && (MYSQL_CONFIG_CODES.has(code) || code.startsWith("HANDSHAKE_"));
13055
13055
  }
13056
- function isConnectionFailure(error) {
13057
- let current = error;
13056
+ function isSqlserverConnectTimeout(error, code) {
13057
+ return code === "ETIMEOUT" && error.name === "ConnectionError";
13058
+ }
13059
+ function wrappedError(error) {
13060
+ if (error.cause instanceof Error)
13061
+ return error.cause;
13062
+ return error.originalError;
13063
+ }
13064
+ function causeChainHasTlsVerificationFailure(error) {
13065
+ let current = wrappedError(error);
13058
13066
  for (let depth = 0;depth < 8 && current instanceof Error; depth++) {
13067
+ const { code } = current;
13068
+ if (typeof code === "string" && TLS_VERIFICATION_CODES.has(code)) {
13069
+ return true;
13070
+ }
13071
+ current = wrappedError(current);
13072
+ }
13073
+ return false;
13074
+ }
13075
+ function isConnectionFailure(error) {
13076
+ for (const current of causeChain(error)) {
13059
13077
  const { code, fatal } = current;
13060
13078
  if (typeof code === "string") {
13061
13079
  if (NODE_CONNECTION_CODES.has(code))
13062
13080
  return true;
13063
13081
  if (POSTGRES_CONNECTION_SQLSTATE.test(code))
13064
13082
  return true;
13083
+ if (SQLSERVER_CONNECTION_CODES.has(code) || isSqlserverConnectTimeout(current, code)) {
13084
+ return !causeChainHasTlsVerificationFailure(current);
13085
+ }
13065
13086
  }
13066
13087
  if (fatal === true && !isMysqlConfigFault(code))
13067
13088
  return true;
@@ -13069,13 +13090,18 @@ function isConnectionFailure(error) {
13069
13090
  if (CODELESS_CONNECTION_MESSAGES.some((re) => re.test(message))) {
13070
13091
  return true;
13071
13092
  }
13072
- current = current.cause;
13073
13093
  }
13074
13094
  return false;
13075
13095
  }
13076
- function isCredentialRejection(error) {
13096
+ function* causeChain(error) {
13077
13097
  let current = error;
13078
13098
  for (let depth = 0;depth < 8 && current instanceof Error; depth++) {
13099
+ yield current;
13100
+ current = wrappedError(current);
13101
+ }
13102
+ }
13103
+ function isCredentialRejection(error) {
13104
+ for (const current of causeChain(error)) {
13079
13105
  const { code } = current;
13080
13106
  if (typeof code === "string" || typeof code === "number") {
13081
13107
  const value = String(code);
@@ -13083,12 +13109,13 @@ function isCredentialRejection(error) {
13083
13109
  return true;
13084
13110
  if (MYSQL_AUTH_CODES.has(value))
13085
13111
  return true;
13112
+ if (SQLSERVER_AUTH_CODES.has(value))
13113
+ return true;
13086
13114
  if (SNOWFLAKE_AUTH_CODES.has(value))
13087
13115
  return true;
13088
13116
  }
13089
13117
  if (current.name === "BigQueryAuthenticationError")
13090
13118
  return true;
13091
- current = current.cause;
13092
13119
  }
13093
13120
  return false;
13094
13121
  }
@@ -13103,6 +13130,19 @@ function databaseAccessFailure(error) {
13103
13130
  return new ConnectionFailedError(message);
13104
13131
  return;
13105
13132
  }
13133
+ function statementRejection(error) {
13134
+ for (const current of causeChain(error)) {
13135
+ const { code, severity } = current;
13136
+ if (severity === "FATAL" || severity === "PANIC")
13137
+ return;
13138
+ if (typeof code !== "string" || !POSTGRES_STATEMENT_SQLSTATES.has(code)) {
13139
+ continue;
13140
+ }
13141
+ const message = current.message;
13142
+ return code === POSTGRES_UNDEFINED_TABLE && POSTGRES_RELATION_MISSING.test(message) ? new TableNotFoundError(message) : new InvalidArgumentError(message);
13143
+ }
13144
+ return;
13145
+ }
13106
13146
  function describeFilesystemAccessFailure(errno) {
13107
13147
  const code = errno.code ?? "";
13108
13148
  const target = errno.path ? ` '${errno.path}'` : "";
@@ -13175,6 +13215,8 @@ function internalErrorToHttpError(error, { log = true, onLogged } = {}) {
13175
13215
  return httpError(404, error.message, "TABLE_NOT_FOUND");
13176
13216
  } else if (error instanceof ConnectionNotFoundError) {
13177
13217
  return httpError(404, error.message);
13218
+ } else if (error instanceof StorageDestinationNotFoundError) {
13219
+ return httpError(404, error.message);
13178
13220
  } else if (error instanceof DestinationNotFoundError) {
13179
13221
  return httpError(422, error.message);
13180
13222
  } else if (error instanceof ConnectionAuthError) {
@@ -13242,7 +13284,7 @@ function toQueryTextProblem(problem) {
13242
13284
  ...problem.at ? { at: { range: problem.at.range } } : {}
13243
13285
  };
13244
13286
  }
13245
- var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", GENERIC_UNREACHABLE_MESSAGE = "The database connection is down: the database could not be reached, so the query did not run.", GENERIC_AUTH_MESSAGE = "The database rejected the connection's credentials. Check the connection's user, password, key or token.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NODE_CONNECTION_CODES, POSTGRES_CONNECTION_SQLSTATE, CODELESS_CONNECTION_MESSAGES, MYSQL_CONFIG_CODES, POSTGRES_AUTH_SQLSTATE, MYSQL_AUTH_CODES, SNOWFLAKE_AUTH_CODES, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, InvalidModelPathError, RenderTagRefusedError, UnparseableTextError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, SkillNotFoundError, AgentNotFoundError, ConflictError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, ConnectionFailedError, UnconfiguredConnectionError, ConnectionPoolExhaustedError, DestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, ChainedUpstreamMissingError, ChainedShapeNotCarriedError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, WriteRollbackFailedError, WriteVerifyError, InvalidStateTransitionError, ServiceUnavailableError, PackageAdmissionRefusedError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
13287
+ var GENERIC_INTERNAL_MESSAGE = "Internal server error.", GENERIC_UPSTREAM_MESSAGE = "Upstream connection error.", GENERIC_UNREACHABLE_MESSAGE = "The database connection is down: the database could not be reached, so the query did not run.", GENERIC_AUTH_MESSAGE = "The database rejected the connection's credentials. Check the connection's user, password, key or token.", MAX_LOGGED_DETAIL_CHARS = 2000, FILESYSTEM_ACCESS_DESCRIPTIONS, NODE_CONNECTION_CODES, POSTGRES_CONNECTION_SQLSTATE, CODELESS_CONNECTION_MESSAGES, MYSQL_CONFIG_CODES, SQLSERVER_CONNECTION_CODES, TLS_VERIFICATION_CODES, POSTGRES_AUTH_SQLSTATE, MYSQL_AUTH_CODES, SQLSERVER_AUTH_CODES, SNOWFLAKE_AUTH_CODES, POSTGRES_STATEMENT_SQLSTATES, POSTGRES_UNDEFINED_TABLE = "42P01", POSTGRES_RELATION_MISSING, NotImplementedError, BadRequestError, InvalidArgumentError, CompileRefusedError, InvalidModelPathError, RenderTagRefusedError, UnparseableTextError, EnvironmentNotFoundError, PackageNotFoundError, ModelNotFoundError, DashboardNotFoundError, SkillNotFoundError, AgentNotFoundError, ConflictError, ConnectionNotFoundError, TableNotFoundError, ConnectionError, ConnectionFailedError, UnconfiguredConnectionError, ConnectionPoolExhaustedError, DestinationNotFoundError, StorageDestinationNotFoundError, ConnectionAuthError, UnsupportedCatalogFormatError, ModelCompilationError, PackageManifestError, MaterializationEligibilityError, ChainedUpstreamMissingError, ChainedShapeNotCarriedError, PublisherConfigError, ServerConfigurationError, FrozenConfigError, AccessDeniedError, QueryCompileError, NotQueryableError, OffSurfaceError, MaterializationNotFoundError, MaterializationConflictError, WriteConflictError, WriteRolledBackError, WriteRollbackFailedError, WriteVerifyError, InvalidStateTransitionError, ServiceUnavailableError, PackageAdmissionRefusedError, PayloadTooLargeError, ResponseUnserializableError, QueryTimeoutError;
13246
13288
  var init_errors = __esm(() => {
13247
13289
  init_constants();
13248
13290
  init_logger();
@@ -13268,7 +13310,8 @@ var init_errors = __esm(() => {
13268
13310
  /^(Error: )?Connection lost: The server closed the connection\.$/,
13269
13311
  new RegExp(`^(Error: )?(connect|read|write|getaddrinfo) (${[
13270
13312
  ...NODE_CONNECTION_CODES
13271
- ].join("|")})\\b`)
13313
+ ].join("|")})\\b`),
13314
+ /^Failed to connect to \S+( \(redirected from \S+\))?( in \d+ms| - (?!.*certificate).+)$/i
13272
13315
  ];
13273
13316
  MYSQL_CONFIG_CODES = new Set([
13274
13317
  "ER_ACCESS_DENIED_ERROR",
@@ -13277,9 +13320,46 @@ var init_errors = __esm(() => {
13277
13320
  "AUTH_SWITCH_PLUGIN_ERROR",
13278
13321
  "MYSQL_CLEAR_PASSWORD_NOT_ENABLED"
13279
13322
  ]);
13323
+ SQLSERVER_CONNECTION_CODES = new Set(["ESOCKET", "EINSTLOOKUP"]);
13324
+ TLS_VERIFICATION_CODES = new Set([
13325
+ "CERT_HAS_EXPIRED",
13326
+ "DEPTH_ZERO_SELF_SIGNED_CERT",
13327
+ "ERR_TLS_CERT_ALTNAME_INVALID",
13328
+ "SELF_SIGNED_CERT_IN_CHAIN",
13329
+ "UNABLE_TO_GET_ISSUER_CERT",
13330
+ "UNABLE_TO_GET_ISSUER_CERT_LOCALLY",
13331
+ "UNABLE_TO_VERIFY_LEAF_SIGNATURE"
13332
+ ]);
13280
13333
  POSTGRES_AUTH_SQLSTATE = /^28[0-9A-Z]{3}$/;
13281
13334
  MYSQL_AUTH_CODES = new Set(["ER_ACCESS_DENIED_ERROR"]);
13335
+ SQLSERVER_AUTH_CODES = new Set(["ELOGIN"]);
13282
13336
  SNOWFLAKE_AUTH_CODES = new Set(["390100", "390144", "390195", "390318"]);
13337
+ POSTGRES_STATEMENT_SQLSTATES = new Set([
13338
+ "42601",
13339
+ "42703",
13340
+ "42P01",
13341
+ "42883",
13342
+ "42704",
13343
+ "42P02",
13344
+ "42702",
13345
+ "42725",
13346
+ "42P09",
13347
+ "42P10",
13348
+ "42804",
13349
+ "42846",
13350
+ "42803",
13351
+ "42P20",
13352
+ "42P18",
13353
+ "42P19",
13354
+ "42712",
13355
+ "42701",
13356
+ "42602",
13357
+ "42622",
13358
+ "42809",
13359
+ "42P21",
13360
+ "42P22"
13361
+ ]);
13362
+ POSTGRES_RELATION_MISSING = /^relation ".*" does not exist$/;
13283
13363
  NotImplementedError = class NotImplementedError extends Error {
13284
13364
  constructor(message) {
13285
13365
  super(message);
@@ -13378,6 +13458,11 @@ var init_errors = __esm(() => {
13378
13458
  super(message);
13379
13459
  }
13380
13460
  };
13461
+ StorageDestinationNotFoundError = class StorageDestinationNotFoundError extends Error {
13462
+ constructor(message) {
13463
+ super(message);
13464
+ }
13465
+ };
13381
13466
  ConnectionAuthError = class ConnectionAuthError extends Error {
13382
13467
  constructor(message) {
13383
13468
  super(message);
@@ -23908,6 +23993,15 @@ class RpcWaitAccountant {
23908
23993
  }
23909
23994
  }
23910
23995
 
23996
+ // src/service/experimental_dialects.ts
23997
+ import { getDialect } from "@malloydata/malloy";
23998
+ var BUNDLED_EXPERIMENTAL_DIALECTS = ["sqlserver"];
23999
+ function acceptBundledExperimentalDialects() {
24000
+ for (const name of BUNDLED_EXPERIMENTAL_DIALECTS) {
24001
+ getDialect(name).acceptExperimental();
24002
+ }
24003
+ }
24004
+
23911
24005
  // src/materialization_metrics.ts
23912
24006
  var resetHooks = [];
23913
24007
  function lazyCounter(name, description) {
@@ -23943,7 +24037,7 @@ var storageServeRoutingCounter = lazyCounter("publisher_storage_serve_routing_to
23943
24037
  var storageTableRetainedCounter = lazyCounter("publisher_storage_tables_retained_total", "Tables a FAILED run left in a storage= destination and deliberately did not " + "reclaim, because the source is refreshed incrementally and the name may be " + "the one it serves from. Label: destination. Not all of these are orphans — " + "a rebuild at a fresh generational name is, a seed on the live serving name " + "is not, and the manifest entry cannot separate them — so read this as an " + "upper bound on what is accumulating rather than a leak count. It is the " + "only accounting there is until reclaiming a destination exists, which is " + "why it is a counter and not just a log line: the question is a rate, not " + "whether it ever happened.");
23944
24038
  var storageBuildFailureCounter = lazyCounter("publisher_storage_build_failures_total", "storage= build failures (federation/passthrough/attach/CTAS), distinct from " + "in-warehouse build failures. Labels: destination (connection name), " + "reason ('build_failed'|'billed_read_not_captured'). The second is the " + "expensive one: the warehouse read ran and was charged, and the rows could " + "not be captured — so a re-drive pays for it again. Worth alerting on " + "separately from a failure that costs only a retry.");
23945
24039
  var attributionSkippedCounter = lazyCounter("publisher_storage_build_attribution_skipped_total", "storage= builds whose warehouse read went out UNATTRIBUTED while tagging was " + "on. Label: reason ('job_listing_unavailable'|'tag_failed'|" + "'read_row_not_found'|'read_row_ambiguous'|'cost_query_failed'). " + "The read still ran and the " + "build still succeeded — what was lost is the label in the customer's own " + "query history, and the cost on this side. Without this an operator who " + "turns tagging on and sees nothing has a single log line to go on.");
23946
- var eligibilityRefusedCounter = lazyCounter("publisher_materialization_eligibility_refused_total", "materialization-eligibility refusals, both tiers. Label: reason " + "('free_parameter'|'given_in_persisted_query'|'dynamic_projection'|" + "'dynamic_join'|'dynamic_joined_where'|'partition_without_storage'|" + "'partition_column_unknown'|'partition_column_not_public'|" + "'merge_key_scope_unresolved'|'preaggregate_over_dynamic_source'|" + "'authorize'|'partition'|'not_duckdb_portable'|" + "'public_surface_unknown'). 'given' is retained on the enum for records " + "that carry it and is no longer produced: where a given sits decides the " + "outcome, so one reason covering every placement cannot be raised.");
24040
+ var eligibilityRefusedCounter = lazyCounter("publisher_materialization_eligibility_refused_total", "materialization-eligibility refusals, both tiers. Label: reason " + "('free_parameter'|'given_in_persisted_query'|'dynamic_projection'|" + "'dynamic_join'|'dynamic_joined_where'|'partition_without_storage'|" + "'partition_column_unknown'|'partition_column_not_public'|" + "'merge_key_scope_unresolved'|'preaggregate_over_dynamic_source'|" + "'authorize'|'partition'|'not_duckdb_portable'|" + "'public_surface_unknown'|'read_only_dialect'). 'given' is retained on the enum for records " + "that carry it and is no longer produced: where a given sits decides the " + "outcome, so one reason covering every placement cannot be raised.");
23947
24041
  var serveShapeTierDropCounter = lazyCounter("publisher_storage_serve_shape_tier_drop_total", "storage serve-shape compile escalations: a refinement tier failed to " + "compile and the riskiest category was dropped, or one or more lifted " + "entry points failed to compile and were dropped alone. Label: tier (the " + "failed tier index, 0=full; 'lifts' for dropped lifts).");
23948
24042
  var serveShapeTypeFallbackCounter = lazyCounter("publisher_storage_serve_shape_type_fallback_total", "Captured DuckDB column types mapped to json in the serve shape (type " + "fidelity loss). Label: kind ('array'|'unrecognized').");
23949
24043
  var chainedStorageBuildCounter = lazyCounter("publisher_storage_chained_build_total", "Chained storage= source builds (a source reading a storage-materialized " + "upstream). Label: outcome ('parent_reuse'|'inline_fallback'|" + "'strict_shape_fallback'|'strict_refused'|'infra_failure'). The " + "parent_reuse share is the headline signal for how far the " + "stack-on-the-parent path gets us vs recompute-from-raw.");
@@ -25132,7 +25226,16 @@ function assertMergeKeyScopeResolvable(persistSource, terms, annotationFields, w
25132
25226
  message: `${what} cannot be materialized: it declares 'merge_key=' and is ` + `scoped by a term this pass cannot express as a predicate over the ` + `stored table's own columns (${unscopable.map((term) => `'${term.code}'`).join(", ")}). An incremental refresh matches rows by the merge ` + `key, and the stored table holds every caller's rows, so the match ` + `must also carry the scoping columns or it would update rows ` + `belonging to other callers. Scope this source with a term over its ` + `own columns, or drop 'merge_key=' to refresh by watermark range.`
25133
25227
  });
25134
25228
  }
25229
+ var READ_ONLY_DIALECTS = new Set(["sqlserver"]);
25135
25230
  function assertColocatedPersistNotAuthorizeGated(persistSource, sourceName = persistSource.name, origin = "persist", gateOutcome, annotationFields = {}) {
25231
+ if (!annotationFields.storage && READ_ONLY_DIALECTS.has(persistSource.dialectName)) {
25232
+ recordEligibilityRefused("read_only_dialect");
25233
+ const what2 = origin === "preaggregate" ? `Pre-aggregation rollup '${sourceName}'` : `Source '${sourceName}'`;
25234
+ throw new MaterializationEligibilityError({
25235
+ reason: "read_only_dialect",
25236
+ message: `${what2} cannot be materialized (colocated '#@ persist'): its ` + `connection '${persistSource.connectionName}' is on the ` + `'${persistSource.dialectName}' dialect, whose connection is ` + `read-only and creates no tables, so there is nowhere in the ` + `source warehouse to write the result. The source serves live. ` + `Remove the annotation, or persist a source on a connection that ` + `can write.`
25237
+ });
25238
+ }
25136
25239
  const partition = resolvePartitionColumns(persistSource, annotationFields);
25137
25240
  if (!partition.ok) {
25138
25241
  recordEligibilityRefused(partition.reason);
@@ -25867,6 +25970,7 @@ function collectColocatedSourceEligibility(compiled) {
25867
25970
  if (!parentPort) {
25868
25971
  throw new Error("package_load_worker.ts must be loaded inside a worker_threads Worker");
25869
25972
  }
25973
+ acceptBundledExperimentalDialects();
25870
25974
  var port = parentPort;
25871
25975
  var nextRpcId = 0;
25872
25976
  var pendingRpc = new Map;