@crowdedkingdoms/crowdyjs 9.0.0 → 10.0.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/MIGRATION.md +56 -34
- package/README.md +83 -50
- package/dist/crowdy-client.d.ts +3 -0
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +2 -0
- package/dist/domains/playerCodeProjects.d.ts +25 -0
- package/dist/domains/playerCodeProjects.d.ts.map +1 -0
- package/dist/domains/playerCodeProjects.js +299 -0
- package/dist/domains/playerCompute.d.ts +1 -1
- package/dist/domains/playerCompute.js +1 -1
- package/dist/generated/graphql.d.ts +792 -7
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +57 -0
- package/dist/index.d.ts +3 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -5
- package/dist/kit/npcs.d.ts.map +1 -1
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/live-coding/rust-analysis.d.ts.map +1 -1
- package/dist/live-coding/rust-analysis.js +64 -1
- package/dist/live-coding/worker-transport.d.ts +3 -0
- package/dist/live-coding/worker-transport.d.ts.map +1 -1
- package/dist/live-coding/worker-transport.js +13 -0
- package/dist/mod-studio/controller.d.ts +188 -0
- package/dist/mod-studio/controller.d.ts.map +1 -0
- package/dist/mod-studio/controller.js +915 -0
- package/dist/mod-studio/diagnostics.d.ts +22 -0
- package/dist/mod-studio/diagnostics.d.ts.map +1 -0
- package/dist/mod-studio/diagnostics.js +141 -0
- package/dist/mod-studio/dom-shell.d.ts +55 -0
- package/dist/mod-studio/dom-shell.d.ts.map +1 -0
- package/dist/mod-studio/dom-shell.js +527 -0
- package/dist/mod-studio/editor.d.ts +17 -0
- package/dist/mod-studio/editor.d.ts.map +1 -0
- package/dist/mod-studio/editor.js +1 -0
- package/dist/mod-studio/index.d.ts +10 -0
- package/dist/mod-studio/index.d.ts.map +1 -0
- package/dist/mod-studio/index.js +9 -0
- package/dist/mod-studio/models.d.ts +149 -0
- package/dist/mod-studio/models.d.ts.map +1 -0
- package/dist/mod-studio/models.js +62 -0
- package/dist/mod-studio/monaco-editor.d.ts +16 -0
- package/dist/mod-studio/monaco-editor.d.ts.map +1 -0
- package/dist/mod-studio/monaco-editor.js +548 -0
- package/dist/mod-studio/mount.d.ts +17 -0
- package/dist/mod-studio/mount.d.ts.map +1 -0
- package/dist/mod-studio/mount.js +86 -0
- package/dist/mod-studio/starter-projects.d.ts +11 -0
- package/dist/mod-studio/starter-projects.d.ts.map +1 -0
- package/dist/mod-studio/starter-projects.js +102 -0
- package/dist/mod-studio/styles.d.ts +2 -0
- package/dist/mod-studio/styles.d.ts.map +1 -0
- package/dist/mod-studio/styles.js +14 -0
- package/dist/mod-studio/textarea-editor.d.ts +8 -0
- package/dist/mod-studio/textarea-editor.d.ts.map +1 -0
- package/dist/mod-studio/textarea-editor.js +71 -0
- package/package.json +4 -4
- package/dist/live-coding/ide.d.ts +0 -23
- package/dist/live-coding/ide.d.ts.map +0 -1
- package/dist/live-coding/ide.js +0 -514
- package/dist/live-coding/index.d.ts +0 -8
- package/dist/live-coding/index.d.ts.map +0 -1
- package/dist/live-coding/index.js +0 -7
- package/dist/live-coding/live-coding-controller.d.ts +0 -75
- package/dist/live-coding/live-coding-controller.d.ts.map +0 -1
- package/dist/live-coding/live-coding-controller.js +0 -141
- package/dist/live-coding/mount.d.ts +0 -26
- package/dist/live-coding/mount.d.ts.map +0 -1
- package/dist/live-coding/mount.js +0 -108
- package/dist/live-coding/templates.d.ts +0 -17
- package/dist/live-coding/templates.d.ts.map +0 -1
- package/dist/live-coding/templates.js +0 -59
|
@@ -0,0 +1,299 @@
|
|
|
1
|
+
import { CrowdyGraphQLError, CrowdyHttpError, CrowdyNetworkError, CrowdyTimeoutError, } from '../errors.js';
|
|
2
|
+
import { ModStudioOfflineError, ModStudioRevisionConflictError, normalizeModStudioPath, } from '../mod-studio/models.js';
|
|
3
|
+
import { PlayerCodeCommonFilesDocument, PlayerCodeImportSource, PlayerCodeLibraryFilesDocument, PlayerCodeLibrarySaveDocument, PlayerCodePairingPreference, PlayerCodeProjectCreateDocument, PlayerCodeProjectDocument, PlayerCodeProjectImportFileDocument, PlayerCodeProjectSaveDocument, PlayerCodeProjectsDocument, } from '../generated/graphql.js';
|
|
4
|
+
/**
|
|
5
|
+
* Typed Game API adapter for private Mod Studio projects and reusable files.
|
|
6
|
+
* Mutable projects remain separate from immutable player-compute versions;
|
|
7
|
+
* only the controller's deploy path converts target files to sourceFilesJson.
|
|
8
|
+
*/
|
|
9
|
+
export class PlayerCodeProjectsAPI {
|
|
10
|
+
constructor(graphql) {
|
|
11
|
+
this.graphql = graphql;
|
|
12
|
+
this.baselines = new Map();
|
|
13
|
+
}
|
|
14
|
+
async listProjects(scope) {
|
|
15
|
+
const data = await this.request(PlayerCodeProjectsDocument, {
|
|
16
|
+
appId: scope.appId,
|
|
17
|
+
includeArchived: false,
|
|
18
|
+
limit: 50,
|
|
19
|
+
offset: 0,
|
|
20
|
+
});
|
|
21
|
+
return data.playerCodeProjects.map(fromSummaryDto);
|
|
22
|
+
}
|
|
23
|
+
async getProject(input) {
|
|
24
|
+
const data = await this.request(PlayerCodeProjectDocument, {
|
|
25
|
+
appId: input.appId,
|
|
26
|
+
projectId: input.projectId,
|
|
27
|
+
});
|
|
28
|
+
return this.remember(fromProjectDto(data.playerCodeProject, input.gridId));
|
|
29
|
+
}
|
|
30
|
+
async createProject(input) {
|
|
31
|
+
const data = await this.request(PlayerCodeProjectCreateDocument, {
|
|
32
|
+
input: {
|
|
33
|
+
appId: input.appId,
|
|
34
|
+
gridId: input.gridId,
|
|
35
|
+
name: input.metadata.name,
|
|
36
|
+
description: input.metadata.description ?? null,
|
|
37
|
+
serverModuleName: input.metadata.serverModuleName ?? null,
|
|
38
|
+
clientModuleName: input.metadata.clientModuleName ?? null,
|
|
39
|
+
pairingPreference: toApiPairing(input.kind, input.metadata.pairingPreference),
|
|
40
|
+
sdkVersion: '0.1.5',
|
|
41
|
+
abiVersion: 0,
|
|
42
|
+
initialFiles: input.files.map(toApiFile),
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
return this.remember(fromProjectDto(data.playerCodeProjectCreate, input.gridId));
|
|
46
|
+
}
|
|
47
|
+
async saveProject(input) {
|
|
48
|
+
try {
|
|
49
|
+
const baseline = this.baselines.get(input.projectId) ??
|
|
50
|
+
(await this.getProject({
|
|
51
|
+
appId: input.appId,
|
|
52
|
+
gridId: input.gridId,
|
|
53
|
+
projectId: input.projectId,
|
|
54
|
+
}));
|
|
55
|
+
const delta = projectFileDelta(baseline, input);
|
|
56
|
+
const data = await this.request(PlayerCodeProjectSaveDocument, {
|
|
57
|
+
input: {
|
|
58
|
+
appId: input.appId,
|
|
59
|
+
projectId: input.projectId,
|
|
60
|
+
expectedRevision: input.expectedRevisionId,
|
|
61
|
+
gridId: input.gridId,
|
|
62
|
+
name: input.metadata.name,
|
|
63
|
+
description: input.metadata.description ?? null,
|
|
64
|
+
serverModuleName: input.metadata.serverModuleName ?? null,
|
|
65
|
+
clientModuleName: input.metadata.clientModuleName ?? null,
|
|
66
|
+
pairingPreference: toApiPairing(projectKind(input), input.metadata.pairingPreference),
|
|
67
|
+
upserts: delta.upserts.map(toApiFile),
|
|
68
|
+
deletes: delta.deletes.map(({ target, path }) => ({
|
|
69
|
+
target: target,
|
|
70
|
+
path,
|
|
71
|
+
})),
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
return this.remember(fromProjectDto(data.playerCodeProjectSave, input.gridId));
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
if (error instanceof CrowdyGraphQLError &&
|
|
78
|
+
error.code === 'CONFLICT' &&
|
|
79
|
+
error.message.includes('PLAYER_CODE_REVISION_CONFLICT')) {
|
|
80
|
+
let remoteProject;
|
|
81
|
+
try {
|
|
82
|
+
remoteProject = await this.getProject({
|
|
83
|
+
appId: input.appId,
|
|
84
|
+
gridId: input.gridId,
|
|
85
|
+
projectId: input.projectId,
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// The conflict remains actionable if the follow-up read fails.
|
|
90
|
+
}
|
|
91
|
+
throw new ModStudioRevisionConflictError(error.message, remoteProject);
|
|
92
|
+
}
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
async listPersonalLibraryFiles(scope) {
|
|
97
|
+
const data = await this.request(PlayerCodeLibraryFilesDocument, {
|
|
98
|
+
appId: scope.appId,
|
|
99
|
+
includeArchived: false,
|
|
100
|
+
limit: 100,
|
|
101
|
+
offset: 0,
|
|
102
|
+
});
|
|
103
|
+
return data.playerCodeLibraryFiles.map(fromLibraryDto);
|
|
104
|
+
}
|
|
105
|
+
async savePersonalLibraryFile(input) {
|
|
106
|
+
const data = await this.request(PlayerCodeLibrarySaveDocument, {
|
|
107
|
+
input: {
|
|
108
|
+
appId: input.appId,
|
|
109
|
+
title: input.title,
|
|
110
|
+
pathHint: normalizeModStudioPath(input.path),
|
|
111
|
+
target: input.target,
|
|
112
|
+
tags: input.tags ?? [],
|
|
113
|
+
content: input.content,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
116
|
+
return fromLibraryDto(data.playerCodeLibrarySave);
|
|
117
|
+
}
|
|
118
|
+
async listCommonFiles(scope) {
|
|
119
|
+
const data = await this.request(PlayerCodeCommonFilesDocument, {
|
|
120
|
+
appId: scope.appId,
|
|
121
|
+
limit: 100,
|
|
122
|
+
offset: 0,
|
|
123
|
+
});
|
|
124
|
+
return data.playerCodeCommonFiles.map(fromCommonDto);
|
|
125
|
+
}
|
|
126
|
+
async importReferenceFile(input) {
|
|
127
|
+
const data = await this.request(PlayerCodeProjectImportFileDocument, {
|
|
128
|
+
input: {
|
|
129
|
+
appId: input.appId,
|
|
130
|
+
projectId: input.projectId,
|
|
131
|
+
expectedProjectRevision: input.expectedRevisionId,
|
|
132
|
+
source: input.source === 'PERSONAL_LIBRARY'
|
|
133
|
+
? PlayerCodeImportSource.Library
|
|
134
|
+
: PlayerCodeImportSource.Common,
|
|
135
|
+
...(input.source === 'PERSONAL_LIBRARY'
|
|
136
|
+
? { libraryFileId: input.referenceId }
|
|
137
|
+
: { commonVersionId: input.referenceId }),
|
|
138
|
+
...(input.destinationPath
|
|
139
|
+
? { destinationPath: normalizeModStudioPath(input.destinationPath) }
|
|
140
|
+
: {}),
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
return this.remember(fromProjectDto(data.playerCodeProjectImportFile, input.gridId));
|
|
144
|
+
}
|
|
145
|
+
remember(project) {
|
|
146
|
+
this.baselines.set(project.projectId, cloneProject(project));
|
|
147
|
+
return project;
|
|
148
|
+
}
|
|
149
|
+
async request(document, variables) {
|
|
150
|
+
try {
|
|
151
|
+
return await this.graphql.request(document, variables);
|
|
152
|
+
}
|
|
153
|
+
catch (error) {
|
|
154
|
+
if (error instanceof CrowdyNetworkError ||
|
|
155
|
+
error instanceof CrowdyTimeoutError ||
|
|
156
|
+
(error instanceof CrowdyHttpError && error.status >= 500)) {
|
|
157
|
+
throw new ModStudioOfflineError(error.message, error);
|
|
158
|
+
}
|
|
159
|
+
throw error;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
function fromSummaryDto(dto) {
|
|
164
|
+
return {
|
|
165
|
+
projectId: dto.projectId,
|
|
166
|
+
name: dto.name,
|
|
167
|
+
kind: kindFromApi(dto.pairingPreference),
|
|
168
|
+
revisionId: String(dto.revision),
|
|
169
|
+
...(dto.serverModuleName
|
|
170
|
+
? { serverModuleName: dto.serverModuleName }
|
|
171
|
+
: {}),
|
|
172
|
+
...(dto.clientModuleName
|
|
173
|
+
? { clientModuleName: dto.clientModuleName }
|
|
174
|
+
: {}),
|
|
175
|
+
updatedAt: dto.updatedAt,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function fromProjectDto(dto, fallbackGridId) {
|
|
179
|
+
const files = dto.files.map((file) => ({
|
|
180
|
+
target: file.target,
|
|
181
|
+
path: normalizeModStudioPath(file.path),
|
|
182
|
+
content: file.content,
|
|
183
|
+
}));
|
|
184
|
+
return {
|
|
185
|
+
projectId: dto.projectId,
|
|
186
|
+
appId: String(dto.appId),
|
|
187
|
+
gridId: dto.gridId == null ? fallbackGridId : String(dto.gridId),
|
|
188
|
+
kind: kindFromApi(dto.pairingPreference),
|
|
189
|
+
metadata: {
|
|
190
|
+
name: dto.name,
|
|
191
|
+
...(dto.description ? { description: dto.description } : {}),
|
|
192
|
+
...(dto.serverModuleName
|
|
193
|
+
? { serverModuleName: dto.serverModuleName }
|
|
194
|
+
: {}),
|
|
195
|
+
...(dto.clientModuleName
|
|
196
|
+
? { clientModuleName: dto.clientModuleName }
|
|
197
|
+
: {}),
|
|
198
|
+
pairingPreference: fromApiPairing(dto.pairingPreference),
|
|
199
|
+
},
|
|
200
|
+
files,
|
|
201
|
+
sdkVersion: dto.sdkVersion,
|
|
202
|
+
abiVersion: dto.abiVersion,
|
|
203
|
+
revision: {
|
|
204
|
+
id: String(dto.revision),
|
|
205
|
+
savedAt: dto.updatedAt,
|
|
206
|
+
},
|
|
207
|
+
createdAt: dto.createdAt,
|
|
208
|
+
updatedAt: dto.updatedAt,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
function fromLibraryDto(dto) {
|
|
212
|
+
return {
|
|
213
|
+
id: dto.libraryFileId,
|
|
214
|
+
source: 'PERSONAL_LIBRARY',
|
|
215
|
+
title: dto.title,
|
|
216
|
+
target: dto.target,
|
|
217
|
+
path: normalizeModStudioPath(dto.pathHint),
|
|
218
|
+
content: dto.content,
|
|
219
|
+
tags: [...dto.tags],
|
|
220
|
+
updatedAt: dto.updatedAt,
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
function fromCommonDto(dto) {
|
|
224
|
+
return {
|
|
225
|
+
id: dto.versionId,
|
|
226
|
+
source: 'COMMON',
|
|
227
|
+
title: dto.title,
|
|
228
|
+
target: dto.target,
|
|
229
|
+
path: normalizeModStudioPath(dto.path),
|
|
230
|
+
content: dto.content,
|
|
231
|
+
tags: [...dto.tags],
|
|
232
|
+
updatedAt: dto.updatedAt,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
function kindFromApi(pairing) {
|
|
236
|
+
if (pairing === PlayerCodePairingPreference.ServerOnly)
|
|
237
|
+
return 'SERVER';
|
|
238
|
+
if (pairing === PlayerCodePairingPreference.ClientOnly)
|
|
239
|
+
return 'CLIENT';
|
|
240
|
+
return 'FULL_STACK';
|
|
241
|
+
}
|
|
242
|
+
function fromApiPairing(pairing) {
|
|
243
|
+
if (pairing === PlayerCodePairingPreference.Paired)
|
|
244
|
+
return 'REQUIRED';
|
|
245
|
+
if (pairing === PlayerCodePairingPreference.Independent)
|
|
246
|
+
return 'OPTIONAL';
|
|
247
|
+
return 'NONE';
|
|
248
|
+
}
|
|
249
|
+
function toApiPairing(kind, pairing) {
|
|
250
|
+
if (kind === 'SERVER')
|
|
251
|
+
return PlayerCodePairingPreference.ServerOnly;
|
|
252
|
+
if (kind === 'CLIENT')
|
|
253
|
+
return PlayerCodePairingPreference.ClientOnly;
|
|
254
|
+
return pairing === 'REQUIRED'
|
|
255
|
+
? PlayerCodePairingPreference.Paired
|
|
256
|
+
: PlayerCodePairingPreference.Independent;
|
|
257
|
+
}
|
|
258
|
+
function toApiFile(file) {
|
|
259
|
+
return {
|
|
260
|
+
target: file.target,
|
|
261
|
+
path: normalizeModStudioPath(file.path),
|
|
262
|
+
content: file.content,
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
function projectKind(input) {
|
|
266
|
+
const hasServer = input.files.some((file) => file.target === 'SERVER');
|
|
267
|
+
const hasClient = input.files.some((file) => file.target === 'CLIENT');
|
|
268
|
+
if (hasServer && hasClient)
|
|
269
|
+
return 'FULL_STACK';
|
|
270
|
+
if (hasServer)
|
|
271
|
+
return 'SERVER';
|
|
272
|
+
return 'CLIENT';
|
|
273
|
+
}
|
|
274
|
+
function projectFileDelta(baseline, input) {
|
|
275
|
+
const previous = new Map(baseline.files.map((file) => [
|
|
276
|
+
`${file.target}:${normalizeModStudioPath(file.path)}`,
|
|
277
|
+
file,
|
|
278
|
+
]));
|
|
279
|
+
const current = new Map(input.files.map((file) => [
|
|
280
|
+
`${file.target}:${normalizeModStudioPath(file.path)}`,
|
|
281
|
+
file,
|
|
282
|
+
]));
|
|
283
|
+
const upserts = input.files.filter((file) => {
|
|
284
|
+
const before = previous.get(`${file.target}:${normalizeModStudioPath(file.path)}`);
|
|
285
|
+
return !before || before.content !== file.content;
|
|
286
|
+
});
|
|
287
|
+
const deletes = baseline.files
|
|
288
|
+
.filter((file) => !current.has(`${file.target}:${normalizeModStudioPath(file.path)}`))
|
|
289
|
+
.map((file) => ({ target: file.target, path: file.path }));
|
|
290
|
+
return { upserts, deletes };
|
|
291
|
+
}
|
|
292
|
+
function cloneProject(project) {
|
|
293
|
+
return {
|
|
294
|
+
...project,
|
|
295
|
+
metadata: { ...project.metadata },
|
|
296
|
+
files: project.files.map((file) => ({ ...file })),
|
|
297
|
+
revision: { ...project.revision },
|
|
298
|
+
};
|
|
299
|
+
}
|
|
@@ -77,7 +77,7 @@ export declare class PlayerComputeAPI {
|
|
|
77
77
|
/**
|
|
78
78
|
* Fetch a client artifact and decode its bytes to an ArrayBuffer plus the
|
|
79
79
|
* broker inputs (content hash for side-load verification, per-dispatch fuel
|
|
80
|
-
* budget). Convenience over {@link artifact} for the
|
|
80
|
+
* budget). Convenience over {@link artifact} for the Mod Studio CLIENT
|
|
81
81
|
* deploy loop.
|
|
82
82
|
*/
|
|
83
83
|
artifactBytes(variables: PlayerComputeArtifactQueryVariables): Promise<{
|
|
@@ -116,7 +116,7 @@ export class PlayerComputeAPI {
|
|
|
116
116
|
/**
|
|
117
117
|
* Fetch a client artifact and decode its bytes to an ArrayBuffer plus the
|
|
118
118
|
* broker inputs (content hash for side-load verification, per-dispatch fuel
|
|
119
|
-
* budget). Convenience over {@link artifact} for the
|
|
119
|
+
* budget). Convenience over {@link artifact} for the Mod Studio CLIENT
|
|
120
120
|
* deploy loop.
|
|
121
121
|
*/
|
|
122
122
|
async artifactBytes(variables) {
|