aboutsummaryrefslogtreecommitdiffstats
path: root/utils/loader.ts
blob: 56e29fadf55651710ec6e12e61e9813fa34551ae (plain)
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
import { parse } from "yaml";
import { loadCategoriesFromJson, loadItemsFromJson, loadQuestsFromJson } from "~/lib/questsLoader";

export async function openFileSystem() {
  try {
    return await (window as any).showDirectoryPicker();
  } catch (e) {
    return undefined;
  }
}

export async function enumerateQuestDirectory(dirHandle: any) {
  let configFile: any = null;
  let categoryFile: any = null;
  let questsDirectory: any = null;
  let itemsDirectory: any = null;

  for await (const [name, handle] of dirHandle) {
    if (name === 'quests' && handle.kind === 'directory') {
      questsDirectory = handle;
    } else if (name === 'items' && handle.kind === 'directory') {
      itemsDirectory = handle;
    } else if (name === 'config.yml' && handle.kind === 'file') {
      configFile = handle;
    } else if (name === 'categories.yml' && handle.kind === 'file') {
      categoryFile = handle;
    }
  }

  if (!configFile) {
    throw Error('invalid quest directory');
  }

  const [questFiles, itemFiles] = await Promise.all([questsDirectory ? listAllFilesAndDirs(questsDirectory) : [], itemsDirectory ? listAllFilesAndDirs(itemsDirectory) : []]);
  const [categories, quests, items] = await Promise.all([(async () => {
    if (!categoryFile) {
      return [];
    }

    const file: any = await categoryFile.getFile();
    const text: string = await file.text();
    const parsedYaml: any = parse(text);

    return loadCategoriesFromJson(parsedYaml.categories);
  })(),
  (async () => {
    if (!questFiles) {
      return [];
    }

    const allQuests = await Promise.all(questFiles.filter(({ name, handle, kind }) => name.endsWith('.yml')).map(async ({ name, handle, kind }) => {
      const file: any = await handle.getFile();
      const text: string = await file.text();
      return [
        name.replace('.yml', ''),
        parse(text)
      ];
    }))

    return loadQuestsFromJson(Object.fromEntries(allQuests));
  })(),
  (async () => {
    if (!itemFiles) {
      return [];
    }

    const allItems = await Promise.all(itemFiles.filter(({ name, handle, kind }) => name.endsWith('.yml')).map(async ({ name, handle, kind }) => {
      const file: any = await handle.getFile();
      const text: string = await file.text();
      return [
        name.replace('.yml', ''),
        parse(text)
      ];
    }))

    return loadItemsFromJson(Object.fromEntries(allItems));
  })()]);

  return { categories, quests, items };
}

async function listAllFilesAndDirs(dirHandle: any): Promise<any[]> {
  const files = [];
  for await (const [name, handle] of dirHandle) {
    const { kind } = handle;
    if (handle.kind === 'directory') {
      files.push(...await listAllFilesAndDirs(handle));
    } else {
      files.push({ name, handle, kind });
    }
  }
  return files;
}