All files / backend/src/import folder-importer.ts

13.33% Statements 4/30
0% Branches 0/12
33.33% Functions 1/3
13.33% Lines 4/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146                                                                                                    9x 9x 9x 9x                                                                                                                                                                                        
/**
 * Folder Importer
 *
 * Imports Hugo sites from local directories.
 */
 
import fs from 'fs-extra';
import path from 'path';
import type { PathHelper } from '../utils/path-helper.js';
import type { FormatProviderResolver } from '../utils/format-provider-resolver.js';
import { pathIsDirectory, filenameFromPath } from '../utils/file-dir-utils.js';
import type { LibraryService } from '../services/library/library-service.js';
import { WorkspaceConfigProvider } from '../services/workspace/workspace-config-provider.js';
import { InitialWorkspaceConfigBuilder } from '../services/workspace/initial-workspace-config-builder.js';
import type { WorkspaceConfig } from '../services/workspace/workspace-config-validator.js';
import { SiteConfig, siteConfigSchema } from '@quiqr/types';
 
/**
 * Site inspection inventory - detailed info about a folder's contents
 */
export interface SiteInventory {
  dirExist: boolean;
  dirName: string;
  hugoConfigExists: boolean;
  hugoConfigParsed: SiteConfig | null;
  hugoThemesDirExists: boolean;
  hugoContentDirExists: boolean;
  hugoDataDirExists: boolean;
  hugoStaticDirExists: boolean;
  quiqrModelDirExists: boolean;
  quiqrFormsDirExists: boolean;
  quiqrDirExists: boolean;
  quiqrModelParsed: WorkspaceConfig | null;
}
 
/**
 * FolderImporter - Imports Hugo sites from local directories
 */
export class FolderImporter {
  private pathHelper: PathHelper;
  private formatProviderResolver: FormatProviderResolver;
  private libraryService: LibraryService;
  private workspaceConfigProvider: WorkspaceConfigProvider;
 
  constructor(
    pathHelper: PathHelper,
    formatProviderResolver: FormatProviderResolver,
    libraryService: LibraryService,
    workspaceConfigProvider: WorkspaceConfigProvider
  ) {
    this.pathHelper = pathHelper;
    this.formatProviderResolver = formatProviderResolver;
    this.libraryService = libraryService;
    this.workspaceConfigProvider = workspaceConfigProvider;
  }
 
  /**
   * Inspect a site directory to determine what type of site it is
   * and what components are present
   */
  async siteDirectoryInspect(folder: string): Promise<SiteInventory> {
    const inventory: SiteInventory = {
      dirExist: pathIsDirectory(folder),
      dirName: filenameFromPath(folder),
      hugoConfigExists: false,
      hugoConfigParsed: null,
      hugoThemesDirExists: pathIsDirectory(path.join(folder, 'themes')),
      hugoContentDirExists: pathIsDirectory(path.join(folder, 'content')),
      hugoDataDirExists: pathIsDirectory(path.join(folder, 'data')),
      hugoStaticDirExists: pathIsDirectory(path.join(folder, 'static')),
      quiqrModelDirExists: pathIsDirectory(path.join(folder, 'quiqr', 'model')),
      quiqrFormsDirExists: pathIsDirectory(path.join(folder, 'quiqr', 'forms')),
      quiqrDirExists: pathIsDirectory(path.join(folder, 'quiqr')),
      quiqrModelParsed: null,
    };
 
    // Check if Quiqr model exists and parse it
    const quiqrModelPath = this.workspaceConfigProvider.getQuiqrModelBasePath(folder);
    if (quiqrModelPath) {
      inventory.quiqrModelParsed = await this.workspaceConfigProvider.readOrCreateMinimalModelConfig(
        folder,
        'source'
      );
    }
 
    // Check if Hugo config exists and parse it
    const hugoConfigFilePath = this.pathHelper.hugoConfigFilePath(folder);
    if (hugoConfigFilePath) {
      const strData = fs.readFileSync(hugoConfigFilePath, { encoding: 'utf-8' });
      const formatProvider = this.formatProviderResolver.resolveForFilePath(hugoConfigFilePath);
      if (formatProvider) {
        const config = formatProvider.parse(strData);
        const result = siteConfigSchema.safeParse(config)
 
        inventory.hugoConfigParsed = null;
        inventory.hugoConfigExists = false;
        
        if (result.data) {
          inventory.hugoConfigParsed = result.data;
          inventory.hugoConfigExists = true;
        }
      }
    }
 
    return inventory;
  }
 
  /**
   * Create a new site from a local directory
   *
   * @param directory - Path to the directory containing the site
   * @param siteName - Name for the new site
   * @param generateQuiqrModel - Whether to generate Quiqr model files
   * @param hugoVersion - Hugo version to use
   * @returns The site key of the newly created site
   */
  async newSiteFromLocalDirectory(
    directory: string,
    siteName: string,
    generateQuiqrModel: boolean,
    hugoVersion?: string
  ): Promise<string> {
    const siteKey = await this.libraryService.createSiteKeyFromName(siteName);
 
    // Copy directory to temp location
    const tempCopyDir = path.join(this.pathHelper.getTempDir(), 'siteFromDir');
    fs.removeSync(tempCopyDir);
    await fs.copy(directory, tempCopyDir);
 
    // Generate Quiqr model if requested
    if (generateQuiqrModel && hugoVersion) {
      const configBuilder = new InitialWorkspaceConfigBuilder(
        tempCopyDir,
        this.formatProviderResolver,
        this.pathHelper
      );
      configBuilder.buildAll('hugo', hugoVersion);
    }
 
    // Create the site from the temp directory
    await this.libraryService.createNewSiteWithTempDirAndKey(siteKey, tempCopyDir);
 
    return siteKey;
  }
}