@dcl/sdk-commands 7.1.4-4692707982.commit-108fa71 → 7.1.4
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.
@@ -114,24 +114,22 @@ async function main(options) {
|
|
114
114
|
if (workspace.projects.length > 1)
|
115
115
|
(0, beautiful_logs_1.printWarning)(options.components.logger, 'Support for multiple projects is still experimental.');
|
116
116
|
for (const project of workspace.projects) {
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
await (0, build_1.buildScene)({ ...options, args: { '--dir': project.workingDirectory, '--watch': false, _: [] } }, project);
|
126
|
-
}
|
127
|
-
// track the event
|
128
|
-
baseCoords = (0, scene_validations_1.getBaseCoords)(project.scene);
|
129
|
-
options.components.analytics.track('Preview started', {
|
130
|
-
projectHash: await (0, project_files_1.b64HashingFunction)(project.workingDirectory),
|
131
|
-
coords: baseCoords,
|
132
|
-
isWorkspace: false
|
133
|
-
});
|
117
|
+
(0, beautiful_logs_1.printCurrentProjectStarting)(options.components.logger, project, workspace);
|
118
|
+
// first run `npm run build`, this can be disabled with --skip-build
|
119
|
+
// then start the embedded compiler, this can be disabled with --no-watch
|
120
|
+
if (watch) {
|
121
|
+
await (0, build_1.buildScene)({ ...options, args: { '--dir': project.workingDirectory, '--watch': true, _: [] } }, project);
|
122
|
+
}
|
123
|
+
else if (!skipBuild) {
|
124
|
+
await (0, build_1.buildScene)({ ...options, args: { '--dir': project.workingDirectory, '--watch': false, _: [] } }, project);
|
134
125
|
}
|
126
|
+
// track the event
|
127
|
+
baseCoords = (0, scene_validations_1.getBaseCoords)(project.scene);
|
128
|
+
options.components.analytics.track('Preview started', {
|
129
|
+
projectHash: await (0, project_files_1.b64HashingFunction)(project.workingDirectory),
|
130
|
+
coords: baseCoords,
|
131
|
+
isWorkspace: false
|
132
|
+
});
|
135
133
|
}
|
136
134
|
(0, beautiful_logs_1.printProgressInfo)(options.components.logger, 'Starting preview server');
|
137
135
|
const port = await (0, get_free_port_1.getPort)(options.args['--port'] || 0);
|
@@ -36,11 +36,12 @@ function smartWearableNameToId(name) {
|
|
36
36
|
}
|
37
37
|
async function setupEcs6Endpoints(components, router, workspace) {
|
38
38
|
const catalystUrl = new URL(await (0, config_1.getCatalystBaseUrl)(components));
|
39
|
-
|
39
|
+
const baseFolders = workspace.projects.map(($) => $.workingDirectory);
|
40
|
+
// handle old preview scene.json
|
40
41
|
router.get('/scene.json', async () => {
|
41
42
|
return {
|
42
43
|
headers: { 'content-type': 'application/json' },
|
43
|
-
body: components.fs.createReadStream(path.join(
|
44
|
+
body: components.fs.createReadStream(path.join(baseFolders[0], 'scene.json'))
|
44
45
|
};
|
45
46
|
});
|
46
47
|
router.get('/lambdas/explore/realms', async (ctx) => {
|
@@ -71,7 +72,8 @@ async function setupEcs6Endpoints(components, router, workspace) {
|
|
71
72
|
router.get('/lambdas/profiles', async (ctx, next) => {
|
72
73
|
const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`;
|
73
74
|
try {
|
74
|
-
const previewWearables = await getAllPreviewWearables(components,
|
75
|
+
const previewWearables = await getAllPreviewWearables(components, {
|
76
|
+
baseFolders,
|
75
77
|
baseUrl
|
76
78
|
});
|
77
79
|
if (previewWearables.length === 1) {
|
@@ -134,43 +136,22 @@ async function setupEcs6Endpoints(components, router, workspace) {
|
|
134
136
|
});
|
135
137
|
serveStatic(components, workspace, router);
|
136
138
|
// TODO: get workspace scenes & wearables...
|
137
|
-
await serveFolders(components, router,
|
139
|
+
await serveFolders(components, router, baseFolders);
|
138
140
|
}
|
139
141
|
exports.setupEcs6Endpoints = setupEcs6Endpoints;
|
140
|
-
async function serveFolders(components, router,
|
142
|
+
async function serveFolders(components, router, baseFolders) {
|
141
143
|
const catalystUrl = await (0, config_1.getCatalystBaseUrl)(components);
|
142
144
|
router.get('/content/contents/:hash', async (ctx, next) => {
|
143
145
|
if (ctx.params.hash && ctx.params.hash.startsWith('b64-')) {
|
144
146
|
const fullPath = path.resolve(Buffer.from(ctx.params.hash.replace(/^b64-/, ''), 'base64').toString('utf8'));
|
145
|
-
// find a project that we are talking about. NOTE: this filter is not exhaustive
|
146
|
-
// relative paths should be used instead
|
147
|
-
const baseProject = workspace.projects.find((project) => fullPath.startsWith(project.workingDirectory));
|
148
147
|
// only return files IF the file is within a baseFolder
|
149
|
-
if (!
|
148
|
+
if (!baseFolders.find((folder) => fullPath.startsWith(folder))) {
|
150
149
|
return next();
|
151
150
|
}
|
152
|
-
if (path.resolve(fullPath) === path.resolve(baseProject.workingDirectory)) {
|
153
|
-
// if we are talking about the root directory, then we must return the json of the entity
|
154
|
-
const entity = await fakeEntityV3FromProject(components, baseProject, project_files_1.b64HashingFunction);
|
155
|
-
if (!entity)
|
156
|
-
return { status: 404 };
|
157
|
-
return {
|
158
|
-
headers: {
|
159
|
-
'x-timestamp': Date.now().toString(),
|
160
|
-
'x-sent': 'true',
|
161
|
-
'cache-control': 'no-cache,private,max-age=1'
|
162
|
-
},
|
163
|
-
body: entity
|
164
|
-
};
|
165
|
-
}
|
166
|
-
if (!(await components.fs.fileExists(fullPath)))
|
167
|
-
return { status: 404 };
|
168
|
-
if (await components.fs.directoryExists(fullPath))
|
169
|
-
return { status: 404 };
|
170
151
|
return {
|
171
152
|
headers: {
|
172
|
-
'x-timestamp': Date.now()
|
173
|
-
'x-sent':
|
153
|
+
'x-timestamp': Date.now(),
|
154
|
+
'x-sent': true,
|
174
155
|
'cache-control': 'no-cache,private,max-age=1'
|
175
156
|
},
|
176
157
|
body: components.fs.createReadStream(fullPath)
|
@@ -183,7 +164,7 @@ async function serveFolders(components, router, workspace) {
|
|
183
164
|
return [];
|
184
165
|
}
|
185
166
|
const requestedPointers = new Set(pointers && typeof pointers === 'string' ? [pointers] : pointers);
|
186
|
-
const resultEntities = await getSceneJson(components,
|
167
|
+
const resultEntities = await getSceneJson(components, baseFolders, Array.from(requestedPointers));
|
187
168
|
const remote = (0, catalyst_requests_1.fetchEntityByPointer)(components, catalystUrl.toString(), pointers.filter(($) => !$.match(/-?\d+,-?\d+/)));
|
188
169
|
const serverEntities = Array.isArray(remote) ? remote : [];
|
189
170
|
return [...resultEntities, ...serverEntities];
|
@@ -203,8 +184,9 @@ async function serveFolders(components, router, workspace) {
|
|
203
184
|
});
|
204
185
|
router.get('/preview-wearables/:id', async (ctx) => {
|
205
186
|
const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`;
|
206
|
-
const wearables = await getAllPreviewWearables(components,
|
207
|
-
baseUrl
|
187
|
+
const wearables = await getAllPreviewWearables(components, {
|
188
|
+
baseUrl,
|
189
|
+
baseFolders
|
208
190
|
});
|
209
191
|
const wearableId = ctx.params.id;
|
210
192
|
return {
|
@@ -219,44 +201,40 @@ async function serveFolders(components, router, workspace) {
|
|
219
201
|
return {
|
220
202
|
body: {
|
221
203
|
ok: true,
|
222
|
-
data: await getAllPreviewWearables(components,
|
204
|
+
data: await getAllPreviewWearables(components, { baseUrl, baseFolders })
|
223
205
|
}
|
224
206
|
};
|
225
207
|
});
|
226
208
|
}
|
227
|
-
async function getAllPreviewWearables(components,
|
228
|
-
// NOTE: the explorers should use the /entities/active endpoint to retrieve the wearables. This endpoint should be removed
|
209
|
+
async function getAllPreviewWearables(components, { baseFolders, baseUrl }) {
|
229
210
|
const wearablePathArray = [];
|
230
|
-
for (const
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
wearablePathArray.push(wearableJsonPath);
|
235
|
-
}
|
211
|
+
for (const wearableDir of baseFolders) {
|
212
|
+
const wearableJsonPath = path.resolve(wearableDir, 'wearable.json');
|
213
|
+
if (await components.fs.fileExists(wearableJsonPath)) {
|
214
|
+
wearablePathArray.push(wearableJsonPath);
|
236
215
|
}
|
237
216
|
}
|
238
217
|
const ret = [];
|
239
|
-
for (const
|
218
|
+
for (const wearableJsonPath of wearablePathArray) {
|
240
219
|
try {
|
241
|
-
|
242
|
-
ret.push(await serveWearable(components, project, baseUrl));
|
220
|
+
ret.push(await serveWearable(components, wearableJsonPath, baseUrl));
|
243
221
|
}
|
244
222
|
catch (err) {
|
245
|
-
components.logger.error(`Couldn't mock the wearable ${
|
223
|
+
components.logger.error(`Couldn't mock the wearable ${wearableJsonPath}. Please verify the correct format and scheme.` + err);
|
246
224
|
}
|
247
225
|
}
|
248
226
|
return ret;
|
249
227
|
}
|
250
|
-
async function serveWearable(components,
|
251
|
-
const
|
228
|
+
async function serveWearable(components, wearableJsonPath, baseUrl) {
|
229
|
+
const wearableDir = path.dirname(wearableJsonPath);
|
252
230
|
const wearableJson = JSON.parse((await components.fs.readFile(wearableJsonPath)).toString());
|
253
231
|
if (!sdk_1.WearableJson.validate(wearableJson)) {
|
254
232
|
const errors = (sdk_1.WearableJson.validate.errors || []).map((a) => `${a.data} ${a.message}`).join('');
|
255
233
|
components.logger.error(`Unable to validate wearable.json properly, please check it.` + errors);
|
256
234
|
throw new Error(`Invalid wearable.json (${wearableJsonPath})`);
|
257
235
|
}
|
258
|
-
const projectFiles = await (0, project_files_1.getProjectPublishableFilesWithHashes)(components,
|
259
|
-
const contentFiles = (0, project_files_1.projectFilesToContentMappings)(
|
236
|
+
const projectFiles = await (0, project_files_1.getProjectPublishableFilesWithHashes)(components, wearableDir, project_files_1.b64HashingFunction);
|
237
|
+
const contentFiles = (0, project_files_1.projectFilesToContentMappings)(wearableDir, projectFiles);
|
260
238
|
const thumbnailFiltered = contentFiles.filter(($) => $.file === 'thumbnail.png');
|
261
239
|
const thumbnail = thumbnailFiltered.length > 0 && thumbnailFiltered[0].hash && `${baseUrl}/${thumbnailFiltered[0].hash}`;
|
262
240
|
const wearableId = 'urn:8dc2d7ad-97e3-44d0-ba89-e8305d795a6a';
|
@@ -289,10 +267,10 @@ async function serveWearable(components, project, baseUrl) {
|
|
289
267
|
}
|
290
268
|
};
|
291
269
|
}
|
292
|
-
async function getSceneJson(components,
|
270
|
+
async function getSceneJson(components, projectRoots, pointers) {
|
293
271
|
const requestedPointers = new Set(pointers);
|
294
272
|
const resultEntities = [];
|
295
|
-
const allDeployments = await Promise.all(
|
273
|
+
const allDeployments = await Promise.all(projectRoots.map(async (projectRoot) => fakeEntityV3FromFolder(components, projectRoot, project_files_1.b64HashingFunction)));
|
296
274
|
for (const pointer of Array.from(requestedPointers)) {
|
297
275
|
// get deployment by pointer
|
298
276
|
const theDeployment = allDeployments.find(($) => $ && $.pointers.includes(pointer));
|
@@ -348,9 +326,6 @@ function serveStatic(components, workspace, router) {
|
|
348
326
|
if (!(await components.fs.fileExists(fullPath))) {
|
349
327
|
return next();
|
350
328
|
}
|
351
|
-
if (await components.fs.directoryExists(fullPath)) {
|
352
|
-
return { status: 404 };
|
353
|
-
}
|
354
329
|
const headers = {
|
355
330
|
'x-timestamp': Date.now(),
|
356
331
|
'x-sent': true,
|
@@ -379,49 +354,44 @@ function serveStatic(components, workspace, router) {
|
|
379
354
|
};
|
380
355
|
});
|
381
356
|
}
|
382
|
-
async function
|
383
|
-
const
|
384
|
-
|
385
|
-
|
386
|
-
|
357
|
+
async function fakeEntityV3FromFolder(components, projectRoot, hashingFunction) {
|
358
|
+
const sceneJsonPath = path.resolve(projectRoot, 'scene.json');
|
359
|
+
let isParcelScene = true;
|
360
|
+
const wearableJsonPath = path.resolve(projectRoot, 'wearable.json');
|
361
|
+
if (await components.fs.fileExists(wearableJsonPath)) {
|
362
|
+
try {
|
363
|
+
const wearableJson = JSON.parse(await components.fs.readFile(wearableJsonPath, 'utf-8'));
|
364
|
+
if (!sdk_1.WearableJson.validate(wearableJson)) {
|
365
|
+
const errors = (sdk_1.WearableJson.validate.errors || []).map((a) => `${a.data} ${a.message}`).join('');
|
366
|
+
components.logger.error(`Unable to validate wearable.json properly, please check its schema.` + errors);
|
367
|
+
components.logger.error(`Invalid wearable.json (${wearableJsonPath})`);
|
368
|
+
}
|
369
|
+
else {
|
370
|
+
isParcelScene = false;
|
371
|
+
}
|
372
|
+
}
|
373
|
+
catch (err) {
|
374
|
+
components.logger.error(`Unable to load wearable.json`);
|
375
|
+
components.logger.error(err);
|
376
|
+
}
|
377
|
+
}
|
378
|
+
if ((await components.fs.fileExists(sceneJsonPath)) && isParcelScene) {
|
387
379
|
const sceneJson = JSON.parse(await components.fs.readFile(sceneJsonPath, 'utf-8'));
|
388
380
|
const { base, parcels } = sceneJson.scene;
|
389
381
|
const pointers = new Set();
|
390
382
|
pointers.add(base);
|
391
383
|
parcels.forEach(($) => pointers.add($));
|
384
|
+
const projectFiles = await (0, project_files_1.getProjectPublishableFilesWithHashes)(components, projectRoot, hashingFunction);
|
385
|
+
const contentFiles = (0, project_files_1.projectFilesToContentMappings)(projectRoot, projectFiles);
|
392
386
|
return {
|
393
387
|
version: 'v3',
|
394
388
|
type: schemas_1.EntityType.SCENE,
|
395
|
-
id: await hashingFunction(
|
389
|
+
id: await hashingFunction(projectRoot),
|
396
390
|
pointers: Array.from(pointers),
|
397
391
|
timestamp: Date.now(),
|
398
392
|
metadata: sceneJson,
|
399
393
|
content: contentFiles
|
400
394
|
};
|
401
395
|
}
|
402
|
-
else if (project.kind === 'wearable') {
|
403
|
-
const wearableJsonPath = path.resolve(project.workingDirectory, 'wearable.json');
|
404
|
-
try {
|
405
|
-
const wearableJson = JSON.parse(await components.fs.readFile(wearableJsonPath, 'utf-8'));
|
406
|
-
if (!sdk_1.WearableJson.validate(wearableJson)) {
|
407
|
-
const errors = (sdk_1.WearableJson.validate.errors || []).map((a) => `${a.data} ${a.message}`).join('');
|
408
|
-
components.logger.error(`Unable to validate wearable.json properly, please check its schema.` + errors);
|
409
|
-
components.logger.error(`Invalid wearable.json (${wearableJsonPath})`);
|
410
|
-
}
|
411
|
-
return {
|
412
|
-
version: 'v3',
|
413
|
-
type: schemas_1.EntityType.WEARABLE,
|
414
|
-
id: await hashingFunction(project.workingDirectory),
|
415
|
-
pointers: Array.from([await hashingFunction(project.workingDirectory)]),
|
416
|
-
timestamp: Date.now(),
|
417
|
-
metadata: wearableJson,
|
418
|
-
content: contentFiles
|
419
|
-
};
|
420
|
-
}
|
421
|
-
catch (err) {
|
422
|
-
components.logger.error(`Unable to load wearable.json`);
|
423
|
-
components.logger.error(err);
|
424
|
-
}
|
425
|
-
}
|
426
396
|
return null;
|
427
397
|
}
|
@@ -7,11 +7,7 @@ export type SceneProject = {
|
|
7
7
|
kind: 'scene';
|
8
8
|
scene: Scene;
|
9
9
|
} & BaseProject;
|
10
|
-
export type
|
11
|
-
kind: 'wearable';
|
12
|
-
wearable: any;
|
13
|
-
} & BaseProject;
|
14
|
-
export type ProjectUnion = SceneProject | WearableProject;
|
10
|
+
export type ProjectUnion = SceneProject;
|
15
11
|
/**
|
16
12
|
* Asserts that the workingDirectory is a valid project
|
17
13
|
*/
|
package/package.json
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
{
|
2
2
|
"name": "@dcl/sdk-commands",
|
3
3
|
"description": "",
|
4
|
-
"version": "7.1.4
|
4
|
+
"version": "7.1.4",
|
5
5
|
"author": "Decentraland",
|
6
6
|
"bin": {
|
7
7
|
"sdk-commands": "./dist/index.js"
|
8
8
|
},
|
9
9
|
"dependencies": {
|
10
10
|
"@dcl/hashing": "1.1.3",
|
11
|
-
"@dcl/inspector": "7.1.4
|
11
|
+
"@dcl/inspector": "7.1.4",
|
12
12
|
"@dcl/linker-dapp": "0.7.0",
|
13
13
|
"@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be",
|
14
14
|
"@dcl/protocol": "1.0.0-4671230683.commit-a8d74c3",
|
@@ -60,5 +60,5 @@
|
|
60
60
|
"displayName": "SDK",
|
61
61
|
"tsconfig": "./tsconfig.json"
|
62
62
|
},
|
63
|
-
"commit": "
|
63
|
+
"commit": "3f2952c5e02d012a18b91605485925bc3dd6f756"
|
64
64
|
}
|