@qualcomm-ui/mdx-vite 2.10.0 → 2.11.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.
package/dist/cli.js CHANGED
@@ -3570,15 +3570,41 @@ var knowledgeIntegrationSchema = implement().with(
3570
3570
  exclude: z2.array(z2.string()).optional(),
3571
3571
  exports: knowledgeExportsSchema.optional(),
3572
3572
  extraFiles: z2.array(knowledgeExtraFileSchema).optional(),
3573
+ frontmatterFields: z2.union([z2.array(z2.string()), z2.any()]).optional(),
3573
3574
  metadata: z2.record(z2.string(), z2.string()).optional(),
3574
3575
  name: z2.string().optional(),
3575
3576
  outputMode: z2.union([z2.literal("per-page"), z2.literal("aggregated")]).optional(),
3576
3577
  outputPath: z2.string().optional(),
3578
+ pageIdPrefix: z2.string().optional(),
3577
3579
  pageTitlePrefix: z2.string().optional()
3578
3580
  }
3579
3581
  );
3582
+ var knowledgeEnvironmentSchema = implement().with({
3583
+ baseUrl: z2.string().optional(),
3584
+ description: z2.string().optional(),
3585
+ exclude: z2.array(z2.string()).optional(),
3586
+ exports: knowledgeExportsSchema.optional(),
3587
+ extraFiles: z2.array(knowledgeExtraFileSchema).optional(),
3588
+ frontmatterFields: z2.array(z2.string()).optional(),
3589
+ id: z2.string(),
3590
+ metadata: z2.record(z2.string(), z2.string()).optional(),
3591
+ name: z2.string().optional(),
3592
+ outputMode: z2.union([z2.literal("per-page"), z2.literal("aggregated")]).optional(),
3593
+ outputPath: z2.string(),
3594
+ pageIdPrefix: z2.string().optional(),
3595
+ pageTitlePrefix: z2.string().optional()
3596
+ });
3597
+ var openWebUiIntegrationSchema = implement().with({
3598
+ envFile: z2.string().optional(),
3599
+ id: z2.string()
3600
+ });
3601
+ var knowledgeIntegrationsSchema = implement().with({
3602
+ openWebUi: z2.array(openWebUiIntegrationSchema).optional()
3603
+ });
3580
3604
  var knowledgeConfigSchema = implement().with({
3581
- global: knowledgeIntegrationSchema.optional()
3605
+ environments: z2.array(knowledgeEnvironmentSchema).optional(),
3606
+ global: knowledgeIntegrationSchema.optional(),
3607
+ integrations: knowledgeIntegrationsSchema.optional()
3582
3608
  });
3583
3609
  var configSchema = implement().with({
3584
3610
  appDirectory: z2.string().optional(),
@@ -5595,7 +5621,6 @@ var KnowledgeApi = class {
5595
5621
  import { config } from "dotenv";
5596
5622
  function loadEnv() {
5597
5623
  const options = program.optsWithGlobals();
5598
- console.debug(options);
5599
5624
  if (options.env) {
5600
5625
  config({ path: options.env });
5601
5626
  } else {
@@ -5615,6 +5640,40 @@ function getConfigFromEnv() {
5615
5640
  webUiUrl: openWebUiUrl
5616
5641
  };
5617
5642
  }
5643
+ function loadOpenWebUiEnv(integration, integrationName) {
5644
+ const envFilePath = integration.envFile ?? `.env.${integration.id}`;
5645
+ config({ override: true, path: envFilePath });
5646
+ const url = process.env.OPEN_WEB_UI_URL ?? process.env.WEB_UI_URL;
5647
+ const apiKey = process.env.OPEN_WEB_UI_API_KEY ?? process.env.WEB_UI_KEY;
5648
+ const knowledgeId = process.env.OPEN_WEB_UI_KNOWLEDGE_ID ?? process.env.KNOWLEDGE_ID;
5649
+ if (!url) {
5650
+ throw new Error(
5651
+ `Missing OPEN_WEB_UI_URL for integration "${integrationName}" (env file: ${envFilePath})`
5652
+ );
5653
+ }
5654
+ if (!apiKey) {
5655
+ throw new Error(
5656
+ `Missing OPEN_WEB_UI_API_KEY for integration "${integrationName}" (env file: ${envFilePath})`
5657
+ );
5658
+ }
5659
+ if (!knowledgeId) {
5660
+ throw new Error(
5661
+ `Missing OPEN_WEB_UI_KNOWLEDGE_ID for integration "${integrationName}" (env file: ${envFilePath})`
5662
+ );
5663
+ }
5664
+ return { apiKey, knowledgeId, url };
5665
+ }
5666
+ function resolveOpenWebUiIntegration(name, integration, outputPath) {
5667
+ const credentials = loadOpenWebUiEnv(integration, name);
5668
+ return {
5669
+ apiKey: credentials.apiKey,
5670
+ environment: integration.id,
5671
+ knowledgeId: credentials.knowledgeId,
5672
+ name,
5673
+ outputPath,
5674
+ url: credentials.url
5675
+ };
5676
+ }
5618
5677
 
5619
5678
  // src/open-web-ui-knowledge/download-knowledge.ts
5620
5679
  function addDownloadKnowledgeCommand() {
@@ -5648,6 +5707,7 @@ function addDownloadKnowledgeCommand() {
5648
5707
  }
5649
5708
 
5650
5709
  // src/open-web-ui-knowledge/generate-knowledge.ts
5710
+ import chalk3 from "chalk";
5651
5711
  import { minimatch } from "minimatch";
5652
5712
  import {
5653
5713
  access,
@@ -5708,6 +5768,100 @@ function loadKnowledgeConfigFromEnv(options) {
5708
5768
  routeDir
5709
5769
  };
5710
5770
  }
5771
+ function mergeEnvironmentConfig(global, environment) {
5772
+ return {
5773
+ ...global,
5774
+ ...environment,
5775
+ extraFiles: environment.extraFiles ?? global?.extraFiles,
5776
+ metadata: global?.metadata || environment.metadata ? { ...global?.metadata, ...environment.metadata } : void 0
5777
+ };
5778
+ }
5779
+ function loadEnvironmentConfigs(options = {}) {
5780
+ const configLoader = new ConfigLoader({});
5781
+ const resolvedConfig = configLoader.loadConfig();
5782
+ const knowledgeConfig = resolvedConfig.knowledge;
5783
+ const globalConfig = knowledgeConfig?.global;
5784
+ const environments = knowledgeConfig?.environments;
5785
+ const routeDir = join2(
5786
+ resolvedConfig.appDirectory,
5787
+ resolvedConfig.pageDirectory
5788
+ );
5789
+ if (!existsSync(resolve3(routeDir))) {
5790
+ throw new Error(`Route directory ${routeDir} does not exist`);
5791
+ }
5792
+ if (!environments || environments.length === 0) {
5793
+ const legacyConfig = loadKnowledgeConfigFromEnv(
5794
+ options.cliOptions ?? { outputMode: "per-page" }
5795
+ );
5796
+ return [legacyConfig];
5797
+ }
5798
+ let filteredEnvironments = environments;
5799
+ if (options.environments?.length) {
5800
+ const filterSet = new Set(options.environments);
5801
+ filteredEnvironments = environments.filter((env) => filterSet.has(env.id));
5802
+ }
5803
+ if (filteredEnvironments.length === 0) {
5804
+ throw new Error(
5805
+ `No matching environments found. Available: ${environments.map((e) => e.id).join(", ")}`
5806
+ );
5807
+ }
5808
+ return filteredEnvironments.map((envConfig) => {
5809
+ const merged = mergeEnvironmentConfig(globalConfig, envConfig);
5810
+ const cliOpts = options.cliOptions;
5811
+ const cliMetadata = parseCliMetadata(cliOpts?.metadata);
5812
+ const mergedMetadata = merged.metadata || cliMetadata ? { ...merged.metadata, ...cliMetadata } : void 0;
5813
+ return {
5814
+ ...merged,
5815
+ ...cliOpts,
5816
+ baseUrl: cliOpts?.baseUrl ?? merged.baseUrl ?? process.env.DOCS_SITE_BASE_URL,
5817
+ docPropsPath: resolvedConfig.typeDocProps,
5818
+ environmentName: envConfig.id,
5819
+ exclude: (cliOpts?.exclude?.length ? cliOpts.exclude : void 0) ?? merged.exclude ?? (process.env.FILE_EXCLUDE_PATTERN ?? "").split(",").filter(Boolean),
5820
+ extraFiles: merged.extraFiles,
5821
+ metadata: mergedMetadata,
5822
+ outputMode: cliOpts?.outputMode ?? merged.outputMode ?? "per-page",
5823
+ outputPath: merged.outputPath,
5824
+ pageTitlePrefix: cliOpts?.pageTitlePrefix ?? merged.pageTitlePrefix ?? process.env.PAGE_TITLE_PREFIX,
5825
+ routeDir
5826
+ };
5827
+ });
5828
+ }
5829
+ function loadOpenWebUiIntegrations(options = {}) {
5830
+ const configLoader = new ConfigLoader({});
5831
+ const resolvedConfig = configLoader.loadConfig();
5832
+ const knowledgeConfig = resolvedConfig.knowledge;
5833
+ const environments = knowledgeConfig?.environments;
5834
+ const integrations = knowledgeConfig?.integrations?.openWebUi;
5835
+ if (!integrations || integrations.length === 0) {
5836
+ return [];
5837
+ }
5838
+ let filteredIntegrations = integrations;
5839
+ if (options.integrations?.length) {
5840
+ const filterSet = new Set(options.integrations);
5841
+ filteredIntegrations = integrations.filter(
5842
+ (integration) => filterSet.has(integration.id)
5843
+ );
5844
+ }
5845
+ if (options.environments?.length) {
5846
+ const filterSet = new Set(options.environments);
5847
+ filteredIntegrations = filteredIntegrations.filter(
5848
+ (integration) => filterSet.has(integration.id)
5849
+ );
5850
+ }
5851
+ return filteredIntegrations.map((integration) => {
5852
+ const envConfig = environments?.find((e) => e.id === integration.id);
5853
+ if (!envConfig) {
5854
+ throw new Error(
5855
+ `Integration "${integration.id}" references unknown environment "${integration.id}". Available environments: ${environments?.map((e) => e.id).join(", ") || "none"}`
5856
+ );
5857
+ }
5858
+ return {
5859
+ integration,
5860
+ name: integration.id,
5861
+ outputPath: envConfig.outputPath
5862
+ };
5863
+ });
5864
+ }
5711
5865
 
5712
5866
  // src/open-web-ui-knowledge/generate-knowledge.ts
5713
5867
  async function exists(dirPath) {
@@ -5881,7 +6035,6 @@ var KnowledgeGenerator = class {
5881
6035
  processedPages,
5882
6036
  extractedMetadata
5883
6037
  );
5884
- await this.generateExtraFiles(extractedMetadata);
5885
6038
  }
5886
6039
  return pages;
5887
6040
  }
@@ -5935,6 +6088,7 @@ var KnowledgeGenerator = class {
5935
6088
  const mdxFiles = entries.filter(
5936
6089
  (f) => f.name.endsWith(".mdx") && !shouldExclude(join3(dirPath, f.name))
5937
6090
  ) ?? [];
6091
+ const pageIdPrefix = this.config.pageIdPrefix ?? "";
5938
6092
  for (const mdxFile of mdxFiles) {
5939
6093
  const demosFolder = entries.find((f) => f.name === "demos");
5940
6094
  const demosFolderPath = demosFolder ? join3(dirPath, demosFolder.name) : void 0;
@@ -5946,7 +6100,7 @@ var KnowledgeGenerator = class {
5946
6100
  components.push({
5947
6101
  demosFolder: demosFolderPath,
5948
6102
  filePath: dirPath,
5949
- id: segments.join("-").trim(),
6103
+ id: `${pageIdPrefix ? `${pageIdPrefix}-` : ""}${segments.join("-").trim()}`,
5950
6104
  mdxFile: join3(dirPath, mdxFile.name),
5951
6105
  name: segments.at(-1),
5952
6106
  pathname: url,
@@ -6481,9 +6635,10 @@ ${propsToDefinitionList(outputs)}`);
6481
6635
  console.log(`File size: ${outputSizeKb} KB`);
6482
6636
  }
6483
6637
  async generateExtraFiles(metadata) {
6638
+ const start = performance.now();
6484
6639
  const extraFiles = this.config.extraFiles ?? [];
6485
6640
  if (extraFiles.length === 0) {
6486
- return;
6641
+ return { count: 0, duration: 0, totalSize: 0 };
6487
6642
  }
6488
6643
  let totalSize = 0;
6489
6644
  await Promise.all(
@@ -6514,11 +6669,14 @@ ${propsToDefinitionList(outputs)}`);
6514
6669
  totalSize += stats.size / 1024;
6515
6670
  })
6516
6671
  );
6517
- console.log(
6518
- `Generated ${extraFiles.length} extra file(s) (${totalSize.toFixed(1)} KB)`
6519
- );
6672
+ return {
6673
+ count: extraFiles.length,
6674
+ duration: performance.now() - start,
6675
+ totalSize
6676
+ };
6520
6677
  }
6521
6678
  async generatePerPageExports(pages, processedPages, metadata) {
6679
+ const start = performance.now();
6522
6680
  await mkdir2(dirname(this.config.outputPath), { recursive: true }).catch(
6523
6681
  () => {
6524
6682
  }
@@ -6529,16 +6687,38 @@ ${propsToDefinitionList(outputs)}`);
6529
6687
  processedPages.map(async (processedPage, index) => {
6530
6688
  const page = pages[index];
6531
6689
  const lines = [];
6532
- if (metadata.length || page.url) {
6533
- lines.push("---");
6534
- if (page.url) {
6535
- lines.push(`url: ${page.url}`);
6536
- }
6537
- if (metadata.length) {
6538
- for (const [key, value] of metadata) {
6539
- lines.push(`${key}: ${value}`);
6690
+ const frontmatterEntries = [];
6691
+ if (page.url) {
6692
+ frontmatterEntries.push(["url", page.url]);
6693
+ }
6694
+ for (const [key, value] of metadata) {
6695
+ frontmatterEntries.push([key, value]);
6696
+ }
6697
+ if (this.config.frontmatterFields) {
6698
+ if (typeof this.config.frontmatterFields === "function") {
6699
+ const transformed = this.config.frontmatterFields(
6700
+ processedPage.frontmatter,
6701
+ page
6702
+ );
6703
+ for (const [key, value] of Object.entries(transformed)) {
6704
+ if (value !== void 0) {
6705
+ frontmatterEntries.push([key, String(value)]);
6706
+ }
6707
+ }
6708
+ } else {
6709
+ for (const field of this.config.frontmatterFields) {
6710
+ const value = processedPage.frontmatter[field];
6711
+ if (value !== void 0) {
6712
+ frontmatterEntries.push([field, String(value)]);
6713
+ }
6540
6714
  }
6541
6715
  }
6716
+ }
6717
+ if (frontmatterEntries.length > 0) {
6718
+ lines.push("---");
6719
+ for (const [key, value] of frontmatterEntries) {
6720
+ lines.push(`${key}: ${value}`);
6721
+ }
6542
6722
  lines.push("---");
6543
6723
  lines.push("");
6544
6724
  }
@@ -6603,8 +6783,10 @@ ${propsToDefinitionList(outputs)}`);
6603
6783
  totalSize += stats.size / 1024;
6604
6784
  })
6605
6785
  );
6606
- console.log(`Generated ${count} files(s) in ${this.config.outputPath}`);
6607
- console.log(`Folder size: ${totalSize.toFixed(1)} KB`);
6786
+ const extraFilesResult = await this.generateExtraFiles(metadata);
6787
+ console.log(
6788
+ `Generated ${count + extraFilesResult.count} files(s) in ${chalk3.magenta.bold(`${Math.round(performance.now() - start + extraFilesResult.duration)}ms`)} at ${chalk3.blue.bold(this.config.outputPath)} - ${(totalSize + extraFilesResult.totalSize).toFixed(1)} KB`
6789
+ );
6608
6790
  }
6609
6791
  };
6610
6792
  async function generate(config2) {
@@ -6619,13 +6801,31 @@ function addGenerateKnowledgeCommand() {
6619
6801
  "--exclude <patterns...>",
6620
6802
  "Glob patterns to exclude (e.g., **/internal/**, guide/drafts/*)",
6621
6803
  []
6622
- ).option("--base-url <url>", "Base URL for component documentation links").option("--metadata <pairs...>", "metadata key-value pairs").option("--clean", "Clean the output path before generating").option("--include-imports", "Include relative import source files", true).action(async (options) => {
6804
+ ).option("--base-url <url>", "Base URL for component documentation links").option("--metadata <pairs...>", "metadata key-value pairs").option("--clean", "Clean the output path before generating").option("--include-imports", "Include relative import source files", true).option(
6805
+ "-e, --environment <environments>",
6806
+ "Comma-separated list of environments to generate (default: all)"
6807
+ ).action(async (options) => {
6623
6808
  loadEnv();
6624
- const knowledgeConfig = loadKnowledgeConfigFromEnv({
6809
+ const cliOptions = {
6625
6810
  ...options,
6626
6811
  outputMode: options.outputMode === "per-page" ? "per-page" : "aggregated"
6812
+ };
6813
+ const environmentFilter = options.environment?.split(",").map((e) => e.trim()).filter(Boolean);
6814
+ const configs = loadEnvironmentConfigs({
6815
+ cliOptions,
6816
+ environments: environmentFilter
6627
6817
  });
6628
- await generate(knowledgeConfig);
6818
+ for (const config2 of configs) {
6819
+ const envLabel = config2.environmentName ? `[${config2.environmentName}] ` : "";
6820
+ console.log(`${envLabel}Generating knowledge to ${config2.outputPath}`);
6821
+ await generate(config2);
6822
+ }
6823
+ if (configs.length > 1) {
6824
+ console.log(
6825
+ `
6826
+ Generated knowledge for ${configs.length} environment(s)`
6827
+ );
6828
+ }
6629
6829
  });
6630
6830
  }
6631
6831
 
@@ -6770,7 +6970,10 @@ var Uploader = class {
6770
6970
  }))
6771
6971
  );
6772
6972
  const knowledge = await this.knowledgeApi.getById(this.config.knowledgeId);
6773
- this.knowledgeFilesCache = (knowledge.files ?? []).map(toKnowledgeFile);
6973
+ const receivedFiles = knowledge.files?.length ? knowledge.files.map(toKnowledgeFile) : await this.filesApi.list().then(
6974
+ (res) => res.filter((file) => file.meta.collection_name === knowledge.id)
6975
+ );
6976
+ this.knowledgeFilesCache = receivedFiles;
6774
6977
  await this.buildHashCache(this.knowledgeFilesCache);
6775
6978
  let skippedCount = 0;
6776
6979
  let successCount = 0;
@@ -6895,9 +7098,56 @@ function addUploadKnowledgeCommand() {
6895
7098
  program.name("upload-knowledge").description("Upload files to OpenWebUI knowledge base").command("upload-knowledge").option("-p, --path <path>", "Path to file or folder relative to script").option(
6896
7099
  "--force",
6897
7100
  "force upload files, even if their contents have not changed"
7101
+ ).option(
7102
+ "-i, --integration <integrations>",
7103
+ "Comma-separated list of integrations to upload to (default: all)"
7104
+ ).option(
7105
+ "-e, --environment <environments>",
7106
+ "Comma-separated list of environments to filter integrations by (default: all)"
6898
7107
  ).action(async (options) => {
6899
7108
  loadEnv();
6900
- return getUploader(options.path, options.force).uploadKnowledge();
7109
+ const integrationFilter = options.integration?.split(",").map((e) => e.trim()).filter(Boolean);
7110
+ const environmentFilter = options.environment?.split(",").map((e) => e.trim()).filter(Boolean);
7111
+ const integrations = loadOpenWebUiIntegrations({
7112
+ environments: environmentFilter,
7113
+ integrations: integrationFilter
7114
+ });
7115
+ if (integrations.length === 0) {
7116
+ console.log("No integrations configured, using legacy env vars");
7117
+ return getUploader(options.path, options.force).uploadKnowledge();
7118
+ }
7119
+ let successCount = 0;
7120
+ let failureCount = 0;
7121
+ for (const { integration, name, outputPath } of integrations) {
7122
+ console.log(`
7123
+ [${name}] Uploading to OpenWebUI...`);
7124
+ try {
7125
+ const resolved = resolveOpenWebUiIntegration(
7126
+ name,
7127
+ integration,
7128
+ outputPath
7129
+ );
7130
+ const uploader = new Uploader({
7131
+ force: options.force,
7132
+ knowledgeFilePath: options.path ?? resolved.outputPath,
7133
+ knowledgeId: resolved.knowledgeId,
7134
+ webUiKey: resolved.apiKey,
7135
+ webUiUrl: resolved.url
7136
+ });
7137
+ await uploader.uploadKnowledge();
7138
+ successCount++;
7139
+ console.log(`[${name}] Upload complete`);
7140
+ } catch (error) {
7141
+ failureCount++;
7142
+ console.error(`[${name}] Upload failed:`, error);
7143
+ }
7144
+ }
7145
+ if (integrations.length > 1) {
7146
+ console.log(
7147
+ `
7148
+ Uploaded to ${successCount} integration(s)${failureCount > 0 ? `, ${failureCount} failed` : ""}`
7149
+ );
7150
+ }
6901
7151
  });
6902
7152
  program.command("get-knowledge-files").description("Get files from OpenWebUI knowledge base").option("-p, --path <path>", "Path to file or folder relative to script").action(async (options) => {
6903
7153
  loadEnv();
@@ -6955,7 +7205,7 @@ import { resolve as resolve7 } from "node:path";
6955
7205
  import { dedent } from "@qualcomm-ui/utils/dedent";
6956
7206
 
6957
7207
  // src/react-demo-plugin/demo-plugin-utils.ts
6958
- import chalk3 from "chalk";
7208
+ import chalk4 from "chalk";
6959
7209
  import { existsSync as existsSync2, readFileSync as readFileSync2 } from "node:fs";
6960
7210
  import { dirname as dirname2, join as join4, relative as relative3, resolve as resolve6, sep } from "node:path";
6961
7211
  import * as ts from "typescript";