scan.ts 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. import fs from 'node:fs';
  2. import path from 'node:path';
  3. import type { GrowiTemplatePluginValidationData } from '../../../../model';
  4. import {
  5. isTemplateStatusValid,
  6. type TemplateStatus,
  7. type TemplateSummary,
  8. } from '../../../interfaces';
  9. import { getStatus } from './get-status';
  10. import { validateTemplatePluginGrowiDirective } from './validate-growi-plugin-directive';
  11. export const scanTemplate = async (
  12. projectDirRoot: string,
  13. templateId: string,
  14. data: GrowiTemplatePluginValidationData,
  15. opts?: {
  16. pluginId?: string;
  17. },
  18. ): Promise<TemplateStatus[]> => {
  19. const status: TemplateStatus[] = [];
  20. const tplRootDirPath = path.resolve(projectDirRoot, 'dist', templateId);
  21. let isDefaultPushed = false;
  22. for await (const locale of data.supportingLocales) {
  23. const tplDir = path.resolve(tplRootDirPath, locale);
  24. try {
  25. const stats = await getStatus(tplDir);
  26. const { isTemplateExists, meta } = stats;
  27. if (!isTemplateExists) throw new Error("'template.md does not exist.");
  28. if (meta == null) throw new Error("'meta.md does not exist.");
  29. if (meta?.title == null)
  30. throw new Error("'meta.md does not contain the title.");
  31. const isDefault = !isDefaultPushed;
  32. status.push({
  33. pluginId: opts?.pluginId,
  34. id: templateId,
  35. locale,
  36. isValid: true,
  37. isDefault,
  38. title: meta.title,
  39. desc: meta.desc,
  40. });
  41. isDefaultPushed = true;
  42. } catch (err) {
  43. status.push({
  44. pluginId: opts?.pluginId,
  45. id: templateId,
  46. locale,
  47. isValid: false,
  48. invalidReason: (err as Error).message,
  49. });
  50. }
  51. }
  52. // eslint-disable-next-line no-console
  53. console.debug(`Template directory (${projectDirRoot}) has scanned`, {
  54. status,
  55. });
  56. return status;
  57. };
  58. export const scanAllTemplates = async (
  59. projectDirRoot: string,
  60. opts?: {
  61. data?: GrowiTemplatePluginValidationData;
  62. pluginId?: string;
  63. returnsInvalidTemplates?: boolean;
  64. },
  65. ): Promise<TemplateSummary[]> => {
  66. const data =
  67. opts?.data ?? validateTemplatePluginGrowiDirective(projectDirRoot);
  68. const summaries: TemplateSummary[] = [];
  69. const distDirPath = path.resolve(projectDirRoot, 'dist');
  70. const distDirFiles = fs.readdirSync(distDirPath);
  71. for await (const templateId of distDirFiles) {
  72. const status = (
  73. await scanTemplate(projectDirRoot, templateId, data, {
  74. pluginId: opts?.pluginId,
  75. })
  76. )
  77. // omit invalid templates if `returnsInvalidTemplates` is true
  78. .filter((s) => (opts?.returnsInvalidTemplates ? true : s.isValid));
  79. // determine default locale
  80. const defaultTemplateStatus = status.find(
  81. (s) => 'isDefault' in s && s.isDefault,
  82. );
  83. if (
  84. defaultTemplateStatus == null ||
  85. !isTemplateStatusValid(defaultTemplateStatus)
  86. ) {
  87. continue;
  88. }
  89. summaries.push({
  90. // for the 'default' key
  91. default: defaultTemplateStatus,
  92. // for each locale keys
  93. ...Object.fromEntries(
  94. status.map((templateStatus) => [templateStatus.locale, templateStatus]),
  95. ),
  96. });
  97. }
  98. return summaries;
  99. };