@malloy-publisher/server 0.0.240 → 0.0.242

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 (23) hide show
  1. package/dist/app/api-doc.yaml +153 -46
  2. package/dist/app/assets/{EnvironmentPage-2oMC3DUO.js → EnvironmentPage-zu0NeDu-.js} +1 -1
  3. package/dist/app/assets/HomePage-kuBM3jiQ.js +1 -0
  4. package/dist/app/assets/{LightMode-BNaG4oAx.js → LightMode-DGBAdVPb.js} +1 -1
  5. package/dist/app/assets/{MainPage-Dje9yqIp.js → MainPage-CCVx9yPs.js} +2 -2
  6. package/dist/app/assets/{MaterializationsPage-D4jCpScu.js → MaterializationsPage-M-bWIx8L.js} +1 -1
  7. package/dist/app/assets/ModelPage-D-L2pqIy.js +1 -0
  8. package/dist/app/assets/{PackagePage-DlO2UBEI.js → PackagePage-BZglxDlj.js} +1 -1
  9. package/dist/app/assets/RouteError-DGoCQGam.js +1 -0
  10. package/dist/app/assets/{ThemeEditorPage-DZzT5zt4.js → ThemeEditorPage-e8MLf7SV.js} +1 -1
  11. package/dist/app/assets/{WorkbookPage-CfDz8XAp.js → WorkbookPage-C8ufpN5i.js} +1 -1
  12. package/dist/app/assets/{core-BGHaIj_q.es-BeNX3GvK.js → core-KFsKleo0.es-D6cYhbct.js} +1 -1
  13. package/dist/app/assets/{index-ByceOJbS.js → index-B-jw9EkA.js} +52 -52
  14. package/dist/app/assets/{index-BfV8vaZu.js → index-CDNkCta4.js} +1 -1
  15. package/dist/app/assets/{index-BeZphO3v.js → index-CLwzlAx6.js} +1 -1
  16. package/dist/app/assets/{index-DXjc2oZx.js → index-Dnef41hg.js} +1 -1
  17. package/dist/app/index.html +1 -1
  18. package/dist/runtime/publisher.js +1 -1
  19. package/dist/server.mjs +206 -37
  20. package/package.json +1 -1
  21. package/dist/app/assets/HomePage-DmgHdpH6.js +0 -1
  22. package/dist/app/assets/ModelPage-oI3O6TwY.js +0 -1
  23. package/dist/app/assets/RouteError-B5MgkwXx.js +0 -1
package/dist/server.mjs CHANGED
@@ -269317,7 +269317,7 @@ class QueryController {
269317
269317
  constructor(environmentStore) {
269318
269318
  this.environmentStore = environmentStore;
269319
269319
  }
269320
- async getQuery(environmentName, packageName, modelPath, sourceName, queryName, query, compactJson = false, filterParams, bypassFilters, givens, metadata) {
269320
+ async getQuery(environmentName, packageName, modelPath, sourceName, queryName, query, compactJson = false, filterParams, bypassFilters, givens, metadata, bypassAuthorize) {
269321
269321
  let requestMetadata;
269322
269322
  let queryClass;
269323
269323
  try {
@@ -269357,7 +269357,7 @@ class QueryController {
269357
269357
  return null;
269358
269358
  }
269359
269359
  }
269360
- }, compactJson ? "compact" : "full"), getQueryTimeoutMs());
269360
+ }, compactJson ? "compact" : "full", bypassAuthorize), getQueryTimeoutMs());
269361
269361
  const renderLogs = import_render_validator.validateRenderTags(result);
269362
269362
  return {
269363
269363
  result: serializedResult,
@@ -277169,12 +277169,19 @@ function unwrapQuotedExpression(body) {
277169
277169
 
277170
277170
  // src/authorize_metrics.ts
277171
277171
  var guardRejectionCounter = null;
277172
+ var bypassCounter = null;
277172
277173
  function recordAuthorizeGuardRejection(field) {
277173
277174
  guardRejectionCounter ??= publisherMeter().createCounter("publisher_authorize_guard_rejected_total", {
277174
277175
  description: "Requests rejected with 400 for declaring an `#(authorize)` annotation in caller-submitted Malloy text. Label: field ('query'|'source_name'|'query_name'|'compile_source')."
277175
277176
  });
277176
277177
  guardRejectionCounter.add(1, { field });
277177
277178
  }
277179
+ function recordAuthorizeBypass(entryPoint) {
277180
+ bypassCounter ??= publisherMeter().createCounter("publisher_authorize_bypass_total", {
277181
+ description: "Gate evaluations skipped because the request carried an authorize bypass (private data-management path). Label: entry_point ('source'|'runnable'). Any nonzero value on a path that should not use the bypass is a finding — see the paired `authorize bypass` audit log line for org/package/model/source."
277182
+ });
277183
+ bypassCounter.add(1, { entry_point: entryPoint });
277184
+ }
277178
277185
 
277179
277186
  // src/service/environment.ts
277180
277187
  init_logger();
@@ -278733,7 +278740,11 @@ class Model {
278733
278740
  }
278734
278741
  return this.fileLevelAuthorize;
278735
278742
  }
278736
- async assertAuthorized(sourceName, givens) {
278743
+ async assertAuthorized(sourceName, givens, bypassAuthorize = false) {
278744
+ if (bypassAuthorize) {
278745
+ this.noteAuthorizeBypass("source", sourceName);
278746
+ return;
278747
+ }
278737
278748
  const gates = sourceName ? this.entryPointGatesBySource.get(sourceName) : undefined;
278738
278749
  if (gates) {
278739
278750
  for (const { label, exprs, selfContained, ambientPrefix } of gates) {
@@ -278743,6 +278754,15 @@ class Model {
278743
278754
  }
278744
278755
  await this.assertAuthorizedExprs(sourceName ?? "(query)", this.effectiveAuthorizeFor(sourceName), givens);
278745
278756
  }
278757
+ noteAuthorizeBypass(entryPoint, sourceName) {
278758
+ recordAuthorizeBypass(entryPoint);
278759
+ logger.info("authorize bypass", {
278760
+ entryPoint,
278761
+ sourceName: sourceName ?? "(query)",
278762
+ modelPath: this.modelPath,
278763
+ packageName: this.packageName
278764
+ });
278765
+ }
278746
278766
  async assertAuthorizedExprs(label, exprs, givens, selfContainedFirst = false, ambientPrefix = 0) {
278747
278767
  if (exprs.length === 0)
278748
278768
  return;
@@ -278765,7 +278785,11 @@ class Model {
278765
278785
  if (!passed)
278766
278786
  deny();
278767
278787
  }
278768
- async assertAuthorizedForAllSources(runnable, givens) {
278788
+ async assertAuthorizedForAllSources(runnable, givens, bypassAuthorize = false) {
278789
+ if (bypassAuthorize) {
278790
+ this.noteAuthorizeBypass("runnable", await this.resolveAuthorizeSourceFromRunnable(runnable));
278791
+ return;
278792
+ }
278769
278793
  const ownSourceName = await this.resolveAuthorizeSourceFromRunnable(runnable);
278770
278794
  await this.assertAuthorized(ownSourceName, givens);
278771
278795
  const { struct, modelDef, compositeResolvedSourceDef } = await this.resolveRunTargetStruct(runnable);
@@ -279342,7 +279366,7 @@ class Model {
279342
279366
  return { ...b, schema, refinements };
279343
279367
  }).filter((b) => b.schema.length > 0);
279344
279368
  }
279345
- async getQueryResults(sourceName, queryName, query, filterParams, bypassFilters, givens, abortSignal, queryMetadataInput, responseShape = "full") {
279369
+ async getQueryResults(sourceName, queryName, query, filterParams, bypassFilters, givens, abortSignal, queryMetadataInput, responseShape = "full", bypassAuthorize = false) {
279346
279370
  const startTime = performance.now();
279347
279371
  if (this.compilationError) {
279348
279372
  if (this.compilationError instanceof MalloyError2 || this.compilationError instanceof ModelCompilationError) {
@@ -279361,7 +279385,7 @@ class Model {
279361
279385
  const surfaceName = extractRunTargetSourceName(query);
279362
279386
  const earlySource = sourceName || (queryName ? this.queries?.find((q) => q.name === queryName)?.sourceName : undefined) || (surfaceName && !this.sources?.some((s) => s.name === surfaceName) ? this.queries?.find((q) => q.name === surfaceName)?.sourceName : undefined) || surfaceName;
279363
279387
  if (earlySource) {
279364
- await this.assertAuthorized(earlySource, givens ?? {});
279388
+ await this.assertAuthorized(earlySource, givens ?? {}, bypassAuthorize);
279365
279389
  }
279366
279390
  try {
279367
279391
  for (const [field, callerText] of [
@@ -279456,7 +279480,7 @@ run: ${sourceName ? `${quoteMalloyIdentifier(sourceName)} -> ` : ""}${quoteMallo
279456
279480
  if (boundary === "deferred") {
279457
279481
  this.assertQueryBoundaryCompiled(compiledSource, query);
279458
279482
  }
279459
- await this.assertAuthorizedForAllSources(runnable, givens ?? {});
279483
+ await this.assertAuthorizedForAllSources(runnable, givens ?? {}, bypassAuthorize);
279460
279484
  const maxRows = getMaxQueryRows();
279461
279485
  const maxBytes = getMaxResponseBytes();
279462
279486
  const buildManifest = this.resolveFreshBuildManifest();
@@ -280652,7 +280676,7 @@ function ledgerLineageMismatch(entry, lineage) {
280652
280676
  }
280653
280677
  const changed = (reason) => ({ reasonCode: "lineage_changed", reason });
280654
280678
  if (entry.sourceEntityId !== lineage.sourceEntityId) {
280655
- return changed(`the source's content address changed, so the recorded boundary was ` + `measured over different SQL than this refresh would apply a delta to`);
280679
+ return changed(`the source's content address is not the one the recorded boundary was ` + `measured under, so that boundary describes different SQL than this ` + `refresh would apply a delta to — either the model was edited, or ` + `this refresh is instructed through a different version of the ` + `package than the one that advanced the boundary`);
280656
280680
  }
280657
280681
  if (entry.connectionName !== lineage.connectionName) {
280658
280682
  return changed(`the recorded boundary was advanced on connection ` + `"${entry.connectionName}", not "${lineage.connectionName}"`);
@@ -284408,6 +284432,13 @@ class WatchModeController {
284408
284432
  init_errors();
284409
284433
  init_logger();
284410
284434
 
284435
+ // src/authorize_bypass_header.ts
284436
+ var BYPASS_AUTHORIZE_HEADER = "x-publisher-bypass-authorize";
284437
+ var readBypassAuthorize = (req) => {
284438
+ const raw = req.headers[BYPASS_AUTHORIZE_HEADER];
284439
+ return typeof raw === "string" && raw.trim().toLowerCase() === "true" ? true : undefined;
284440
+ };
284441
+
284411
284442
  // src/filter_deprecation.ts
284412
284443
  var setFilterDeprecationHeaders = (res, options) => {
284413
284444
  const hasFilterParams = options.filterParams !== undefined && options.filterParams !== null && !(typeof options.filterParams === "object" && !Array.isArray(options.filterParams) && Object.keys(options.filterParams).length === 0);
@@ -284559,6 +284590,9 @@ class MaterializationController {
284559
284590
  if (parsed.strictUpstreams !== undefined) {
284560
284591
  result.strictUpstreams = parsed.strictUpstreams;
284561
284592
  }
284593
+ if (parsed.ledger !== undefined) {
284594
+ result.ledger = parsed.ledger;
284595
+ }
284562
284596
  }
284563
284597
  if (body.forceRefresh !== undefined) {
284564
284598
  if (typeof body.forceRefresh !== "boolean") {
@@ -284628,6 +284662,12 @@ class MaterializationController {
284628
284662
  }
284629
284663
  result.strictUpstreams = obj.strictUpstreams;
284630
284664
  }
284665
+ if (obj.ledger !== undefined && obj.ledger !== null) {
284666
+ if (!Array.isArray(obj.ledger)) {
284667
+ throw new BadRequestError("buildInstructions.ledger must be an array");
284668
+ }
284669
+ result.ledger = obj.ledger.map((entry) => this.validateLedgerEntry(entry));
284670
+ }
284631
284671
  return result;
284632
284672
  }
284633
284673
  validateManifestReference(raw) {
@@ -284678,6 +284718,40 @@ class MaterializationController {
284678
284718
  ...typeof instruction.reseed === "boolean" ? { reseed: instruction.reseed } : {}
284679
284719
  };
284680
284720
  }
284721
+ validateLedgerEntry(raw) {
284722
+ if (typeof raw !== "object" || raw === null) {
284723
+ throw new BadRequestError("Each buildInstructions.ledger entry must be an object");
284724
+ }
284725
+ const entry = raw;
284726
+ for (const field of [
284727
+ "connectionName",
284728
+ "physicalTableName",
284729
+ "coveredThrough",
284730
+ "coveredThroughType",
284731
+ "watermark",
284732
+ "sourceEntityId"
284733
+ ]) {
284734
+ if (typeof entry[field] !== "string" || entry[field] === "") {
284735
+ throw new BadRequestError(`Ledger entry '${field}' must be a non-empty string`);
284736
+ }
284737
+ }
284738
+ if (entry.strategy !== "merge" && entry.strategy !== "range_replace") {
284739
+ throw new BadRequestError("Ledger entry 'strategy' must be 'merge' or 'range_replace'");
284740
+ }
284741
+ if (entry.mergeKeys !== undefined && (!Array.isArray(entry.mergeKeys) || entry.mergeKeys.some((k) => typeof k !== "string"))) {
284742
+ throw new BadRequestError("Ledger entry 'mergeKeys' must be an array of strings");
284743
+ }
284744
+ return {
284745
+ connectionName: entry.connectionName,
284746
+ physicalTableName: entry.physicalTableName,
284747
+ coveredThrough: entry.coveredThrough,
284748
+ coveredThroughType: entry.coveredThroughType,
284749
+ watermark: entry.watermark,
284750
+ strategy: entry.strategy,
284751
+ sourceEntityId: entry.sourceEntityId,
284752
+ ...Array.isArray(entry.mergeKeys) ? { mergeKeys: entry.mergeKeys } : {}
284753
+ };
284754
+ }
284681
284755
  async stopMaterialization(environmentName, packageName, materializationId) {
284682
284756
  return this.materializationService.stopMaterialization(environmentName, packageName, materializationId);
284683
284757
  }
@@ -292742,6 +292816,25 @@ import { Manifest } from "@malloydata/malloy";
292742
292816
 
292743
292817
  // src/service/incremental_build.ts
292744
292818
  init_logger();
292819
+ function ledgerTableKey(connectionName, physicalTableName) {
292820
+ return `${connectionName}\x00${physicalTableName}`;
292821
+ }
292822
+ function indexCallerLedger(entries) {
292823
+ const index = new Map;
292824
+ for (const entry of entries) {
292825
+ index.set(ledgerTableKey(entry.connectionName, entry.physicalTableName), {
292826
+ sourceEntityId: entry.sourceEntityId,
292827
+ coveredThroughValue: entry.coveredThrough,
292828
+ coveredThroughType: entry.coveredThroughType,
292829
+ watermarkDimension: entry.watermark,
292830
+ mergeKeyDimensions: entry.mergeKeys ?? [],
292831
+ derivedStrategy: entry.strategy,
292832
+ physicalTableName: entry.physicalTableName,
292833
+ connectionName: entry.connectionName
292834
+ });
292835
+ }
292836
+ return index;
292837
+ }
292745
292838
  function incrementalLineage(params) {
292746
292839
  const d = params.declaration;
292747
292840
  if (!d?.incremental)
@@ -292769,25 +292862,32 @@ function incrementalLineage(params) {
292769
292862
  }
292770
292863
  async function planSourceRefresh(params) {
292771
292864
  const { context, lineage } = params;
292865
+ const forceRefresh = context.forceRefresh || params.reseed === true;
292866
+ const dialect = params.persistSource.dialectName;
292772
292867
  let ledgerEntry = null;
292773
- try {
292774
- ledgerEntry = await context.ledger.getIncrementalLedgerEntry(context.environmentId, lineage.connectionName, lineage.physicalTableName);
292775
- } catch (err) {
292776
- return {
292777
- mode: "seed",
292778
- reasonCode: "ledger_unreadable",
292779
- reason: `the covered_through ledger could not be read (${errMessage(err)})`
292780
- };
292868
+ if (context.callerLedger) {
292869
+ ledgerEntry = context.callerLedger.get(ledgerTableKey(lineage.connectionName, lineage.physicalTableName)) ?? null;
292870
+ } else {
292871
+ try {
292872
+ ledgerEntry = await context.ledger.getIncrementalLedgerEntry(context.environmentId, lineage.connectionName, lineage.physicalTableName);
292873
+ } catch (err) {
292874
+ return {
292875
+ mode: "seed",
292876
+ reasonCode: "ledger_unreadable",
292877
+ reason: `the covered_through ledger could not be read (${errMessage(err)})`
292878
+ };
292879
+ }
292781
292880
  }
292782
- const postgresVersionNum = lineage.strategy === "merge" && params.persistSource.dialectName === "postgres" && ledgerEntry !== null ? await probePostgresVersion(params.runner) : undefined;
292881
+ const postgresVersionNum = lineage.strategy === "merge" && dialect === "postgres" && ledgerEntry !== null ? await probePostgresVersion(params.runner) : undefined;
292882
+ let step;
292783
292883
  try {
292784
- return await planIncrementalStep({
292884
+ step = await planIncrementalStep({
292785
292885
  runner: params.runner,
292786
- dialect: params.persistSource.dialectName,
292886
+ dialect,
292787
292887
  quotedTablePath: params.quotedTablePath,
292788
292888
  lineage,
292789
292889
  ledgerEntry,
292790
- forceRefresh: context.forceRefresh || params.reseed === true,
292890
+ forceRefresh,
292791
292891
  now: context.now,
292792
292892
  sourceSQL: params.sourceSQL,
292793
292893
  columns: params.columns,
@@ -292800,9 +292900,15 @@ async function planSourceRefresh(params) {
292800
292900
  reason: `the delta could not be planned (${errMessage(err)})`
292801
292901
  };
292802
292902
  }
292903
+ if (context.callerLedger && step.mode === "seed" && (step.reasonCode === "lineage_changed" || step.reasonCode === "table_renamed")) {
292904
+ throw new Error(`The supplied ledger entry for table "${lineage.physicalTableName}" ` + `was measured under a different definition of this source: ` + `${step.reason}. Delete the entry to rebuild the source, or set ` + `reseed.`);
292905
+ }
292906
+ return step;
292803
292907
  }
292804
292908
  async function advanceLedger(params) {
292805
292909
  const { context, lineage } = params;
292910
+ if (context.callerLedger)
292911
+ return;
292806
292912
  try {
292807
292913
  await context.ledger.upsertIncrementalLedgerEntry({
292808
292914
  environmentId: context.environmentId,
@@ -292827,6 +292933,8 @@ async function advanceLedger(params) {
292827
292933
  }
292828
292934
  }
292829
292935
  async function resetLedger(context, lineage) {
292936
+ if (context.callerLedger)
292937
+ return;
292830
292938
  try {
292831
292939
  await context.ledger.deleteIncrementalLedgerEntry(context.environmentId, lineage.connectionName, lineage.physicalTableName);
292832
292940
  } catch (err) {
@@ -293135,8 +293243,24 @@ async function resolveEnvironmentId(repository, environmentName) {
293135
293243
  }
293136
293244
 
293137
293245
  // src/service/materialization_service.ts
293138
- function boundaryFields(bound) {
293139
- return bound ? { coveredThrough: bound.value, coveredThroughType: bound.malloyType } : {};
293246
+ function refreshFields(did) {
293247
+ return did ? { refresh: did } : {};
293248
+ }
293249
+ function ledgerFields(lineage, bound) {
293250
+ if (!lineage || !bound)
293251
+ return {};
293252
+ return {
293253
+ ledger: {
293254
+ connectionName: lineage.connectionName,
293255
+ physicalTableName: lineage.physicalTableName,
293256
+ coveredThrough: bound.value,
293257
+ coveredThroughType: bound.malloyType,
293258
+ watermark: lineage.watermarkName,
293259
+ ...lineage.mergeKeys.length > 0 ? { mergeKeys: lineage.mergeKeys } : {},
293260
+ strategy: lineage.strategy,
293261
+ sourceEntityId: lineage.sourceEntityId
293262
+ }
293263
+ };
293140
293264
  }
293141
293265
  function connectionMetadataLayers(environment, connectionName) {
293142
293266
  try {
@@ -293279,7 +293403,7 @@ class MaterializationService {
293279
293403
  const buildInstructions = options.buildInstructions;
293280
293404
  const orchestrated = buildInstructions !== undefined;
293281
293405
  if (orchestrated) {
293282
- this.validateInstructions(pkg.getBuildPlan(), buildInstructions);
293406
+ this.validateInstructions(pkg.getBuildPlan(), buildInstructions, options.ledger, options.reseed ?? false);
293283
293407
  }
293284
293408
  const active2 = await this.repository.getActiveMaterialization(environmentId, packageName);
293285
293409
  if (active2) {
@@ -293310,6 +293434,7 @@ class MaterializationService {
293310
293434
  forceRefresh,
293311
293435
  reseed,
293312
293436
  buildInstructions,
293437
+ ledger: orchestrated ? options.ledger : undefined,
293313
293438
  referenceManifest: options.referenceManifest,
293314
293439
  strictUpstreams: options.strictUpstreams,
293315
293440
  trigger,
@@ -293346,7 +293471,8 @@ class MaterializationService {
293346
293471
  packageName,
293347
293472
  materializationId: id,
293348
293473
  forceRefresh: opts.reseed ?? false,
293349
- now: new Date(startedAt)
293474
+ now: new Date(startedAt),
293475
+ ledger: opts.ledger
293350
293476
  });
293351
293477
  let instructions;
293352
293478
  let carried;
@@ -293563,7 +293689,7 @@ class MaterializationService {
293563
293689
  });
293564
293690
  }
293565
293691
  }
293566
- validateInstructions(plan, instructions) {
293692
+ validateInstructions(plan, instructions, ledger, runReseed = false) {
293567
293693
  if (!plan) {
293568
293694
  throw new BadRequestError("Package has no persist sources; buildInstructions cannot be applied");
293569
293695
  }
@@ -293579,6 +293705,41 @@ class MaterializationService {
293579
293705
  throw new BadRequestError("realization=SNAPSHOT is not supported (COPY only)");
293580
293706
  }
293581
293707
  }
293708
+ if (ledger === undefined || ledger.length === 0)
293709
+ return;
293710
+ const instructed = new Map;
293711
+ const byAddress = new Map(Object.values(plan.sources).map((s) => [s.sourceEntityId, s]));
293712
+ for (const instruction of instructions) {
293713
+ const planSource = (instruction.sourceID ? plan.sources[instruction.sourceID] : undefined) ?? byAddress.get(instruction.sourceEntityId);
293714
+ if (!planSource)
293715
+ continue;
293716
+ instructed.set(`${planSource.connectionName}\x00${instruction.physicalTableName}`, {
293717
+ sourceEntityId: planSource.sourceEntityId,
293718
+ refresh: planSource.refresh ?? null,
293719
+ reseed: runReseed || instruction.reseed === true
293720
+ });
293721
+ }
293722
+ const seen = new Set;
293723
+ for (const entry of ledger) {
293724
+ const key = `${entry.connectionName}\x00${entry.physicalTableName}`;
293725
+ const table = `'${entry.physicalTableName}' on connection '${entry.connectionName}'`;
293726
+ if (seen.has(key)) {
293727
+ throw new BadRequestError(`Ledger entry for table ${table} appears more than once`);
293728
+ }
293729
+ seen.add(key);
293730
+ const target = instructed.get(key);
293731
+ if (!target) {
293732
+ throw new BadRequestError(`Ledger entry names table ${table}, which this run's ` + `instructions do not build`);
293733
+ }
293734
+ if (target.reseed)
293735
+ continue;
293736
+ if (target.refresh !== "incremental") {
293737
+ throw new BadRequestError(`Ledger entry names table ${table}, whose source does not ` + `declare refresh="incremental"`);
293738
+ }
293739
+ if (entry.sourceEntityId !== target.sourceEntityId) {
293740
+ throw new BadRequestError(`Ledger entry for table ${table} was measured under a ` + `different definition of its source (its sourceEntityId does ` + `not match the plan's) — expected after a publish or ` + `rollback that changed the source. Delete the entry to ` + `rebuild the source, or set reseed.`);
293741
+ }
293742
+ }
293582
293743
  }
293583
293744
  quoteSeedTablePath(sourceEntityId, physicalTableName, connectionName, connections) {
293584
293745
  const connection = connectionName ? connections.get(connectionName) : undefined;
@@ -293599,7 +293760,13 @@ class MaterializationService {
293599
293760
  }
293600
293761
  if (Object.keys(declarations).length === 0)
293601
293762
  return;
293602
- return { ...run, declarations, ledger: this.repository };
293763
+ const { ledger, ...rest } = run;
293764
+ return {
293765
+ ...rest,
293766
+ declarations,
293767
+ ledger: this.repository,
293768
+ ...ledger !== undefined ? { callerLedger: indexCallerLedger(ledger) } : {}
293769
+ };
293603
293770
  }
293604
293771
  async executeInstructedBuild(compiled, environment, instructions, seedEntries, signal, strict = false, owner, buildMetadata, incremental) {
293605
293772
  const { graphs, sources, connectionDigests, connections } = compiled;
@@ -293850,7 +294017,8 @@ class MaterializationService {
293850
294017
  physicalTableName,
293851
294018
  connectionName: persistSource.connectionName,
293852
294019
  realization: instruction.realization,
293853
- ...boundaryFields(seededThrough),
294020
+ ...ledgerFields(incrementalRefresh?.lineage, seededThrough),
294021
+ ...refreshFields(incrementalRefresh ? "full" : undefined),
293854
294022
  rowCount: null
293855
294023
  };
293856
294024
  }
@@ -293909,7 +294077,8 @@ class MaterializationService {
293909
294077
  connectionName: persistSource.connectionName,
293910
294078
  realization: instruction.realization,
293911
294079
  rowCount: null,
293912
- ...boundaryFields(step.coveredThrough)
294080
+ ...ledgerFields(lineage, step.coveredThrough),
294081
+ ...refreshFields(step.mode === "delta" ? "delta" : "none")
293913
294082
  };
293914
294083
  }
293915
294084
  async buildOneSourceIntoStorage(persistSource, instruction, manifest, environment, buildSQL, builtEntries, dependsOnStorageUpstream) {
@@ -294491,7 +294660,7 @@ var ASSET_EXTENSIONS = new Set([
294491
294660
  "woff2",
294492
294661
  "xlsx"
294493
294662
  ]);
294494
- var SPA_OWNED_SEGMENTS = new Set(["pages", "workbook"]);
294663
+ var SPA_OWNED_SEGMENTS = new Set(["data-apps", "pages", "workbook"]);
294495
294664
  function extensionOf(segment) {
294496
294665
  const dot = segment.lastIndexOf(".");
294497
294666
  if (dot <= 0 || dot === segment.length - 1)
@@ -294803,7 +294972,7 @@ app.get("/environments/:environmentName/packages/:packageName", (req, res, next)
294803
294972
  res.redirect(308, withRequestQuery(req, canonical));
294804
294973
  });
294805
294974
  app.get("/environments/:environmentName/packages/:packageName/*", serveFromPackage);
294806
- var PAGES_DEPTH_CAP = 3;
294975
+ var DATA_APPS_DEPTH_CAP = 3;
294807
294976
  var NON_TAG_TEXT_PATTERN = /<!--[\s\S]*?-->|<!--[\s\S]*$|<(script|style|title|textarea)\b[\s\S]*?<\/\1\s*>/gi;
294808
294977
  function stripNonTagText(input) {
294809
294978
  let current = input;
@@ -294814,7 +294983,7 @@ function stripNonTagText(input) {
294814
294983
  } while (current !== previous);
294815
294984
  return current;
294816
294985
  }
294817
- async function listPackagePages(environmentName, packageName, publicRoot) {
294986
+ async function listPackageDataApps(environmentName, packageName, publicRoot) {
294818
294987
  const fs11 = await import("fs/promises");
294819
294988
  const out = [];
294820
294989
  let realPublicRoot;
@@ -294824,7 +294993,7 @@ async function listPackagePages(environmentName, packageName, publicRoot) {
294824
294993
  return out;
294825
294994
  }
294826
294995
  async function walk(dir, depth) {
294827
- if (depth > PAGES_DEPTH_CAP)
294996
+ if (depth > DATA_APPS_DEPTH_CAP)
294828
294997
  return;
294829
294998
  let entries;
294830
294999
  try {
@@ -294921,14 +295090,14 @@ try {
294921
295090
  logger.warn("Failed to register Prometheus metrics endpoint", { error });
294922
295091
  }
294923
295092
  app.use(drainingGuard);
294924
- app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/pages`, async (req, res) => {
295093
+ app.get(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/data-apps`, async (req, res) => {
294925
295094
  try {
294926
295095
  const environment = await environmentStore.getEnvironment(req.params.environmentName, false);
294927
295096
  const pkg = await environment.getPackage(req.params.packageName, false);
294928
- const pages = await listPackagePages(req.params.environmentName, req.params.packageName, path14.join(pkg.getPackagePath(), "public"));
294929
- res.json(pages);
295097
+ const dataApps = await listPackageDataApps(req.params.environmentName, req.params.packageName, path14.join(pkg.getPackagePath(), "public"));
295098
+ res.json(dataApps);
294930
295099
  } catch (error) {
294931
- logger.error("Failed to list package pages", { error });
295100
+ logger.error("Failed to list package data apps", { error });
294932
295101
  const { json, status } = internalErrorToHttpError(error);
294933
295102
  res.status(status).json(json);
294934
295103
  }
@@ -295442,7 +295611,7 @@ app.post(`${API_PREFIX2}/environments/:environmentName/packages/:packageName/mod
295442
295611
  queryMetadata: req.body?.queryMetadata,
295443
295612
  queryClass: req.body?.queryClass,
295444
295613
  versionId: req.body?.versionId
295445
- });
295614
+ }, readBypassAuthorize(req));
295446
295615
  setFilterDeprecationHeaders(res, {
295447
295616
  filterParams: req.body.filterParams ?? req.body.sourceFilters,
295448
295617
  bypassFilters: req.body.bypassFilters === true ? true : undefined
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@malloy-publisher/server",
3
3
  "description": "Malloy Publisher Server",
4
- "version": "0.0.240",
4
+ "version": "0.0.242",
5
5
  "main": "dist/server.mjs",
6
6
  "bin": {
7
7
  "malloy-publisher": "dist/server.mjs"
@@ -1 +0,0 @@
1
- import{$ as t,j as o,J as a}from"./index-ByceOJbS.js";function s(){const n=t();return o.jsx(a,{onClickEnvironment:n})}export{s as default};
@@ -1 +0,0 @@
1
- import{F as j,$ as y,N,j as e,a0 as c,a1 as f,G as s,a2 as k,a3 as u,a4 as v,T as o,a5 as t,a6 as l}from"./index-ByceOJbS.js";function b(){const a=j(),n=a["*"],d=y(),{server:p}=N();if(!a.environmentName)return e.jsx("div",{children:e.jsx("h2",{children:"Missing environment name"})});if(!a.packageName)return e.jsx("div",{children:e.jsx("h2",{children:"Missing package name"})});const i={p:3,maxWidth:1200,mx:"auto"};if(n?.startsWith("pages/")&&!n.endsWith(".malloy")&&!n.endsWith(".malloynb")){const h=n.slice(6),g=c({environmentName:a.environmentName,packageName:a.packageName,modelPath:h});return e.jsx(f,{resourceUri:g})}const r=c({environmentName:a.environmentName,packageName:a.packageName,modelPath:n});if(n?.endsWith(".malloy"))return e.jsx(s,{sx:i,children:e.jsx(k,{resourceUri:r,runOnDemand:!0,maxResultSize:512*1024})});if(n?.endsWith(".malloynb"))return e.jsx(s,{sx:i,children:e.jsx(u,{resourceUri:r,maxResultSize:1024*1024,onNavigate:d})});const x=/\.[^./]+$/.test(n??""),m=v({server:p,environmentName:a.environmentName,packageName:a.packageName,path:n??""});return e.jsxs(s,{sx:i,children:[e.jsx(o,{variant:"h6",sx:{fontWeight:600},children:"Nothing to open at this path"}),e.jsxs(o,{variant:"body2",color:"text.secondary",sx:{mt:1},children:[e.jsx(s,{component:"span",sx:{fontFamily:t},children:n})," ","does not name a"," ",e.jsx(s,{component:"span",sx:{fontFamily:t},children:".malloy"})," ","or"," ",e.jsx(s,{component:"span",sx:{fontFamily:t},children:".malloynb"})," ","file in package"," ",e.jsx(s,{component:"span",sx:{fontFamily:t},children:a.packageName}),". This address opens"," ",e.jsx(s,{component:"span",sx:{fontFamily:t},children:".malloy"})," ","and"," ",e.jsx(s,{component:"span",sx:{fontFamily:t},children:".malloynb"})," ","files."]}),x&&e.jsxs(o,{variant:"body2",color:"text.secondary",sx:{mt:1},children:["A file from the package's"," ",e.jsx(s,{component:"span",sx:{fontFamily:t},children:"public/"})," ","directory is served at ",e.jsx(l,{href:m,children:m}),"."]}),e.jsxs(o,{variant:"body2",color:"text.secondary",sx:{mt:1},children:[e.jsxs(l,{href:`/${encodeURIComponent(a.environmentName)}/${encodeURIComponent(a.packageName)}`,children:["Back to ",a.packageName]})," ","lists this package's models, notebooks, and pages."]})]})}export{b as default};
@@ -1 +0,0 @@
1
- import{aa as o,j as r,ab as s,ac as a,G as n,T as t}from"./index-ByceOJbS.js";function x(){const e=o();return console.error(e),r.jsx(s,{maxWidth:"lg",component:"main",sx:{display:"flex",flexDirection:"column",my:2,gap:0},children:r.jsxs(a,{sx:{m:"auto",flexDirection:"column"},children:[r.jsx(n,{sx:{height:"300px"}}),r.jsx("img",{src:"/error.png"}),r.jsx(t,{variant:"subtitle1",children:"An unexpected error occurred"})]})})}export{x as default};