@mdfriday/foundry 26.4.4 → 26.4.6

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
@@ -4292,6 +4292,30 @@ var init_workspace_factory = __esm({
4292
4292
  };
4293
4293
  }
4294
4294
  // ============================================================================
4295
+ // Folder Structure Scanning
4296
+ // ============================================================================
4297
+ /**
4298
+ * Scan folder structure
4299
+ *
4300
+ * 扫描文件夹结构,识别 content、content.{lang}、static 文件夹
4301
+ * 用于在创建项目前预览文件夹结构
4302
+ */
4303
+ async scanFolderStructure(folderPath) {
4304
+ if (!this.fileSystemRepo) {
4305
+ throw new Error("FileSystemRepository is required to scan folder structure");
4306
+ }
4307
+ log5.info("Scanning folder structure", { path: folderPath });
4308
+ const structure = await this.fileSystemRepo.scanFolderStructure(folderPath);
4309
+ const folderStructure = FolderStructure.fromScanResult(structure);
4310
+ log5.debug("Folder structure scanned", {
4311
+ isStructured: folderStructure.getIsStructured(),
4312
+ contentFolders: folderStructure.getContentFolderCount(),
4313
+ hasStatic: folderStructure.hasStaticFolder(),
4314
+ languages: folderStructure.getSupportedLanguages()
4315
+ });
4316
+ return folderStructure;
4317
+ }
4318
+ // ============================================================================
4295
4319
  // Private Helpers
4296
4320
  // ============================================================================
4297
4321
  createSampleContent() {
@@ -4548,6 +4572,18 @@ Please specify a project name with --project <name>`);
4548
4572
  return this.workspaceFactory.findProjectRoot(startPath);
4549
4573
  }
4550
4574
  // ============================================================================
4575
+ // Folder Structure Scanning
4576
+ // ============================================================================
4577
+ /**
4578
+ * Scan folder structure
4579
+ *
4580
+ * 扫描文件夹结构,识别 content、content.{lang}、static 文件夹
4581
+ * 用于在创建项目前预览文件夹结构
4582
+ */
4583
+ async scanFolderStructure(folderPath) {
4584
+ return this.workspaceFactory.scanFolderStructure(folderPath);
4585
+ }
4586
+ // ============================================================================
4551
4587
  // Cross-Domain: Identity Storage Integration
4552
4588
  // ============================================================================
4553
4589
  /**
@@ -8674,14 +8710,35 @@ var init_mdfriday_publisher = __esm({
8674
8710
  "MDFriday access token not found.\nPlease login first:\n mdf auth login"
8675
8711
  );
8676
8712
  }
8713
+ const { changedFiles, allFiles } = await this.getFileLists(
8714
+ sourceDir,
8715
+ options?.incremental
8716
+ );
8717
+ const isIncremental = options?.incremental && changedFiles.length < allFiles.length && changedFiles.length > 0;
8718
+ if (isIncremental) {
8719
+ log12.info(
8720
+ `Incremental deploy: ${changedFiles.length}/${allFiles.length} files (${Math.round(changedFiles.length / allFiles.length * 100)}%)`
8721
+ );
8722
+ } else if (options?.incremental && changedFiles.length === 0) {
8723
+ log12.info("No files changed, skipping deployment");
8724
+ return {
8725
+ success: true,
8726
+ url: "",
8727
+ filesUploaded: 0,
8728
+ bytesTransferred: 0,
8729
+ duration: Date.now() - startTime
8730
+ };
8731
+ }
8677
8732
  options?.onProgress?.({
8678
8733
  phase: "scanning",
8679
8734
  percentage: 5,
8680
- message: "Creating deployment package..."
8735
+ message: isIncremental ? `Creating incremental package (${changedFiles.length} files)...` : "Creating deployment package..."
8681
8736
  });
8682
- const zipContent = await this.createZipFromDirectory(sourceDir);
8737
+ const zipContent = isIncremental ? await this.createIncrementalZip(sourceDir, changedFiles) : await this.createZipFromDirectory(sourceDir);
8683
8738
  const zipSize = zipContent.length;
8684
- log12.info(`Created ZIP package: ${this.formatBytes(zipSize)}`);
8739
+ log12.info(
8740
+ `Created ${isIncremental ? "incremental" : "full"} ZIP package: ${this.formatBytes(zipSize)}`
8741
+ );
8685
8742
  options?.onProgress?.({
8686
8743
  phase: "scanning",
8687
8744
  percentage: 30,
@@ -8724,7 +8781,11 @@ var init_mdfriday_publisher = __esm({
8724
8781
  "mdfriday",
8725
8782
  { previewId, deploymentType: this.config.deploymentType }
8726
8783
  );
8727
- await this.manifestRepo.saveManifest(this.projectPath, manifest);
8784
+ await this.manifestRepo.saveManifest(
8785
+ this.projectPath,
8786
+ manifest,
8787
+ this.config.deploymentType
8788
+ );
8728
8789
  options?.onProgress?.({
8729
8790
  phase: "complete",
8730
8791
  percentage: 100,
@@ -8735,7 +8796,7 @@ var init_mdfriday_publisher = __esm({
8735
8796
  return {
8736
8797
  success: true,
8737
8798
  url: deployUrl,
8738
- filesUploaded: manifest.getAllFiles().length,
8799
+ filesUploaded: changedFiles.length,
8739
8800
  bytesTransferred: zipSize,
8740
8801
  duration
8741
8802
  };
@@ -8793,6 +8854,70 @@ var init_mdfriday_publisher = __esm({
8793
8854
  // ============================================================================
8794
8855
  // Private Methods
8795
8856
  // ============================================================================
8857
+ /**
8858
+ * Get file lists for incremental or full publish
8859
+ * Similar to FtpPublisher.getFileLists()
8860
+ *
8861
+ * @returns changedFiles - Files that are new or modified
8862
+ * @returns allFiles - All current files in sourceDir
8863
+ */
8864
+ async getFileLists(sourceDir, incremental) {
8865
+ const currentManifest = await this.manifestRepo.generateManifest(
8866
+ this.projectId,
8867
+ sourceDir,
8868
+ "mdfriday",
8869
+ { deploymentType: this.config.deploymentType }
8870
+ );
8871
+ const allFiles = currentManifest.getAllFiles();
8872
+ if (!incremental) {
8873
+ log12.debug("Full publish mode: deploying all files");
8874
+ return {
8875
+ changedFiles: allFiles,
8876
+ allFiles
8877
+ };
8878
+ }
8879
+ const lastManifest = await this.manifestRepo.loadManifest(
8880
+ this.projectPath,
8881
+ "mdfriday",
8882
+ this.config.deploymentType
8883
+ );
8884
+ if (!lastManifest) {
8885
+ log12.info("No previous manifest found, performing full deploy");
8886
+ return {
8887
+ changedFiles: allFiles,
8888
+ allFiles
8889
+ };
8890
+ }
8891
+ const changedFiles = lastManifest.getChangedFiles(currentManifest);
8892
+ log12.info(`Incremental mode: ${changedFiles.length}/${allFiles.length} files changed`);
8893
+ return {
8894
+ changedFiles,
8895
+ allFiles
8896
+ };
8897
+ }
8898
+ /**
8899
+ * Create incremental ZIP containing only specified files
8900
+ * Maintains directory structure
8901
+ */
8902
+ async createIncrementalZip(sourceDir, filesToInclude) {
8903
+ const JSZip2 = require("jszip");
8904
+ const zip = new JSZip2();
8905
+ log12.debug(`Creating incremental ZIP with ${filesToInclude.length} files`);
8906
+ for (const relativePath of filesToInclude) {
8907
+ const filePath = import_path10.default.join(sourceDir, relativePath);
8908
+ try {
8909
+ const fileContent = await import_fs7.promises.readFile(filePath);
8910
+ zip.file(relativePath, new Uint8Array(fileContent));
8911
+ } catch (error) {
8912
+ log12.error(`Failed to add file to ZIP: ${relativePath}`, error);
8913
+ throw new Error(`Failed to add file to incremental ZIP: ${relativePath}`);
8914
+ }
8915
+ }
8916
+ return await zip.generateAsync({ type: "uint8array" });
8917
+ }
8918
+ // ============================================================================
8919
+ // Private Methods
8920
+ // ============================================================================
8796
8921
  /**
8797
8922
  * Create ZIP file from directory
8798
8923
  * Similar to old Netlify implementation
@@ -9075,8 +9200,8 @@ var init_node_manifest_repository = __esm({
9075
9200
  /**
9076
9201
  * Load manifest from file
9077
9202
  */
9078
- async loadManifest(projectPath, publishMethod) {
9079
- const manifestPath = this.getManifestPath(projectPath, publishMethod);
9203
+ async loadManifest(projectPath, publishMethod, suffix) {
9204
+ const manifestPath = this.getManifestPath(projectPath, publishMethod, suffix);
9080
9205
  try {
9081
9206
  const content = await import_fs8.promises.readFile(manifestPath, "utf-8");
9082
9207
  const json = JSON.parse(content);
@@ -9093,10 +9218,14 @@ var init_node_manifest_repository = __esm({
9093
9218
  /**
9094
9219
  * Save manifest to file
9095
9220
  */
9096
- async saveManifest(projectPath, manifest) {
9221
+ async saveManifest(projectPath, manifest, suffix) {
9097
9222
  const manifestDir = import_path11.default.join(projectPath, ".mdfriday");
9098
9223
  await import_fs8.promises.mkdir(manifestDir, { recursive: true });
9099
- const manifestPath = this.getManifestPath(projectPath, manifest.getPublishMethod());
9224
+ const manifestPath = this.getManifestPath(
9225
+ projectPath,
9226
+ manifest.getPublishMethod(),
9227
+ suffix
9228
+ );
9100
9229
  await import_fs8.promises.writeFile(
9101
9230
  manifestPath,
9102
9231
  JSON.stringify(manifest.toJSON(), null, 2),
@@ -9123,8 +9252,8 @@ var init_node_manifest_repository = __esm({
9123
9252
  /**
9124
9253
  * Delete manifest file
9125
9254
  */
9126
- async deleteManifest(projectPath, publishMethod) {
9127
- const manifestPath = this.getManifestPath(projectPath, publishMethod);
9255
+ async deleteManifest(projectPath, publishMethod, suffix) {
9256
+ const manifestPath = this.getManifestPath(projectPath, publishMethod, suffix);
9128
9257
  try {
9129
9258
  await import_fs8.promises.unlink(manifestPath);
9130
9259
  log14.debug(`Manifest deleted: ${manifestPath}`);
@@ -9141,9 +9270,15 @@ var init_node_manifest_repository = __esm({
9141
9270
  // ============================================================================
9142
9271
  /**
9143
9272
  * Get manifest file path
9273
+ *
9274
+ * @param projectPath
9275
+ * @param publishMethod
9276
+ * @param suffix - Optional suffix for manifest filename (e.g., 'free', 'custom')
9277
+ * For mdfriday with different deploymentTypes
9144
9278
  */
9145
- getManifestPath(projectPath, publishMethod) {
9146
- return import_path11.default.join(projectPath, ".mdfriday", `manifest-${publishMethod}.json`);
9279
+ getManifestPath(projectPath, publishMethod, suffix) {
9280
+ const filename = suffix ? `manifest-${publishMethod}-${suffix}.json` : `manifest-${publishMethod}.json`;
9281
+ return import_path11.default.join(projectPath, ".mdfriday", filename);
9147
9282
  }
9148
9283
  /**
9149
9284
  * Recursively scan directory and collect file info
@@ -55225,7 +55360,7 @@ For more information, visit: https://help.mdfriday.com
55225
55360
  * Show version
55226
55361
  */
55227
55362
  showVersion() {
55228
- const version = "26.4.4";
55363
+ const version = "26.4.6";
55229
55364
  return {
55230
55365
  success: true,
55231
55366
  message: `MDFriday CLI v${version}`