@terrafirmagreg-team/dump 1.2.3 → 1.2.5
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/package.json +3 -3
- package/src/lib/dump/json-reader.ts +55 -17
- package/src/lib/dump/paths.ts +6 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@terrafirmagreg-team/dump",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Game-dump readers and contracts",
|
|
6
6
|
"license": "LGPL-3.0-only",
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"src"
|
|
15
15
|
],
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@terrafirmagreg-team/data": "^1.2.
|
|
17
|
+
"@terrafirmagreg-team/data": "^1.2.2",
|
|
18
18
|
"@terrafirmagreg-team/sites": "^1.2.1",
|
|
19
|
-
"@terrafirmagreg-team/translate": "^1.2.
|
|
19
|
+
"@terrafirmagreg-team/translate": "^1.2.6",
|
|
20
20
|
"aws4fetch": "^1.0.20",
|
|
21
21
|
"fumadocs-core": "16.17.10"
|
|
22
22
|
},
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
} from '@terrafirmagreg-team/dump/lib/dump/paths';
|
|
7
7
|
import type { DatasetRef } from '@terrafirmagreg-team/sites/location';
|
|
8
8
|
import type { DumpReader } from '@terrafirmagreg-team/dump/lib/dump/reader';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
createAsyncCache,
|
|
11
|
+
type AsyncCache,
|
|
12
|
+
} from '@terrafirmagreg-team/data/lib/async-cache';
|
|
13
|
+
import { markDumpResult } from '@terrafirmagreg-team/data/lib/dump-status';
|
|
10
14
|
|
|
11
15
|
const SAFE_LANG_CODE = /^[a-z0-9]+(_[a-z0-9]+)*$/i;
|
|
12
16
|
|
|
@@ -61,46 +65,76 @@ async function request(url: string): Promise<Response | undefined> {
|
|
|
61
65
|
|
|
62
66
|
export const DUMP_POINTER_TTL = 60_000;
|
|
63
67
|
|
|
64
|
-
|
|
68
|
+
function markDumpFetch(
|
|
69
|
+
datasetId: string | undefined,
|
|
70
|
+
res: Response | undefined,
|
|
71
|
+
ok: boolean,
|
|
72
|
+
) {
|
|
73
|
+
if (!datasetId) return;
|
|
74
|
+
if (res?.status === 404) return;
|
|
75
|
+
markDumpResult(datasetId, ok);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
const fetchJsonLoader = async (
|
|
79
|
+
url: string,
|
|
80
|
+
high: boolean,
|
|
81
|
+
datasetId?: string,
|
|
82
|
+
) =>
|
|
65
83
|
fetchLane(async () => {
|
|
66
84
|
try {
|
|
67
85
|
const res = await request(url);
|
|
68
|
-
|
|
86
|
+
const ok = res?.ok === true;
|
|
87
|
+
markDumpFetch(datasetId, res, ok);
|
|
88
|
+
if (!ok) return undefined;
|
|
69
89
|
return (await res.json()) as unknown;
|
|
70
90
|
} catch {
|
|
91
|
+
if (datasetId) markDumpResult(datasetId, false);
|
|
71
92
|
return undefined;
|
|
72
93
|
}
|
|
73
94
|
}, high);
|
|
74
95
|
|
|
75
|
-
const fetchJsonGzLoader = async (
|
|
96
|
+
const fetchJsonGzLoader = async (
|
|
97
|
+
url: string,
|
|
98
|
+
high: boolean,
|
|
99
|
+
datasetId?: string,
|
|
100
|
+
) =>
|
|
76
101
|
fetchLane(async () => {
|
|
77
102
|
try {
|
|
78
103
|
const res = await request(url);
|
|
79
|
-
|
|
104
|
+
const ok = res?.ok === true && Boolean(res.body);
|
|
105
|
+
markDumpFetch(datasetId, res, ok);
|
|
106
|
+
if (!ok) return undefined;
|
|
80
107
|
const text = await new Response(
|
|
81
|
-
res
|
|
108
|
+
res!.body!.pipeThrough(new DecompressionStream('gzip')),
|
|
82
109
|
).text();
|
|
83
110
|
return JSON.parse(text) as unknown;
|
|
84
111
|
} catch {
|
|
112
|
+
if (datasetId) markDumpResult(datasetId, false);
|
|
85
113
|
return undefined;
|
|
86
114
|
}
|
|
87
115
|
}, high);
|
|
88
116
|
|
|
89
|
-
const fetchJson = createAsyncCache(
|
|
117
|
+
const fetchJson = createAsyncCache(
|
|
118
|
+
fetchJsonLoader,
|
|
119
|
+
(url: string) => url,
|
|
120
|
+
) as AsyncCache<[url: string, high: boolean, datasetId?: string], unknown>;
|
|
90
121
|
|
|
91
|
-
const fetchJsonGz = createAsyncCache(
|
|
122
|
+
const fetchJsonGz = createAsyncCache(
|
|
123
|
+
fetchJsonGzLoader,
|
|
124
|
+
(url: string) => url,
|
|
125
|
+
) as AsyncCache<[url: string, high: boolean, datasetId?: string], unknown>;
|
|
92
126
|
|
|
93
127
|
const fetchJsonMutable = createAsyncCache(
|
|
94
128
|
fetchJsonLoader,
|
|
95
|
-
(url) => url,
|
|
129
|
+
(url: string) => url,
|
|
96
130
|
DUMP_POINTER_TTL,
|
|
97
|
-
)
|
|
131
|
+
) as AsyncCache<[url: string, high: boolean, datasetId?: string], unknown>;
|
|
98
132
|
|
|
99
133
|
const fetchJsonGzMutable = createAsyncCache(
|
|
100
134
|
fetchJsonGzLoader,
|
|
101
|
-
(url) => url,
|
|
135
|
+
(url: string) => url,
|
|
102
136
|
DUMP_POINTER_TTL,
|
|
103
|
-
)
|
|
137
|
+
) as AsyncCache<[url: string, high: boolean, datasetId?: string], unknown>;
|
|
104
138
|
|
|
105
139
|
export const COMPRESSED_TREE = /^(?:data|meta)\//;
|
|
106
140
|
|
|
@@ -135,14 +169,15 @@ export class JsonDumpReader implements DumpReader {
|
|
|
135
169
|
return fetchJsonMutable(
|
|
136
170
|
dumpStorageUrl(`${this.packId}/versions.json`),
|
|
137
171
|
high,
|
|
172
|
+
this.packId,
|
|
138
173
|
);
|
|
139
174
|
}
|
|
140
175
|
return this.location().then((loc) => {
|
|
141
176
|
const key = loc.files?.[path];
|
|
142
177
|
if (key) {
|
|
143
178
|
return key.endsWith('.gz')
|
|
144
|
-
? fetchJsonGz(dumpStorageUrl(`${key}`), high)
|
|
145
|
-
: fetchJson(dumpStorageUrl(`${key}`), high);
|
|
179
|
+
? fetchJsonGz(dumpStorageUrl(`${key}`), high, this.packId)
|
|
180
|
+
: fetchJson(dumpStorageUrl(`${key}`), high, this.packId);
|
|
146
181
|
}
|
|
147
182
|
|
|
148
183
|
if (loc.files) return undefined;
|
|
@@ -152,8 +187,8 @@ export class JsonDumpReader implements DumpReader {
|
|
|
152
187
|
? [fetchJsonMutable, fetchJsonGzMutable]
|
|
153
188
|
: [fetchJson, fetchJsonGz];
|
|
154
189
|
return COMPRESSED_TREE.test(path)
|
|
155
|
-
? jsonGz(dumpStorageUrl(`${rel}.gz`), high)
|
|
156
|
-
: json(dumpStorageUrl(`${rel}`), high);
|
|
190
|
+
? jsonGz(dumpStorageUrl(`${rel}.gz`), high, this.packId)
|
|
191
|
+
: json(dumpStorageUrl(`${rel}`), high, this.packId);
|
|
157
192
|
});
|
|
158
193
|
}
|
|
159
194
|
|
|
@@ -185,6 +220,7 @@ export class JsonDumpReader implements DumpReader {
|
|
|
185
220
|
const versions = (await fetchJsonMutable(
|
|
186
221
|
dumpStorageUrl(`${this.packId}/versions.json`),
|
|
187
222
|
true,
|
|
223
|
+
this.packId,
|
|
188
224
|
)) as { latest?: string } | undefined;
|
|
189
225
|
if (versions?.latest) {
|
|
190
226
|
const root = `${this.packId}/${versions.latest}`;
|
|
@@ -192,6 +228,7 @@ export class JsonDumpReader implements DumpReader {
|
|
|
192
228
|
const exists = await fetchJson(
|
|
193
229
|
dumpStorageUrl(`${root}/manifest.json`),
|
|
194
230
|
false,
|
|
231
|
+
this.packId,
|
|
195
232
|
);
|
|
196
233
|
if (exists) {
|
|
197
234
|
const loc: DumpLocation = { root, files: await this.objectsIndex(root) };
|
|
@@ -212,8 +249,9 @@ export class JsonDumpReader implements DumpReader {
|
|
|
212
249
|
(await fetchJsonGz(
|
|
213
250
|
dumpStorageUrl(`${root}/objects.json.gz`),
|
|
214
251
|
false,
|
|
252
|
+
this.packId,
|
|
215
253
|
)) ??
|
|
216
|
-
(await fetchJson(dumpStorageUrl(`${root}/objects.json`), false));
|
|
254
|
+
(await fetchJson(dumpStorageUrl(`${root}/objects.json`), false, this.packId));
|
|
217
255
|
const files =
|
|
218
256
|
raw && typeof raw === 'object' && !Array.isArray(raw)
|
|
219
257
|
? (raw as Record<string, unknown>).files
|
package/src/lib/dump/paths.ts
CHANGED
|
@@ -8,8 +8,12 @@ export type DumpLocation = {
|
|
|
8
8
|
files?: Record<string, string>;
|
|
9
9
|
};
|
|
10
10
|
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const store = globalThis as Record<symbol, unknown>;
|
|
12
|
+
const dumpLocations = (store[Symbol.for('terrafirmagreg.dump.locations')] ??=
|
|
13
|
+
new Map<string, DumpLocation>()) as Map<string, DumpLocation>;
|
|
14
|
+
const dumpLocationListeners = (store[
|
|
15
|
+
Symbol.for('terrafirmagreg.dump.locationListeners')
|
|
16
|
+
] ??= new Set<() => void>()) as Set<() => void>;
|
|
13
17
|
|
|
14
18
|
export function registerDumpLocation(
|
|
15
19
|
dataset: DatasetRef,
|