@malloy-publisher/server 0.4.0 → 0.5.0

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 (26) hide show
  1. package/README.docker.md +12 -2
  2. package/dist/app/api-doc.yaml +62 -3
  3. package/dist/app/assets/{EnvironmentPage-BnxD6uzV.js → EnvironmentPage-cVoREk0T.js} +1 -1
  4. package/dist/app/assets/{HomePage-D_srvBnZ.js → HomePage-9sQJEb1e.js} +1 -1
  5. package/dist/app/assets/{LightMode-DCsTKw61.js → LightMode-C8uGSmfv.js} +1 -1
  6. package/dist/app/assets/{MainPage-CzHkstrF.js → MainPage-BIG2W9IX.js} +2 -2
  7. package/dist/app/assets/ModelPage-DKkVe4Md.js +2 -0
  8. package/dist/app/assets/PackagePage-Cax6RcJM.js +1 -0
  9. package/dist/app/assets/RenderedResult-BB7eokcf.es-D-hyXuFF.js +136 -0
  10. package/dist/app/assets/{RouteError-gRAhsKGi.js → RouteError-BzJ2T1nX.js} +1 -1
  11. package/dist/app/assets/{ThemeEditorPage-C2gOJTU1.js → ThemeEditorPage-Ce7Cp5zL.js} +1 -1
  12. package/dist/app/assets/{ToggleButtonGroup-CoIPitu6.js → ToggleButtonGroup-DOVU2psA.js} +1 -1
  13. package/dist/app/assets/{index-BswZnpqD.js → index-BJv4aICx.js} +1 -1
  14. package/dist/app/assets/{index-hVLQwLRj.js → index-BOX8mX0R.js} +1 -1
  15. package/dist/app/assets/{index-BhkeAzTe.js → index-CPy5UJ3W.js} +1 -1
  16. package/dist/app/assets/{index-DTfS9vNi.js → index-DfULFk5d.js} +1 -1
  17. package/dist/app/assets/{index-DKvKsj6c.js → index-DycyDIlK.js} +76 -76
  18. package/dist/app/assets/index.es-Doid8lz7.js +111 -0
  19. package/dist/app/index.html +1 -1
  20. package/dist/package_load_worker.mjs +38 -60
  21. package/dist/server.mjs +739 -479
  22. package/package.json +1 -1
  23. package/dist/app/assets/ModelPage-CoQ07DHX.js +0 -2
  24. package/dist/app/assets/PackagePage-CUeUHOnm.js +0 -1
  25. package/dist/app/assets/RenderedResult-BnPzJ9Jf.es-Dme58kt1.js +0 -116
  26. package/dist/app/assets/index.es-D0L4_L8o.js +0 -106
@@ -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-DKvKsj6c.js"></script>
19
+ <script type="module" crossorigin src="/assets/index-DycyDIlK.js"></script>
20
20
  <link rel="stylesheet" crossorigin href="/assets/index-DUqldpo0.css">
21
21
  </head>
22
22
  <body>
@@ -14351,7 +14351,8 @@ var init_filter = __esm(() => {
14351
14351
  // src/service/source_extraction.ts
14352
14352
  import {
14353
14353
  isJoined as isJoined2,
14354
- isSourceDef as isSourceDef4
14354
+ isSourceDef as isSourceDef4,
14355
+ modelDefToModelInfo
14355
14356
  } from "@malloydata/malloy";
14356
14357
  function joinFieldNamesUnresolvableDeclaration(field, modelDef) {
14357
14358
  const ids = [field.referenceID, field.sourceID].filter((id) => !!id);
@@ -14370,7 +14371,7 @@ function joinFieldNamesUnresolvableDeclaration(field, modelDef) {
14370
14371
  function isEarlierPosition(a, b) {
14371
14372
  return a.line < b.line || a.line === b.line && a.character < b.character;
14372
14373
  }
14373
- function considerAuthorizeNoteOwner(declaredBy, note, candidate) {
14374
+ function considerNoteOwner(declaredBy, note, candidate) {
14374
14375
  const location = candidate.location;
14375
14376
  if (!location || location.url !== note.at.url)
14376
14377
  return;
@@ -14379,6 +14380,11 @@ function considerAuthorizeNoteOwner(declaredBy, note, candidate) {
14379
14380
  declaredBy.set(note, candidate);
14380
14381
  }
14381
14382
  }
14383
+ function collectSourceInfos(modelDef) {
14384
+ const names = Object.keys(modelDef.contents).filter((name) => isSourceDef4(modelDef.contents[name]));
14385
+ const exports = [...new Set([...modelDef.exports, ...names])];
14386
+ return modelDefToModelInfo({ ...modelDef, exports }).entries.filter((entry) => entry.kind === "source");
14387
+ }
14382
14388
  function extractSourcesFromModelDef(modelDef, givens, onParseError) {
14383
14389
  const filterMap = new Map;
14384
14390
  const authorizeMap = new Map;
@@ -14395,7 +14401,7 @@ function extractSourcesFromModelDef(modelDef, givens, onParseError) {
14395
14401
  for (const note of ownLevelNotes(struct.annotations)) {
14396
14402
  if (containsAuthorizeAnnotationTag([note.text])) {
14397
14403
  gatedSourceOwnAuthorizeNotes.add(note);
14398
- considerAuthorizeNoteOwner(authorizeNoteDeclaredBy, note, struct);
14404
+ considerNoteOwner(authorizeNoteDeclaredBy, note, struct);
14399
14405
  }
14400
14406
  }
14401
14407
  nearMissAuthorize.push(...collectAuthorizeNearMisses([
@@ -14413,7 +14419,7 @@ function extractSourcesFromModelDef(modelDef, givens, onParseError) {
14413
14419
  for (const note of ownLevelNotes(entry.annotations)) {
14414
14420
  if (containsAuthorizeAnnotationTag([note.text])) {
14415
14421
  gatedSourceOwnAuthorizeNotes.add(note);
14416
- considerAuthorizeNoteOwner(authorizeNoteDeclaredBy, note, entry);
14422
+ considerNoteOwner(authorizeNoteDeclaredBy, note, entry);
14417
14423
  }
14418
14424
  }
14419
14425
  nearMissAuthorize.push(...collectAuthorizeNearMisses(ownLevelNotes(entry.annotations).map((note) => note.text)));
@@ -15009,7 +15015,7 @@ import {
15009
15015
  isSourceDef as isSourceDef6,
15010
15016
  MalloyConfig,
15011
15017
  MalloyError as MalloyError2,
15012
- modelDefToModelInfo,
15018
+ modelDefToModelInfo as modelDefToModelInfo2,
15013
15019
  Runtime
15014
15020
  } from "@malloydata/malloy";
15015
15021
  import {
@@ -15407,39 +15413,11 @@ async function readPackageMetadata(packagePath) {
15407
15413
  }
15408
15414
  async function listPackageFiles(packagePath) {
15409
15415
  const files = await import_recursive_readdir.default(packagePath, [ignoreDotfiles]);
15410
- return files.map((full) => path2.relative(packagePath, full).replace(/\\/g, "/"));
15416
+ return files.map((full) => path2.relative(packagePath, full).replace(/\\/g, "/")).sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
15411
15417
  }
15412
15418
  function filterModelPaths(allRelative) {
15413
15419
  return allRelative.filter((p) => p.endsWith(MODEL_FILE_SUFFIX) || p.endsWith(NOTEBOOK_FILE_SUFFIX));
15414
15420
  }
15415
- async function collectImportedSourceInfos(modelDef, runtime, importBaseURL) {
15416
- const sourceInfos = [];
15417
- const importedNames = new Set;
15418
- const imports = modelDef.imports ?? [];
15419
- for (const importLocation of imports) {
15420
- try {
15421
- const modelString = await runtime.urlReader.readURL(new URL(importLocation.importURL));
15422
- const importedModelDef = (await runtime.loadModel(modelString, { importBaseURL }).getModel())._modelDef;
15423
- const importedInfo = modelDefToModelInfo(importedModelDef);
15424
- const importedSources = importedInfo.entries.filter((entry) => entry.kind === "source");
15425
- for (const source of importedSources) {
15426
- if (!importedNames.has(source.name)) {
15427
- sourceInfos.push(source);
15428
- importedNames.add(source.name);
15429
- }
15430
- }
15431
- } catch {}
15432
- }
15433
- return { sourceInfos, importedNames };
15434
- }
15435
- function appendLocalSourceInfos(modelDef, target, importedNames) {
15436
- const localInfo = modelDefToModelInfo(modelDef);
15437
- const localSources = localInfo.entries.filter((entry) => entry.kind === "source");
15438
- for (const source of localSources) {
15439
- if (!importedNames.has(source.name))
15440
- target.push(source);
15441
- }
15442
- }
15443
15421
  function extractSources(modelDef, givens) {
15444
15422
  const {
15445
15423
  sources,
@@ -15474,8 +15452,24 @@ function extractQueries(modelDef) {
15474
15452
  misplacedAuthorize
15475
15453
  };
15476
15454
  }
15455
+ function captureReadText(inner) {
15456
+ const texts = new Map;
15457
+ return {
15458
+ reader: {
15459
+ readURL: async (url) => {
15460
+ const contents = await inner.readURL(url);
15461
+ const key = url.toString();
15462
+ if (!texts.has(key))
15463
+ texts.set(key, contents);
15464
+ return contents;
15465
+ }
15466
+ },
15467
+ textFor: (url) => texts.get(url.toString())
15468
+ };
15469
+ }
15477
15470
  function buildRuntimeForModel(job, malloyConfig) {
15478
- const urlReader = new HackyDataStylesAccumulator(makeWorkerUrlReader(job));
15471
+ const { reader, textFor } = captureReadText(makeWorkerUrlReader(job));
15472
+ const urlReader = new HackyDataStylesAccumulator(reader);
15479
15473
  const runtime = new Runtime({
15480
15474
  urlReader,
15481
15475
  config: malloyConfig,
@@ -15484,21 +15478,20 @@ function buildRuntimeForModel(job, malloyConfig) {
15484
15478
  strict: false
15485
15479
  } : undefined
15486
15480
  });
15487
- return { runtime, urlReader };
15481
+ return { runtime, urlReader, textFor };
15488
15482
  }
15489
15483
  async function compileMalloyModel(job, malloyConfig, modelPath) {
15490
15484
  const compileStart = performance.now();
15491
15485
  const fullPath = path2.join(job.packagePath, modelPath);
15492
15486
  const modelURL = pathToFileURL(fullPath);
15493
15487
  const importBaseURL = new URL(".", modelURL);
15494
- const { runtime, urlReader } = buildRuntimeForModel(job, malloyConfig);
15488
+ const { runtime, urlReader, textFor } = buildRuntimeForModel(job, malloyConfig);
15495
15489
  const mm = runtime.loadModel(modelURL, { importBaseURL });
15496
15490
  const compiled = await mm.getModel();
15497
15491
  const modelDef = compiled._modelDef;
15498
15492
  const malloyGivens = Array.from(compiled.givens.values());
15499
15493
  const givens = malloyGivens.length > 0 ? malloyGivens.map((g) => malloyGivenToApi(g)) : undefined;
15500
- const { sourceInfos, importedNames } = await collectImportedSourceInfos(modelDef, runtime, importBaseURL);
15501
- appendLocalSourceInfos(modelDef, sourceInfos, importedNames);
15494
+ const sourceInfos = collectSourceInfos(modelDef);
15502
15495
  const {
15503
15496
  sources,
15504
15497
  filterMap,
@@ -15539,12 +15532,13 @@ async function compileMalloyModel(job, malloyConfig, modelPath) {
15539
15532
  modelPath,
15540
15533
  modelType: "model",
15541
15534
  modelDef,
15542
- modelInfo: modelDefToModelInfo(modelDef),
15535
+ modelInfo: modelDefToModelInfo2(modelDef),
15543
15536
  sourceInfos,
15544
15537
  sources,
15545
15538
  queries,
15546
15539
  filterMap: Array.from(filterMap.entries()),
15547
15540
  givens,
15541
+ modelSourceText: textFor(modelURL),
15548
15542
  dataStyles: urlReader.getHackyAccumulatedDataStyles(),
15549
15543
  compileDurationMs: performance.now() - compileStart,
15550
15544
  problems: job.collectProblems ? compiled.problems : undefined,
@@ -15567,7 +15561,6 @@ async function compileNotebookModel(job, malloyConfig, modelPath) {
15567
15561
  }
15568
15562
  return mm;
15569
15563
  });
15570
- const oldImports = [];
15571
15564
  const oldSources = {};
15572
15565
  const notebookCells = [];
15573
15566
  for (let i = 0;i < parse.statements.length; i++) {
@@ -15583,21 +15576,8 @@ async function compileNotebookModel(job, malloyConfig, modelPath) {
15583
15576
  continue;
15584
15577
  }
15585
15578
  const currentModelDef = (await localMM.getModel())._modelDef;
15586
- let newSources = [];
15587
- const newImports = currentModelDef.imports?.slice(oldImports.length);
15588
- if (newImports) {
15589
- for (const importLocation of newImports) {
15590
- try {
15591
- const modelString = await runtime.urlReader.readURL(new URL(importLocation.importURL));
15592
- const importModel = (await runtime.loadModel(modelString, { importBaseURL }).getModel())._modelDef;
15593
- const importInfo = modelDefToModelInfo(importModel);
15594
- newSources = importInfo.entries.filter((e) => e.kind === "source").filter((s) => !(s.name in oldSources));
15595
- oldImports.push(importLocation.importURL.toString());
15596
- } catch {}
15597
- }
15598
- }
15599
- const currentInfo = modelDefToModelInfo(currentModelDef);
15600
- newSources = newSources.concat(currentInfo.entries.filter((e) => e.kind === "source").filter((s) => !(s.name in oldSources)));
15579
+ const currentInfo = modelDefToModelInfo2(currentModelDef);
15580
+ const newSources = collectSourceInfos(currentModelDef).filter((s) => !(s.name in oldSources));
15601
15581
  for (const s of newSources)
15602
15582
  oldSources[s.name] = s;
15603
15583
  const runnable = localMM.loadFinalQuery();
@@ -15641,9 +15621,7 @@ async function compileNotebookModel(job, malloyConfig, modelPath) {
15641
15621
  finalModelDef = compiled._modelDef;
15642
15622
  const malloyGivens = Array.from(compiled.givens.values());
15643
15623
  finalGivens = malloyGivens.length > 0 ? malloyGivens.map((g) => malloyGivenToApi(g)) : undefined;
15644
- const collected = await collectImportedSourceInfos(finalModelDef, runtime, importBaseURL);
15645
- appendLocalSourceInfos(finalModelDef, collected.sourceInfos, collected.importedNames);
15646
- finalSourceInfos = collected.sourceInfos;
15624
+ finalSourceInfos = collectSourceInfos(finalModelDef);
15647
15625
  const extracted = extractSources(finalModelDef, finalGivens);
15648
15626
  finalSources = extracted.sources;
15649
15627
  attachSuggestGivenNames(finalGivens, suggestGivenLookup(finalModelDef, (name) => extracted.sources.find((source) => source.name === name)?.authorize, new Set((finalGivens ?? []).map((given) => given.name))));
@@ -15680,7 +15658,7 @@ async function compileNotebookModel(job, malloyConfig, modelPath) {
15680
15658
  modelPath,
15681
15659
  modelType: "notebook",
15682
15660
  modelDef: finalModelDef,
15683
- modelInfo: finalModelDef ? modelDefToModelInfo(finalModelDef) : undefined,
15661
+ modelInfo: finalModelDef ? modelDefToModelInfo2(finalModelDef) : undefined,
15684
15662
  sourceInfos: finalSourceInfos,
15685
15663
  sources: finalSources,
15686
15664
  queries: finalQueries,