@dreamboard-games/api-client 0.1.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.
- package/LICENSE +89 -0
- package/NOTICE +1 -0
- package/dist/@tanstack/react-query.gen.d.ts +1037 -0
- package/dist/@tanstack/react-query.gen.d.ts.map +1 -0
- package/dist/@tanstack/react-query.gen.js +1016 -0
- package/dist/client/client.gen.d.ts +3 -0
- package/dist/client/client.gen.d.ts.map +1 -0
- package/dist/client/client.gen.js +235 -0
- package/dist/client/index.d.ts +9 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +6 -0
- package/dist/client/types.gen.d.ts +118 -0
- package/dist/client/types.gen.d.ts.map +1 -0
- package/dist/client/types.gen.js +2 -0
- package/dist/client/utils.gen.d.ts +34 -0
- package/dist/client/utils.gen.d.ts.map +1 -0
- package/dist/client/utils.gen.js +233 -0
- package/dist/client.gen.d.ts +13 -0
- package/dist/client.gen.d.ts.map +1 -0
- package/dist/client.gen.js +3 -0
- package/dist/core/auth.gen.d.ts +19 -0
- package/dist/core/auth.gen.d.ts.map +1 -0
- package/dist/core/auth.gen.js +14 -0
- package/dist/core/bodySerializer.gen.d.ts +26 -0
- package/dist/core/bodySerializer.gen.d.ts.map +1 -0
- package/dist/core/bodySerializer.gen.js +57 -0
- package/dist/core/params.gen.d.ts +44 -0
- package/dist/core/params.gen.d.ts.map +1 -0
- package/dist/core/params.gen.js +100 -0
- package/dist/core/pathSerializer.gen.d.ts +34 -0
- package/dist/core/pathSerializer.gen.d.ts.map +1 -0
- package/dist/core/pathSerializer.gen.js +114 -0
- package/dist/core/queryKeySerializer.gen.d.ts +19 -0
- package/dist/core/queryKeySerializer.gen.d.ts.map +1 -0
- package/dist/core/queryKeySerializer.gen.js +99 -0
- package/dist/core/serverSentEvents.gen.d.ts +72 -0
- package/dist/core/serverSentEvents.gen.d.ts.map +1 -0
- package/dist/core/serverSentEvents.gen.js +136 -0
- package/dist/core/types.gen.d.ts +79 -0
- package/dist/core/types.gen.d.ts.map +1 -0
- package/dist/core/types.gen.js +2 -0
- package/dist/core/utils.gen.d.ts +20 -0
- package/dist/core/utils.gen.d.ts.map +1 -0
- package/dist/core/utils.gen.js +87 -0
- package/dist/generated/problem-types.gen.d.ts +26 -0
- package/dist/generated/problem-types.gen.d.ts.map +1 -0
- package/dist/generated/problem-types.gen.js +23 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/sdk.gen.d.ts +364 -0
- package/dist/sdk.gen.d.ts.map +1 -0
- package/dist/sdk.gen.js +634 -0
- package/dist/source-revisions.d.ts +27 -0
- package/dist/source-revisions.d.ts.map +1 -0
- package/dist/source-revisions.js +174 -0
- package/dist/storage-paths.d.ts +17 -0
- package/dist/storage-paths.d.ts.map +1 -0
- package/dist/storage-paths.js +16 -0
- package/dist/types.gen.d.ts +5007 -0
- package/dist/types.gen.d.ts.map +1 -0
- package/dist/types.gen.js +2 -0
- package/dist/zod.gen.d.ts +37398 -0
- package/dist/zod.gen.d.ts.map +1 -0
- package/dist/zod.gen.js +2396 -0
- package/package.json +105 -0
- package/src/@tanstack/react-query.gen.ts +1114 -0
- package/src/client/client.gen.ts +311 -0
- package/src/client/index.ts +25 -0
- package/src/client/types.gen.ts +241 -0
- package/src/client/utils.gen.ts +332 -0
- package/src/client.gen.ts +16 -0
- package/src/core/auth.gen.ts +42 -0
- package/src/core/bodySerializer.gen.ts +100 -0
- package/src/core/params.gen.ts +176 -0
- package/src/core/pathSerializer.gen.ts +181 -0
- package/src/core/queryKeySerializer.gen.ts +136 -0
- package/src/core/serverSentEvents.gen.ts +265 -0
- package/src/core/types.gen.ts +118 -0
- package/src/core/utils.gen.ts +143 -0
- package/src/generated/problem-types.gen.ts +35 -0
- package/src/index.ts +7 -0
- package/src/sdk.gen.ts +709 -0
- package/src/source-revisions.ts +283 -0
- package/src/storage-paths.ts +19 -0
- package/src/types.gen.ts +5486 -0
- package/src/zod.gen.ts +2705 -0
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { createSourceBlobUploadSession } from "./sdk.gen.js";
|
|
2
|
+
const textEncoder = new TextEncoder();
|
|
3
|
+
function bytesToHex(bytes) {
|
|
4
|
+
return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
5
|
+
}
|
|
6
|
+
async function sha256Hex(bytes) {
|
|
7
|
+
const normalizedBytes = new Uint8Array(bytes.byteLength);
|
|
8
|
+
normalizedBytes.set(bytes);
|
|
9
|
+
const digest = await crypto.subtle.digest("SHA-256", normalizedBytes.buffer);
|
|
10
|
+
return bytesToHex(new Uint8Array(digest));
|
|
11
|
+
}
|
|
12
|
+
function getUtf8ByteSize(content) {
|
|
13
|
+
return textEncoder.encode(content).byteLength;
|
|
14
|
+
}
|
|
15
|
+
async function computeSourceContentHash(content) {
|
|
16
|
+
return sha256Hex(textEncoder.encode(content));
|
|
17
|
+
}
|
|
18
|
+
async function describeSourceBlob(content) {
|
|
19
|
+
return {
|
|
20
|
+
contentHash: await computeSourceContentHash(content),
|
|
21
|
+
byteSize: getUtf8ByteSize(content),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
export async function materializeSourceChangeOperations(changes) {
|
|
25
|
+
const blobsByHash = new Map();
|
|
26
|
+
const materialized = await Promise.all(Array.from(changes, async (change) => {
|
|
27
|
+
if (change.kind === "delete") {
|
|
28
|
+
return change;
|
|
29
|
+
}
|
|
30
|
+
const blob = await describeSourceBlob(change.content);
|
|
31
|
+
const existing = blobsByHash.get(blob.contentHash);
|
|
32
|
+
if (!existing) {
|
|
33
|
+
blobsByHash.set(blob.contentHash, blob);
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
kind: "upsert",
|
|
37
|
+
path: change.path,
|
|
38
|
+
contentHash: blob.contentHash,
|
|
39
|
+
byteSize: blob.byteSize,
|
|
40
|
+
};
|
|
41
|
+
}));
|
|
42
|
+
return {
|
|
43
|
+
blobs: Array.from(blobsByHash.values()).sort((left, right) => left.contentHash.localeCompare(right.contentHash)),
|
|
44
|
+
changes: materialized,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
export function mapUpsertBlobContentsByContentHash(localChanges, materializedChanges) {
|
|
48
|
+
const uploadBlobs = new Map();
|
|
49
|
+
const length = Math.min(localChanges.length, materializedChanges.length);
|
|
50
|
+
for (let index = 0; index < length; index += 1) {
|
|
51
|
+
const localChange = localChanges[index];
|
|
52
|
+
const materializedChange = materializedChanges[index];
|
|
53
|
+
if (localChange?.kind !== "upsert" ||
|
|
54
|
+
materializedChange?.kind !== "upsert") {
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
uploadBlobs.set(materializedChange.contentHash, {
|
|
58
|
+
contentHash: materializedChange.contentHash,
|
|
59
|
+
byteSize: materializedChange.byteSize,
|
|
60
|
+
content: localChange.content,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
return uploadBlobs;
|
|
64
|
+
}
|
|
65
|
+
class SourceBlobUploadError extends Error {
|
|
66
|
+
constructor(status, details) {
|
|
67
|
+
const suffix = details.trim().length > 0 ? `: ${details.trim()}` : "";
|
|
68
|
+
super(`Failed to upload source blob (HTTP ${status}${suffix})`);
|
|
69
|
+
this.name = "SourceBlobUploadError";
|
|
70
|
+
this.status = status;
|
|
71
|
+
this.details = details;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function isDuplicateDirectUploadError(error) {
|
|
75
|
+
if (!(error instanceof SourceBlobUploadError)) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
if (error.status === 409) {
|
|
79
|
+
return true;
|
|
80
|
+
}
|
|
81
|
+
const normalizedDetails = error.details.toLowerCase();
|
|
82
|
+
return (normalizedDetails.includes("duplicate") ||
|
|
83
|
+
normalizedDetails.includes("already exists") ||
|
|
84
|
+
normalizedDetails.includes("resource already exists"));
|
|
85
|
+
}
|
|
86
|
+
async function uploadSourceBlob(uploadTarget, content) {
|
|
87
|
+
const response = await fetch(uploadTarget.url, {
|
|
88
|
+
method: uploadTarget.method,
|
|
89
|
+
headers: uploadTarget.headers,
|
|
90
|
+
body: textEncoder.encode(content),
|
|
91
|
+
});
|
|
92
|
+
if (response.ok) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const details = await response.text().catch(() => "");
|
|
96
|
+
throw new SourceBlobUploadError(response.status, details);
|
|
97
|
+
}
|
|
98
|
+
export class SourceBlobSessionRequestError extends Error {
|
|
99
|
+
constructor(message, apiError, response) {
|
|
100
|
+
super(message);
|
|
101
|
+
this.name = "SourceBlobSessionRequestError";
|
|
102
|
+
this.apiError = apiError;
|
|
103
|
+
this.response = response;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
async function confirmSourceBlobAlreadyExists(options) {
|
|
107
|
+
const { gameId, blob } = options;
|
|
108
|
+
const { data, error, response } = await createSourceBlobUploadSession({
|
|
109
|
+
path: { gameId },
|
|
110
|
+
body: {
|
|
111
|
+
blobs: [
|
|
112
|
+
{
|
|
113
|
+
contentHash: blob.contentHash,
|
|
114
|
+
byteSize: blob.byteSize,
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
if (error || !data) {
|
|
120
|
+
throw new SourceBlobSessionRequestError("Failed to create source blob upload session", error, response);
|
|
121
|
+
}
|
|
122
|
+
return data.uploads[0]?.status === "exists";
|
|
123
|
+
}
|
|
124
|
+
export async function uploadGameSourceBlobs(options) {
|
|
125
|
+
const { gameId, blobs } = options;
|
|
126
|
+
const uniqueBlobs = new Map();
|
|
127
|
+
for (const blob of blobs) {
|
|
128
|
+
const existing = uniqueBlobs.get(blob.contentHash);
|
|
129
|
+
if (!existing) {
|
|
130
|
+
uniqueBlobs.set(blob.contentHash, blob);
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (existing.byteSize !== blob.byteSize) {
|
|
134
|
+
throw new Error(`Source blob ${blob.contentHash} has conflicting byte sizes.`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (uniqueBlobs.size === 0) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
const { data, error, response } = await createSourceBlobUploadSession({
|
|
141
|
+
path: { gameId },
|
|
142
|
+
body: {
|
|
143
|
+
blobs: Array.from(uniqueBlobs.values(), ({ contentHash, byteSize }) => ({
|
|
144
|
+
contentHash,
|
|
145
|
+
byteSize,
|
|
146
|
+
})),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
if (error || !data) {
|
|
150
|
+
throw new SourceBlobSessionRequestError("Failed to create source blob upload session", error, response);
|
|
151
|
+
}
|
|
152
|
+
for (const upload of data.uploads) {
|
|
153
|
+
if (upload.status !== "upload_required") {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const blob = uniqueBlobs.get(upload.contentHash);
|
|
157
|
+
if (!blob) {
|
|
158
|
+
throw new Error(`Upload session referenced unknown source blob ${upload.contentHash}.`);
|
|
159
|
+
}
|
|
160
|
+
if (!upload.uploadTarget) {
|
|
161
|
+
throw new Error(`Upload target missing for source blob ${upload.contentHash}.`);
|
|
162
|
+
}
|
|
163
|
+
try {
|
|
164
|
+
await uploadSourceBlob(upload.uploadTarget, blob.content);
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
if (isDuplicateDirectUploadError(error) &&
|
|
168
|
+
(await confirmSourceBlobAlreadyExists({ gameId, blob }))) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
throw error;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage path constants shared between frontend and backend.
|
|
3
|
+
* These mirror the values in the Kotlin StoragePathUtils.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Storage bucket for compiled scripts (game logic and UI bundles)
|
|
7
|
+
*/
|
|
8
|
+
export declare const STORAGE_BUCKET = "scripts";
|
|
9
|
+
/**
|
|
10
|
+
* Directory name for source files
|
|
11
|
+
*/
|
|
12
|
+
export declare const SOURCE_DIR = "src";
|
|
13
|
+
/**
|
|
14
|
+
* Directory name for compiled output
|
|
15
|
+
*/
|
|
16
|
+
export declare const DIST_DIR = "dist";
|
|
17
|
+
//# sourceMappingURL=storage-paths.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage-paths.d.ts","sourceRoot":"","sources":["../src/storage-paths.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH;;GAEG;AACH,eAAO,MAAM,cAAc,YAAY,CAAC;AAExC;;GAEG;AACH,eAAO,MAAM,UAAU,QAAQ,CAAC;AAEhC;;GAEG;AACH,eAAO,MAAM,QAAQ,SAAS,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage path constants shared between frontend and backend.
|
|
3
|
+
* These mirror the values in the Kotlin StoragePathUtils.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Storage bucket for compiled scripts (game logic and UI bundles)
|
|
7
|
+
*/
|
|
8
|
+
export const STORAGE_BUCKET = "scripts";
|
|
9
|
+
/**
|
|
10
|
+
* Directory name for source files
|
|
11
|
+
*/
|
|
12
|
+
export const SOURCE_DIR = "src";
|
|
13
|
+
/**
|
|
14
|
+
* Directory name for compiled output
|
|
15
|
+
*/
|
|
16
|
+
export const DIST_DIR = "dist";
|