@terrafirmagreg-team/recipe 0.1.0 → 1.2.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.
Files changed (240) hide show
  1. package/package.json +16 -16
  2. package/src/components/button-copy.tsx +1 -0
  3. package/src/components/cards/card/index.tsx +5 -3
  4. package/src/components/cards/card/scene.tsx +4 -2
  5. package/src/components/cards/card/strip.tsx +4 -2
  6. package/src/components/cards/card/text.tsx +2 -1
  7. package/src/components/cards/card/tips.tsx +1 -0
  8. package/src/components/cards/default-item.tsx +6 -2
  9. package/src/components/cards/glare-filter.tsx +1 -0
  10. package/src/components/cards/paged-card.tsx +1 -0
  11. package/src/components/cards/slot-hitbox.tsx +4 -2
  12. package/src/components/cards/strip-card/buttons.tsx +7 -2
  13. package/src/components/cards/strip-card/index.tsx +3 -1
  14. package/src/components/cards/strip-card/member-cell.tsx +4 -2
  15. package/src/components/cards/strip-card/sprite.tsx +1 -0
  16. package/src/components/embed-card.tsx +44 -0
  17. package/src/components/mdx/recipe.tsx +34 -16
  18. package/src/components/tool-list.tsx +1 -0
  19. package/src/{lib/tree.ts → components/tree.tsx} +20 -12
  20. package/src/components/views/alloy/index.tsx +14 -7
  21. package/src/components/views/alloy/list.tsx +3 -2
  22. package/src/components/views/alloy/mix/index.tsx +1 -0
  23. package/src/components/views/alloy/mix/ratio.tsx +7 -6
  24. package/src/components/views/alloy/mix/rows.tsx +6 -7
  25. package/src/components/views/alloy/mix/status.tsx +8 -7
  26. package/src/components/views/alloy/mix/total.tsx +13 -12
  27. package/src/components/views/alloy/range-bar.tsx +2 -1
  28. package/src/components/views/alloy/stack-bar.tsx +4 -2
  29. package/src/components/views/browser/axis-switcher.tsx +13 -12
  30. package/src/components/views/browser/card-grid.tsx +2 -1
  31. package/src/components/views/browser/favorite-button.tsx +2 -1
  32. package/src/components/views/browser/frame.tsx +3 -2
  33. package/src/components/views/browser/index.tsx +20 -2
  34. package/src/components/views/browser/item-panel/index.tsx +11 -9
  35. package/src/components/views/browser/item-panel/skeleton.tsx +1 -0
  36. package/src/components/views/browser/item-panel-grid/cell.tsx +5 -3
  37. package/src/components/views/browser/item-panel-grid/favorite-cell.tsx +4 -2
  38. package/src/components/views/browser/item-panel-grid/index.tsx +4 -2
  39. package/src/components/views/browser/item-view/index.tsx +7 -12
  40. package/src/components/views/browser/item-view/tags.tsx +7 -5
  41. package/src/components/views/browser/item-view-header.tsx +10 -9
  42. package/src/components/views/browser/pane-tabs.tsx +1 -0
  43. package/src/components/views/browser/place-header.tsx +4 -3
  44. package/src/components/views/browser/query-controls.tsx +3 -1
  45. package/src/components/views/browser/recipe-item-header.tsx +5 -4
  46. package/src/components/views/browser/settings.tsx +4 -3
  47. package/src/components/views/browser/toolbar.tsx +3 -2
  48. package/src/components/views/browser/type-tabs.tsx +5 -3
  49. package/src/components/views/browser/type-view.tsx +7 -12
  50. package/src/components/views/browser/workstation-rail.tsx +4 -3
  51. package/src/components/views/calc/calculator/actions.tsx +4 -14
  52. package/src/components/views/calc/calculator/help.tsx +69 -28
  53. package/src/components/views/calc/calculator/index.tsx +34 -82
  54. package/src/components/views/calc/dot-overlay.tsx +1 -0
  55. package/src/components/views/calc/edge.tsx +134 -32
  56. package/src/components/views/calc/flow/index.tsx +92 -54
  57. package/src/components/views/calc/flow/picker-dialogs.tsx +84 -6
  58. package/src/components/views/calc/flow/toolbar.tsx +9 -21
  59. package/src/components/views/calc/flow/view-menu.tsx +16 -120
  60. package/src/components/views/calc/member-picker.tsx +8 -6
  61. package/src/components/views/calc/node-card/actions.tsx +28 -106
  62. package/src/components/views/calc/node-card/badges.tsx +10 -28
  63. package/src/components/views/calc/node-card/chips.tsx +8 -40
  64. package/src/components/views/calc/node-card/far.tsx +13 -65
  65. package/src/components/views/calc/node-card/full.tsx +133 -83
  66. package/src/components/views/calc/node-card/index.tsx +1 -0
  67. package/src/components/views/calc/node-card/menu.tsx +93 -22
  68. package/src/components/views/calc/node-card/port-cells.tsx +186 -0
  69. package/src/components/views/calc/node-card/port-rails.tsx +251 -0
  70. package/src/components/views/calc/node-card/ports.tsx +86 -0
  71. package/src/components/views/calc/recipe-picker/body.tsx +17 -14
  72. package/src/components/views/calc/recipe-picker/footer.tsx +5 -3
  73. package/src/components/views/calc/recipe-picker/index.tsx +5 -0
  74. package/src/components/views/calc/sidebar.tsx +19 -10
  75. package/src/components/views/calc/trees/icon-picker.tsx +3 -2
  76. package/src/components/views/calc/trees/index.tsx +5 -4
  77. package/src/components/views/calc/trees/label.tsx +6 -4
  78. package/src/components/views/calc/trees/rows.tsx +6 -5
  79. package/src/components/views/forge/gui.tsx +2 -1
  80. package/src/components/views/forge/index.tsx +14 -7
  81. package/src/components/views/forge/list.tsx +3 -2
  82. package/src/components/views/forge/workbench/controls.tsx +13 -6
  83. package/src/components/views/forge/workbench/index.tsx +3 -2
  84. package/src/components/views/forge/workbench/panel.tsx +1 -0
  85. package/src/components/views/forge/workbench/ruler.tsx +5 -4
  86. package/src/components/views/forge/workbench/status.tsx +6 -5
  87. package/src/components/views/forge/workbench/tape.tsx +5 -4
  88. package/src/hooks/alloy/use-fluid-colors.ts +12 -9
  89. package/src/hooks/alloy/use-mix-state.ts +3 -2
  90. package/src/hooks/calc/flow/use-engage.ts +129 -0
  91. package/src/hooks/calc/flow/use-handlers.ts +192 -0
  92. package/src/hooks/calc/flow/use-layout.ts +105 -0
  93. package/src/hooks/calc/flow/{mount.ts → use-mount.ts} +1 -0
  94. package/src/hooks/calc/flow/{nodes.ts → use-nodes.ts} +46 -37
  95. package/src/hooks/calc/flow/use-pickers.ts +57 -0
  96. package/src/hooks/calc/flow/{viewport.ts → use-viewport.ts} +13 -26
  97. package/src/hooks/calc/flow/{window.ts → use-window.ts} +1 -0
  98. package/src/hooks/calc/use-actions.ts +208 -229
  99. package/src/hooks/calc/use-amounts.ts +23 -60
  100. package/src/hooks/calc/use-data.ts +106 -192
  101. package/src/hooks/calc/use-defaults.ts +4 -2
  102. package/src/hooks/calc/use-far-mode.ts +1 -0
  103. package/src/hooks/calc/use-focus.ts +8 -7
  104. package/src/hooks/calc/use-maps.ts +1 -0
  105. package/src/hooks/calc/use-reset.ts +1 -0
  106. package/src/hooks/calc/use-resolver.ts +32 -196
  107. package/src/hooks/calc/use-session.ts +1 -0
  108. package/src/hooks/calc/use-share.ts +5 -2
  109. package/src/hooks/calc/use-storage.ts +5 -4
  110. package/src/hooks/calc/use-tier.ts +1 -0
  111. package/src/hooks/calc/use-view-mode.ts +1 -0
  112. package/src/hooks/calc/use-worker.ts +56 -121
  113. package/src/hooks/forge/use-anvil-gui.ts +4 -2
  114. package/src/hooks/forge/use-forge-state.ts +1 -0
  115. package/src/hooks/forge/use-ruler.ts +1 -0
  116. package/src/hooks/use-add-to-calc.ts +23 -19
  117. package/src/hooks/use-categories-by-id.ts +18 -0
  118. package/src/hooks/use-favorite-hotkey.ts +1 -0
  119. package/src/hooks/use-favorites.ts +1 -0
  120. package/src/hooks/use-group-outlines.ts +1 -0
  121. package/src/hooks/use-hide-unused.ts +2 -1
  122. package/src/hooks/use-index.ts +6 -2
  123. package/src/hooks/use-item-feeds.ts +3 -1
  124. package/src/hooks/use-item-pane.ts +6 -4
  125. package/src/hooks/use-item-press.ts +27 -23
  126. package/src/hooks/use-item-tag-groups.ts +4 -2
  127. package/src/hooks/use-item-tooltips.ts +3 -1
  128. package/src/hooks/use-left-sidebar-tree.ts +11 -3
  129. package/src/hooks/use-mod-names.ts +4 -2
  130. package/src/hooks/use-mount-limit.ts +1 -0
  131. package/src/hooks/use-panel-cells.ts +3 -1
  132. package/src/hooks/use-panel-page.ts +9 -6
  133. package/src/hooks/use-panel-tabs.ts +2 -1
  134. package/src/hooks/use-query.ts +8 -6
  135. package/src/hooks/use-session.ts +6 -2
  136. package/src/hooks/use-sidebar-group.ts +3 -7
  137. package/src/hooks/use-tag-members.ts +3 -1
  138. package/src/hooks/use-tool-recipes.ts +1 -0
  139. package/src/hooks/use-type-filter.ts +1 -0
  140. package/src/lib/alloy/mix.ts +1 -0
  141. package/src/lib/alloy/parse.ts +1 -0
  142. package/src/lib/calc/defaults.ts +6 -4
  143. package/src/lib/calc/flow.ts +143 -107
  144. package/src/lib/calc/focus.ts +1 -0
  145. package/src/lib/calc/meta.ts +3 -1
  146. package/src/lib/calc/pack.ts +47 -154
  147. package/src/lib/calc/ports.ts +43 -0
  148. package/src/lib/calc/resolve.ts +6 -38
  149. package/src/lib/calc/route/buckets.ts +1 -0
  150. package/src/lib/calc/route/geometry.ts +13 -24
  151. package/src/lib/calc/route/index.ts +1 -0
  152. package/src/lib/calc/route/polyline.ts +3 -3
  153. package/src/lib/calc/route/router.ts +181 -57
  154. package/src/lib/calc/scheme.ts +226 -0
  155. package/src/lib/calc/storage/entry.ts +27 -19
  156. package/src/lib/calc/storage/index.ts +2 -0
  157. package/src/lib/calc/storage/keys.ts +4 -8
  158. package/src/lib/calc/storage/store.ts +11 -36
  159. package/src/lib/calc/tree/index.ts +2 -16
  160. package/src/lib/calc/tree/materials.ts +1 -0
  161. package/src/lib/calc/tree/recipe.ts +1 -0
  162. package/src/lib/calc/tree/share.ts +86 -149
  163. package/src/lib/calc/worker/api.ts +3 -11
  164. package/src/lib/calc/worker/fetch.ts +1 -0
  165. package/src/lib/calc/worker/flush.ts +7 -20
  166. package/src/lib/calc/worker/index.ts +1 -1
  167. package/src/lib/calc/worker/protocol.ts +16 -13
  168. package/src/lib/calc/worker/resolve.ts +32 -84
  169. package/src/lib/calc/worker/state.ts +5 -6
  170. package/src/{components/cards/card/model.ts → lib/card-model.ts} +1 -0
  171. package/src/lib/client/recipe-categories.ts +11 -93
  172. package/src/lib/client/recipe.ts +13 -11
  173. package/src/lib/client-index/catalog.ts +33 -27
  174. package/src/lib/client-index/chrome.ts +30 -30
  175. package/src/lib/client-index/index.ts +1 -0
  176. package/src/lib/client-index/registry.ts +70 -59
  177. package/src/lib/client-index/rows.ts +63 -57
  178. package/src/lib/client-index/tooltips.ts +28 -34
  179. package/src/lib/config.ts +2 -1
  180. package/src/lib/data/category/dto.ts +4 -3
  181. package/src/lib/data/category/load.ts +9 -8
  182. package/src/lib/data/category/parse.ts +4 -3
  183. package/src/lib/data/dto.ts +4 -3
  184. package/src/lib/data/grid.ts +2 -1
  185. package/src/lib/data/parse/entry.ts +3 -2
  186. package/src/lib/data/parse/index.ts +1 -0
  187. package/src/lib/data/parse/layout.ts +5 -2
  188. package/src/lib/data/parse/slots.ts +3 -2
  189. package/src/lib/data/parse/widgets.ts +3 -2
  190. package/src/lib/data/scene.ts +1 -1
  191. package/src/lib/data/slot-io.ts +1 -0
  192. package/src/lib/dump.ts +4 -3
  193. package/src/lib/embed.ts +22 -0
  194. package/src/lib/favorite-hover.ts +1 -0
  195. package/src/lib/fluid-outputs.ts +10 -12
  196. package/src/lib/forge/actions.ts +2 -1
  197. package/src/lib/forge/data.ts +2 -1
  198. package/src/lib/forge/solve.ts +1 -0
  199. package/src/lib/group.ts +1 -0
  200. package/src/lib/index-store.ts +15 -9
  201. package/src/lib/links.ts +15 -9
  202. package/src/lib/lookup.ts +10 -8
  203. package/src/lib/panel-outline.ts +1 -0
  204. package/src/lib/panel.ts +3 -2
  205. package/src/lib/preview.ts +12 -8
  206. package/src/lib/recipe-slots.ts +1 -0
  207. package/src/lib/search.ts +1 -0
  208. package/src/lib/sidebar.ts +1 -0
  209. package/src/lib/used-items.ts +1 -0
  210. package/src/locales/en_us.json +170 -226
  211. package/src/locales/ru_ru.json +170 -226
  212. package/src/locales.ts +1 -0
  213. package/src/types/alloy.ts +1 -0
  214. package/src/{hooks/calc/flow/props.ts → types/calc-flow-props.ts} +18 -14
  215. package/src/types/calc.ts +41 -44
  216. package/src/types/forge.ts +1 -0
  217. package/src/types/index.ts +4 -2
  218. package/styles/calc.css +308 -47
  219. package/src/components/cards/fit-card.tsx +0 -26
  220. package/src/components/views/calc/target.tsx +0 -271
  221. package/src/hooks/calc/flow/engage.ts +0 -89
  222. package/src/hooks/calc/flow/handlers.ts +0 -115
  223. package/src/hooks/calc/flow/layout.ts +0 -149
  224. package/src/hooks/calc/flow/pickers.ts +0 -50
  225. package/src/hooks/calc/use-calc-fill.ts +0 -91
  226. package/src/hooks/calc/use-density.ts +0 -28
  227. package/src/hooks/calc/use-derived.ts +0 -258
  228. package/src/hooks/calc/use-direction.ts +0 -23
  229. package/src/hooks/calc/use-edge-style.ts +0 -40
  230. package/src/hooks/calc/use-fill.ts +0 -213
  231. package/src/lib/alloy/alloy.test.ts +0 -186
  232. package/src/lib/calc/tree/build.ts +0 -196
  233. package/src/lib/calc/tree/context.ts +0 -42
  234. package/src/lib/calc/tree/goal.ts +0 -64
  235. package/src/lib/calc/tree/ideal.ts +0 -36
  236. package/src/lib/calc/tree/pick.ts +0 -68
  237. package/src/lib/calc/tree/tree.test.ts +0 -169
  238. package/src/lib/calc/worker/fill.ts +0 -123
  239. package/src/lib/client-index/cache.ts +0 -13
  240. package/src/lib/forge/forge.test.ts +0 -123
@@ -1,96 +1,14 @@
1
- import { asRecord } from '@terrafirmagreg-team/game/lib/dump/contract/read';
2
- import { asCategory } from '@terrafirmagreg-team/recipe/lib/data/category/parse';
3
- import type {
4
- DumpRecipeCategory,
5
- DumpRecipeLayout,
6
- } from '@terrafirmagreg-team/recipe/lib/data/category/dto';
7
- import type { RecipeTypeRow } from '@terrafirmagreg-team/game/lib/dump/gen';
8
- import {
9
- clientDumpJson,
10
- loadClientManifest,
11
- } from '@terrafirmagreg-team/game/lib/dump/client/dump';
12
- import { createAsyncCache } from '@terrafirmagreg-team/ui/lib/utils/async-cache';
13
-
14
- const clientCategoryFile = createAsyncCache(
15
- async (dataset: string, ns: string) => {
16
- const manifest = await loadClientManifest(dataset);
17
- const listed = manifest?.namespaces[ns];
18
- if (!listed || !listed.registry.includes('recipe_categories')) {
19
- return undefined;
20
- }
21
- return asRecord(
22
- await clientDumpJson(
23
- dataset,
24
- 'registry/recipe_categories.json',
25
- 'high',
26
- ),
27
- );
28
- },
29
- );
30
-
31
- function categoryFromRaw(
32
- catalogKey: string,
33
- raw: unknown,
34
- ): DumpRecipeCategory | undefined {
35
- return asCategory(
36
- raw && typeof raw === 'object' && !Array.isArray(raw) && !('id' in raw)
37
- ? { ...raw, id: catalogKey }
38
- : raw,
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
+ import { loadDatasetRecipeCategories } from '@terrafirmagreg-team/recipe/lib/data/category/load';
3
+ import type { DumpRecipeLayout } from '@terrafirmagreg-team/recipe/lib/data/category/dto';
4
+
5
+ export function clientRecipeLayout(
6
+ dataset: DatasetRef,
7
+ categoryId: string,
8
+ ): Promise<DumpRecipeLayout | undefined> {
9
+ return loadDatasetRecipeCategories(dataset).then(
10
+ (categories) =>
11
+ categories.find((cat) => cat.id === categoryId)?.layout,
39
12
  );
40
13
  }
41
14
 
42
- export const clientRecipeLayout = createAsyncCache(
43
- async (
44
- dataset: string,
45
- categoryId: string,
46
- ): Promise<DumpRecipeLayout | undefined> => {
47
- const ns = categoryId.split(':', 1)[0];
48
- if (!ns) return undefined;
49
- const entries = await clientCategoryFile(dataset, ns);
50
- return categoryFromRaw(categoryId, entries?.[categoryId])?.layout;
51
- },
52
- );
53
-
54
- function recipeNamespaces(types: RecipeTypeRow[] | undefined): string[] {
55
- const out = new Set<string>();
56
- for (const row of types ?? []) {
57
- const ns = row.id.split(':', 1)[0];
58
- if (ns) out.add(ns);
59
- for (const fileNs of Object.keys(row.files ?? {})) {
60
- if (fileNs) out.add(fileNs);
61
- }
62
- }
63
- return [...out];
64
- }
65
-
66
- export const loadClientRecipeCategories = createAsyncCache(
67
- async (dataset: string): Promise<DumpRecipeCategory[]> => {
68
- const merged = asRecord(
69
- await clientDumpJson(dataset, 'registry/recipe_categories.json'),
70
- );
71
- if (merged) {
72
- const out: DumpRecipeCategory[] = [];
73
- for (const [catalogKey, raw] of Object.entries(merged)) {
74
- const cat = categoryFromRaw(catalogKey, raw);
75
- if (cat) out.push(cat);
76
- }
77
- out.sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
78
- return out;
79
- }
80
- const manifest = await loadClientManifest(dataset);
81
- const namespaces = recipeNamespaces(manifest?.indexes.recipes.types);
82
- const out: DumpRecipeCategory[] = [];
83
- await Promise.all(
84
- namespaces.map(async (ns) => {
85
- const entries = await clientCategoryFile(dataset, ns);
86
- if (!entries) return;
87
- for (const [catalogKey, raw] of Object.entries(entries)) {
88
- const cat = categoryFromRaw(catalogKey, raw);
89
- if (cat) out.push(cat);
90
- }
91
- }),
92
- );
93
- out.sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
94
- return out;
95
- },
96
- );
@@ -1,15 +1,16 @@
1
- import { asRecord, asString } from '@terrafirmagreg-team/game/lib/dump/contract/read';
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
+ import { asRecord, asString } from '@terrafirmagreg-team/dump/lib/dump/contract/read';
2
3
  import { parseRecipe } from '@terrafirmagreg-team/recipe/lib/data/parse';
3
4
  import type { Recipe } from '@terrafirmagreg-team/recipe/lib/data/dto';
4
- import { dumpRelPublicUrl } from '@terrafirmagreg-team/game/lib/dump/paths';
5
+ import { dumpRelPublicUrl } from '@terrafirmagreg-team/dump/lib/dump/paths';
5
6
  import {
6
7
  clientDumpJson,
7
8
  loadClientManifest,
8
- } from '@terrafirmagreg-team/game/lib/dump/client/dump';
9
+ } from '@terrafirmagreg-team/dump/lib/dump/client/dump';
9
10
  import { clientRecipeLayout } from '@terrafirmagreg-team/recipe/lib/client/recipe-categories';
10
- import { createAsyncCache } from '@terrafirmagreg-team/ui/lib/utils/async-cache';
11
+ import { createDatasetCache } from '@terrafirmagreg-team/dump/lib/dump/reader';
11
12
 
12
- const recipeIndex = createAsyncCache(async (dataset: string, ns: string) => {
13
+ const recipeIndex = createDatasetCache(async (dataset: DatasetRef, ns: string) => {
13
14
  const manifest = await loadClientManifest(dataset);
14
15
  const listed = manifest?.namespaces[ns];
15
16
  if (!listed || !listed.registry.includes('recipes')) return undefined;
@@ -19,7 +20,7 @@ const recipeIndex = createAsyncCache(async (dataset: string, ns: string) => {
19
20
  });
20
21
 
21
22
  export async function clientRecipeFileRels(
22
- dataset: string,
23
+ dataset: DatasetRef,
23
24
  recipeId: string,
24
25
  ): Promise<string[]> {
25
26
  const ns = recipeId.split(':', 1)[0];
@@ -46,19 +47,19 @@ export async function clientRecipeFileRels(
46
47
  }
47
48
 
48
49
  async function clientRecipeFileRel(
49
- dataset: string,
50
+ dataset: DatasetRef,
50
51
  recipeId: string,
51
52
  ): Promise<string | undefined> {
52
53
  return (await clientRecipeFileRels(dataset, recipeId))[0];
53
54
  }
54
55
 
55
56
  export const loadClientRecipe: (
56
- dataset: string,
57
+ dataset: DatasetRef,
57
58
  id: string,
58
59
  bucket?: string,
59
- ) => Promise<Recipe | undefined> = createAsyncCache(
60
+ ) => Promise<Recipe | undefined> = createDatasetCache(
60
61
  async (
61
- dataset: string,
62
+ dataset: DatasetRef,
62
63
  id: string,
63
64
  bucket?: string,
64
65
  ): Promise<Recipe | undefined> => {
@@ -74,10 +75,11 @@ export const loadClientRecipe: (
74
75
  : undefined;
75
76
  return parseRecipe(raw, {
76
77
  modId: ns,
77
- bodyUrl: dumpRelPublicUrl(dataset, rel) ?? `/${dataset}`,
78
+ bodyUrl: dumpRelPublicUrl(dataset, rel) ?? `/${dataset.id}`,
78
79
  id,
79
80
  ...(layout ? { layout } : {}),
80
81
  });
81
82
  },
82
83
  (dataset, id, bucket) => JSON.stringify([dataset, id, bucket ?? '']),
83
84
  );
85
+
@@ -1,12 +1,10 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import type { RecipeChrome, RecipeCompactIndex } from '@terrafirmagreg-team/recipe/types';
2
- import { loadClientRecipeCategories } from '@terrafirmagreg-team/recipe/lib/client/recipe-categories';
3
+ import { loadDatasetRecipeCategories } from '@terrafirmagreg-team/recipe/lib/data/category/load';
3
4
  import { stackDisplayName } from '@terrafirmagreg-team/game/lib/entry/display';
4
- import { memoPending } from './cache';
5
+ import { createDatasetCache } from '@terrafirmagreg-team/dump/lib/dump/reader';
5
6
  import { recipeTypeRows } from './rows';
6
7
 
7
- const indexCache = new Map<string, RecipeCompactIndex>();
8
- const skeletonCache = new Map<string, Promise<RecipeCompactIndex>>();
9
-
10
8
  const emptyRecipeIndex = (): RecipeCompactIndex => ({
11
9
  types: [],
12
10
  items: [],
@@ -14,7 +12,7 @@ const emptyRecipeIndex = (): RecipeCompactIndex => ({
14
12
  });
15
13
 
16
14
  async function loadRecipeStructureFromDump(
17
- dataset: string,
15
+ dataset: DatasetRef,
18
16
  chrome: RecipeChrome,
19
17
  ): Promise<RecipeCompactIndex> {
20
18
  const rows = await recipeTypeRows(dataset);
@@ -37,33 +35,40 @@ async function loadRecipeStructureFromDump(
37
35
  };
38
36
  }
39
37
 
40
- export async function loadRecipeCompactIndex(
41
- dataset: string,
38
+ const indexCache = createDatasetCache(
39
+ async (
40
+ dataset: DatasetRef,
41
+ chrome?: RecipeChrome,
42
+ ): Promise<RecipeCompactIndex> => {
43
+ if (!chrome) return emptyRecipeIndex();
44
+ return loadRecipeStructureFromDump(dataset, chrome);
45
+ },
46
+ (dataset, chrome) =>
47
+ `${dataset.id}/${dataset.version ?? ''} ${chrome ? (Object.keys(chrome.names)[0] ?? '') : ''}`,
48
+ );
49
+
50
+ const skeletonCache = createDatasetCache(
51
+ async (dataset: DatasetRef): Promise<RecipeCompactIndex> =>
52
+ loadDatasetRecipeCategories(dataset).then((categories) =>
53
+ loadRecipeStructureFromDump(dataset, {
54
+ items: [],
55
+ names: {},
56
+ ...(categories.length ? { categories } : {}),
57
+ }),
58
+ ),
59
+ );
60
+
61
+ export function loadRecipeCompactIndex(
62
+ dataset: DatasetRef,
42
63
  chrome?: RecipeChrome,
43
64
  ): Promise<RecipeCompactIndex> {
44
- const lang = chrome ? (Object.keys(chrome.names)[0] ?? '') : '';
45
- const cacheKey = `${dataset} ${lang}`;
46
- const cached = indexCache.get(cacheKey);
47
- if (cached) return cached;
48
- if (!chrome) return emptyRecipeIndex();
49
- const index = await loadRecipeStructureFromDump(dataset, chrome);
50
- indexCache.set(cacheKey, index);
51
- return index;
65
+ return indexCache(dataset, chrome);
52
66
  }
53
67
 
54
68
  export function loadRecipeSkeletonIndex(
55
- dataset: string,
69
+ dataset: DatasetRef,
56
70
  ): Promise<RecipeCompactIndex> {
57
- const cached = skeletonCache.get(dataset);
58
- if (cached) return cached;
59
- const pending = loadClientRecipeCategories(dataset).then((categories) =>
60
- loadRecipeStructureFromDump(dataset, {
61
- items: [],
62
- names: {},
63
- ...(categories.length ? { categories } : {}),
64
- }),
65
- );
66
- return memoPending(skeletonCache, dataset, pending);
71
+ return skeletonCache(dataset);
67
72
  }
68
73
 
69
74
  export function nonEmptyCategoryIds(
@@ -83,3 +88,4 @@ export function recipeItemName(
83
88
  ): string {
84
89
  return stackDisplayName(names[lang] ?? names.en_us, id);
85
90
  }
91
+
@@ -1,34 +1,33 @@
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
1
2
  import type {
2
3
  RecipeCategory,
3
4
  RecipeChrome,
4
5
  RecipeStackGroup,
5
6
  } from '@terrafirmagreg-team/recipe/types';
6
- import { clientDumpLang, loadClientManifest } from '@terrafirmagreg-team/game/lib/dump/client/dump';
7
+ import { clientDumpLang, loadClientManifest } from '@terrafirmagreg-team/dump/lib/dump/client/dump';
7
8
  import {
8
9
  creativeTabName,
9
10
  dumpTextString,
10
- } from '@terrafirmagreg-team/game/lib/dump/assets/lang/names';
11
+ } from '@terrafirmagreg-team/dump/lib/dump/assets/lang/names';
11
12
  import { stackDisplayName } from '@terrafirmagreg-team/game/lib/entry/display';
12
13
  import {
13
14
  loadClientRegistry,
14
15
  loadClientRegistryOrder,
15
16
  resolveClientStackDisplay,
16
- } from '@terrafirmagreg-team/game/lib/dump/client/registry';
17
- import { loadClientTagMembers } from '@terrafirmagreg-team/game/lib/dump/client/tags';
18
- import { loadClientTabs } from '@terrafirmagreg-team/game/lib/dump/client/tabs';
19
- import { loadClientRecipeCategories } from '@terrafirmagreg-team/recipe/lib/client/recipe-categories';
20
- import { loadClientRegistryGroups } from '@terrafirmagreg-team/game/lib/dump/client/groups';
21
- import { loadClientModNames } from '@terrafirmagreg-team/game/lib/dump/client/mods';
22
- import { loadClientModAtlases } from '@terrafirmagreg-team/game/lib/dump/client/atlases';
23
- import { lookupSpriteInBundle } from '@terrafirmagreg-team/game/lib/dump/assets/atlas/lookup';
24
- import { stackIdBase, stackIdFromRef } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
25
- import type { AtlasBundle } from '@terrafirmagreg-team/game/lib/dump/assets/atlas/dto';
26
- import { memoPending } from './cache';
27
-
28
- const chromeCache = new Map<string, Promise<RecipeChrome>>();
17
+ } from '@terrafirmagreg-team/dump/lib/dump/client/registry';
18
+ import { loadClientTagMembers } from '@terrafirmagreg-team/dump/lib/dump/client/tags';
19
+ import { loadClientTabs } from '@terrafirmagreg-team/dump/lib/dump/client/tabs';
20
+ import { loadDatasetRecipeCategories } from '@terrafirmagreg-team/recipe/lib/data/category/load';
21
+ import { loadClientRegistryGroups } from '@terrafirmagreg-team/dump/lib/dump/client/groups';
22
+ import { loadClientModNames } from '@terrafirmagreg-team/dump/lib/dump/client/mods';
23
+ import { loadClientModAtlases } from '@terrafirmagreg-team/dump/lib/dump/client/atlases';
24
+ import { lookupSpriteInBundle } from '@terrafirmagreg-team/dump/lib/dump/assets/atlas/lookup';
25
+ import { stackIdBase, stackIdFromRef } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
26
+ import type { AtlasBundle } from '@terrafirmagreg-team/dump/lib/dump/assets/atlas/dto';
27
+ import { createDatasetCache } from '@terrafirmagreg-team/dump/lib/dump/reader';
29
28
 
30
29
  async function clientEntityNames(
31
- dataset: string,
30
+ dataset: DatasetRef,
32
31
  lang: string,
33
32
  ids: Iterable<string>,
34
33
  ): Promise<Record<string, string>> {
@@ -78,7 +77,7 @@ async function clientEntityNames(
78
77
  }
79
78
 
80
79
  async function clientNamedCategories(
81
- dataset: string,
80
+ dataset: DatasetRef,
82
81
  lang: string,
83
82
  types: string[],
84
83
  categories: RecipeCategory[],
@@ -92,13 +91,13 @@ async function clientNamedCategories(
92
91
  return names;
93
92
  }
94
93
 
95
- async function clientUsedIds(dataset: string): Promise<string[]> {
94
+ async function clientUsedIds(dataset: DatasetRef): Promise<string[]> {
96
95
  const manifest = await loadClientManifest(dataset);
97
96
  return manifest?.indexes.used ?? [];
98
97
  }
99
98
 
100
99
  async function clientRecipeGroups(
101
- dataset: string,
100
+ dataset: DatasetRef,
102
101
  lang: string,
103
102
  ): Promise<RecipeStackGroup[]> {
104
103
  const rows = await loadClientRegistryGroups(dataset);
@@ -111,20 +110,14 @@ async function clientRecipeGroups(
111
110
  }));
112
111
  }
113
112
 
114
- export function loadRecipeChromeClient(
115
- dataset: string,
116
- lang: string,
117
- ): Promise<RecipeChrome> {
118
- const key = `${dataset} ${lang}`;
119
- const cached = chromeCache.get(key);
120
- if (cached) return cached;
121
- const pending = (async (): Promise<RecipeChrome> => {
113
+ const loadChrome = createDatasetCache(
114
+ async (dataset: DatasetRef, lang: string): Promise<RecipeChrome> => {
122
115
  const [items, fluids, creative, categories, usedIds, itemTags, blockTags] =
123
116
  await Promise.all([
124
117
  loadClientRegistryOrder(dataset, 'item'),
125
118
  loadClientRegistryOrder(dataset, 'fluid'),
126
119
  loadClientTabs(dataset),
127
- loadClientRecipeCategories(dataset),
120
+ loadDatasetRecipeCategories(dataset),
128
121
  clientUsedIds(dataset),
129
122
  loadClientTagMembers(dataset, 'item'),
130
123
  loadClientTagMembers(dataset, 'block'),
@@ -175,6 +168,13 @@ export function loadRecipeChromeClient(
175
168
  [lang]: { ...tabNames, ...categoryNames, ...entityNames },
176
169
  },
177
170
  };
178
- })();
179
- return memoPending(chromeCache, key, pending);
171
+ },
172
+ );
173
+
174
+ export function loadRecipeChromeClient(
175
+ dataset: DatasetRef,
176
+ lang: string,
177
+ ): Promise<RecipeChrome> {
178
+ return loadChrome(dataset, lang);
180
179
  }
180
+
@@ -17,3 +17,4 @@ export {
17
17
  nonEmptyCategoryIds,
18
18
  recipeItemName,
19
19
  } from './catalog';
20
+
@@ -1,19 +1,13 @@
1
- import { clientDumpJson } from '@terrafirmagreg-team/game/lib/dump/client/dump';
2
- import { loadClientTagMembers } from '@terrafirmagreg-team/game/lib/dump/client/tags';
1
+ import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
2
+ import { clientDumpJson } from '@terrafirmagreg-team/dump/lib/dump/client/dump';
3
+ import { loadClientTagMembers } from '@terrafirmagreg-team/dump/lib/dump/client/tags';
3
4
  import {
4
5
  asRecord,
5
6
  asStringList,
6
7
  resolveEdgeRows,
7
- } from '@terrafirmagreg-team/game/lib/dump/contract/read';
8
- import { stackIdBase } from '@terrafirmagreg-team/game/lib/dump/contract/ref';
9
- import { memoPending } from './cache';
10
-
11
- const registrySliceCache = new Map<
12
- string,
13
- Promise<Record<string, Record<string, unknown>>>
14
- >();
15
- const tagSliceCache = new Map<string, Promise<Record<string, string[]>>>();
16
- const tagMembersCache = new Map<string, Promise<Record<string, string[]>>>();
8
+ } from '@terrafirmagreg-team/dump/lib/dump/contract/read';
9
+ import { stackIdBase } from '@terrafirmagreg-team/dump/lib/dump/contract/ref';
10
+ import { createDatasetCache } from '@terrafirmagreg-team/dump/lib/dump/reader';
17
11
 
18
12
  const REGISTRY_FIELD: Record<
19
13
  string,
@@ -29,24 +23,28 @@ function registryField(kind: string) {
29
23
  return REGISTRY_FIELD[kind] ?? 'items';
30
24
  }
31
25
 
26
+ const registrySliceCache = createDatasetCache(
27
+ async (
28
+ dataset: DatasetRef,
29
+ kind: string,
30
+ ): Promise<Record<string, Record<string, unknown>>> => {
31
+ const field = registryField(kind);
32
+ const raw = await clientDumpJson(dataset, `registry/${field}.json`);
33
+ const map = asRecord(raw);
34
+ return map ? resolveEdgeRows(map) : {};
35
+ },
36
+ (dataset, kind) => `${dataset.id}/${dataset.version ?? ''} ${registryField(kind)}`,
37
+ );
38
+
32
39
  function loadRegistryFile(
33
- dataset: string,
40
+ dataset: DatasetRef,
34
41
  kind: string,
35
42
  ): Promise<Record<string, Record<string, unknown>>> {
36
- const field = registryField(kind);
37
- const key = `${dataset} ${field}`;
38
- const cached = registrySliceCache.get(key);
39
- if (cached) return cached;
40
- const pending = clientDumpJson(dataset, `registry/${field}.json`)
41
- .then((raw) => {
42
- const map = asRecord(raw);
43
- return map ? resolveEdgeRows(map) : {};
44
- });
45
- return memoPending(registrySliceCache, key, pending);
43
+ return registrySliceCache(dataset, kind);
46
44
  }
47
45
 
48
46
  export async function loadRegistryEntrySlice(
49
- dataset: string,
47
+ dataset: DatasetRef,
50
48
  kind: string,
51
49
  id: string,
52
50
  ): Promise<Record<string, unknown> | undefined> {
@@ -55,16 +53,14 @@ export async function loadRegistryEntrySlice(
55
53
  return map[id] ?? map[base];
56
54
  }
57
55
 
58
- export function loadTagSlice(
59
- dataset: string,
60
- kind: string,
61
- ns: string,
62
- ): Promise<Record<string, string[]>> {
63
- const key = `${dataset} ${kind} ${ns}`;
64
- const cached = tagSliceCache.get(key);
65
- if (cached) return cached;
66
- const prefix = `${ns}:`;
67
- const pending = loadRegistryFile(dataset, kind).then((map) => {
56
+ const tagSliceCache = createDatasetCache(
57
+ async (
58
+ dataset: DatasetRef,
59
+ kind: string,
60
+ ns: string,
61
+ ): Promise<Record<string, string[]>> => {
62
+ const prefix = `${ns}:`;
63
+ const map = await loadRegistryFile(dataset, kind);
68
64
  const out: Record<string, string[]> = {};
69
65
  for (const [id, entry] of Object.entries(map)) {
70
66
  if (!id.startsWith(prefix)) continue;
@@ -72,39 +68,54 @@ export function loadTagSlice(
72
68
  if (tags.length) out[id] = tags;
73
69
  }
74
70
  return out;
75
- });
76
- return memoPending(tagSliceCache, key, pending);
77
- }
71
+ },
72
+ );
78
73
 
79
- function loadTagMembersByKind(
80
- dataset: string,
74
+ export function loadTagSlice(
75
+ dataset: DatasetRef,
81
76
  kind: string,
77
+ ns: string,
82
78
  ): Promise<Record<string, string[]>> {
83
- const memberKind = registryField(kind) === 'blocks' ? 'block' : 'item';
84
- const key = `${dataset} ${memberKind}`;
85
- const cached = tagMembersCache.get(key);
86
- if (cached) return cached;
87
- const pending = loadClientTagMembers(dataset, memberKind).then(
88
- (raw) => raw ?? {},
89
- );
90
- return memoPending(tagMembersCache, key, pending);
79
+ return tagSliceCache(dataset, kind, ns);
91
80
  }
92
81
 
93
- export function loadAllTagMembers(
94
- dataset: string,
95
- ): Promise<Record<string, string[]>> {
96
- const key = `${dataset} all`;
97
- const cached = tagMembersCache.get(key);
98
- if (cached) return cached;
99
- const pending = Promise.all([
100
- loadTagMembersByKind(dataset, 'item'),
101
- loadTagMembersByKind(dataset, 'block'),
102
- ]).then(([items, blocks]) => {
82
+ const tagMembersByKindCache = createDatasetCache(
83
+ async (
84
+ dataset: DatasetRef,
85
+ kind: string,
86
+ ): Promise<Record<string, string[]>> => {
87
+ const memberKind = registryField(kind) === 'blocks' ? 'block' : 'item';
88
+ return (await loadClientTagMembers(dataset, memberKind)) ?? {};
89
+ },
90
+ (dataset, kind) =>
91
+ `${dataset.id}/${dataset.version ?? ''} ${registryField(kind) === 'blocks' ? 'block' : 'item'}`,
92
+ );
93
+
94
+ const allTagMembersCache = createDatasetCache(
95
+ async (dataset: DatasetRef): Promise<Record<string, string[]>> => {
96
+ const [items, blocks] = await Promise.all([
97
+ loadTagMembersByKind(dataset, 'item'),
98
+ loadTagMembersByKind(dataset, 'block'),
99
+ ]);
103
100
  const merged: Record<string, string[]> = { ...items };
104
101
  for (const [tag, ids] of Object.entries(blocks)) {
105
102
  merged[tag] = merged[tag] ? [...merged[tag], ...ids] : ids;
106
103
  }
107
104
  return merged;
108
- });
109
- return memoPending(tagMembersCache, key, pending);
105
+ },
106
+ (dataset) => `${dataset.id}/${dataset.version ?? ''} all`,
107
+ );
108
+
109
+ function loadTagMembersByKind(
110
+ dataset: DatasetRef,
111
+ kind: string,
112
+ ): Promise<Record<string, string[]>> {
113
+ return tagMembersByKindCache(dataset, kind);
110
114
  }
115
+
116
+ export function loadAllTagMembers(
117
+ dataset: DatasetRef,
118
+ ): Promise<Record<string, string[]>> {
119
+ return allTagMembersCache(dataset);
120
+ }
121
+