@dcl/sdk-commands 7.1.4 → 7.1.5-4704298040.commit-f6a337a

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,22 +114,24 @@ 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
- (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);
117
+ if (project.kind === 'scene') {
118
+ (0, beautiful_logs_1.printCurrentProjectStarting)(options.components.logger, project, workspace);
119
+ // first run `npm run build`, this can be disabled with --skip-build
120
+ // then start the embedded compiler, this can be disabled with --no-watch
121
+ if (watch) {
122
+ await (0, build_1.buildScene)({ ...options, args: { '--dir': project.workingDirectory, '--watch': true, _: [] } }, project);
123
+ }
124
+ else if (!skipBuild) {
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
+ });
125
134
  }
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
- });
133
135
  }
134
136
  (0, beautiful_logs_1.printProgressInfo)(options.components.logger, 'Starting preview server');
135
137
  const port = await (0, get_free_port_1.getPort)(options.args['--port'] || 0);
@@ -36,12 +36,11 @@ 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
- const baseFolders = workspace.projects.map(($) => $.workingDirectory);
40
- // handle old preview scene.json
39
+ // handle old preview scene.json DEPRECATED
41
40
  router.get('/scene.json', async () => {
42
41
  return {
43
42
  headers: { 'content-type': 'application/json' },
44
- body: components.fs.createReadStream(path.join(baseFolders[0], 'scene.json'))
43
+ body: components.fs.createReadStream(path.join(workspace.projects[0].workingDirectory, 'scene.json'))
45
44
  };
46
45
  });
47
46
  router.get('/lambdas/explore/realms', async (ctx) => {
@@ -72,8 +71,7 @@ async function setupEcs6Endpoints(components, router, workspace) {
72
71
  router.get('/lambdas/profiles', async (ctx, next) => {
73
72
  const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`;
74
73
  try {
75
- const previewWearables = await getAllPreviewWearables(components, {
76
- baseFolders,
74
+ const previewWearables = await getAllPreviewWearables(components, workspace, {
77
75
  baseUrl
78
76
  });
79
77
  if (previewWearables.length === 1) {
@@ -136,22 +134,43 @@ async function setupEcs6Endpoints(components, router, workspace) {
136
134
  });
137
135
  serveStatic(components, workspace, router);
138
136
  // TODO: get workspace scenes & wearables...
139
- await serveFolders(components, router, baseFolders);
137
+ await serveFolders(components, router, workspace);
140
138
  }
141
139
  exports.setupEcs6Endpoints = setupEcs6Endpoints;
142
- async function serveFolders(components, router, baseFolders) {
140
+ async function serveFolders(components, router, workspace) {
143
141
  const catalystUrl = await (0, config_1.getCatalystBaseUrl)(components);
144
142
  router.get('/content/contents/:hash', async (ctx, next) => {
145
143
  if (ctx.params.hash && ctx.params.hash.startsWith('b64-')) {
146
144
  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));
147
148
  // only return files IF the file is within a baseFolder
148
- if (!baseFolders.find((folder) => fullPath.startsWith(folder))) {
149
+ if (!baseProject) {
149
150
  return next();
150
151
  }
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 };
151
170
  return {
152
171
  headers: {
153
- 'x-timestamp': Date.now(),
154
- 'x-sent': true,
172
+ 'x-timestamp': Date.now().toString(),
173
+ 'x-sent': 'true',
155
174
  'cache-control': 'no-cache,private,max-age=1'
156
175
  },
157
176
  body: components.fs.createReadStream(fullPath)
@@ -164,7 +183,7 @@ async function serveFolders(components, router, baseFolders) {
164
183
  return [];
165
184
  }
166
185
  const requestedPointers = new Set(pointers && typeof pointers === 'string' ? [pointers] : pointers);
167
- const resultEntities = await getSceneJson(components, baseFolders, Array.from(requestedPointers));
186
+ const resultEntities = await getSceneJson(components, workspace, Array.from(requestedPointers));
168
187
  const remote = (0, catalyst_requests_1.fetchEntityByPointer)(components, catalystUrl.toString(), pointers.filter(($) => !$.match(/-?\d+,-?\d+/)));
169
188
  const serverEntities = Array.isArray(remote) ? remote : [];
170
189
  return [...resultEntities, ...serverEntities];
@@ -184,9 +203,8 @@ async function serveFolders(components, router, baseFolders) {
184
203
  });
185
204
  router.get('/preview-wearables/:id', async (ctx) => {
186
205
  const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`;
187
- const wearables = await getAllPreviewWearables(components, {
188
- baseUrl,
189
- baseFolders
206
+ const wearables = await getAllPreviewWearables(components, workspace, {
207
+ baseUrl
190
208
  });
191
209
  const wearableId = ctx.params.id;
192
210
  return {
@@ -201,40 +219,44 @@ async function serveFolders(components, router, baseFolders) {
201
219
  return {
202
220
  body: {
203
221
  ok: true,
204
- data: await getAllPreviewWearables(components, { baseUrl, baseFolders })
222
+ data: await getAllPreviewWearables(components, workspace, { baseUrl })
205
223
  }
206
224
  };
207
225
  });
208
226
  }
209
- async function getAllPreviewWearables(components, { baseFolders, baseUrl }) {
227
+ async function getAllPreviewWearables(components, workspace, { baseUrl }) {
228
+ // NOTE: the explorers should use the /entities/active endpoint to retrieve the wearables. This endpoint should be removed
210
229
  const wearablePathArray = [];
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);
230
+ for (const project of workspace.projects) {
231
+ if (project.kind === 'wearable') {
232
+ const wearableJsonPath = path.resolve(project.workingDirectory, 'wearable.json');
233
+ if (await components.fs.fileExists(wearableJsonPath)) {
234
+ wearablePathArray.push(wearableJsonPath);
235
+ }
215
236
  }
216
237
  }
217
238
  const ret = [];
218
- for (const wearableJsonPath of wearablePathArray) {
239
+ for (const project of workspace.projects) {
219
240
  try {
220
- ret.push(await serveWearable(components, wearableJsonPath, baseUrl));
241
+ if (project.kind === 'wearable')
242
+ ret.push(await serveWearable(components, project, baseUrl));
221
243
  }
222
244
  catch (err) {
223
- components.logger.error(`Couldn't mock the wearable ${wearableJsonPath}. Please verify the correct format and scheme.` + err);
245
+ components.logger.error(`Couldn't mock the wearable ${project.workingDirectory}. Please verify the correct format and scheme.` + err);
224
246
  }
225
247
  }
226
248
  return ret;
227
249
  }
228
- async function serveWearable(components, wearableJsonPath, baseUrl) {
229
- const wearableDir = path.dirname(wearableJsonPath);
250
+ async function serveWearable(components, project, baseUrl) {
251
+ const wearableJsonPath = path.join(project.workingDirectory, 'wearable.json');
230
252
  const wearableJson = JSON.parse((await components.fs.readFile(wearableJsonPath)).toString());
231
253
  if (!sdk_1.WearableJson.validate(wearableJson)) {
232
254
  const errors = (sdk_1.WearableJson.validate.errors || []).map((a) => `${a.data} ${a.message}`).join('');
233
255
  components.logger.error(`Unable to validate wearable.json properly, please check it.` + errors);
234
256
  throw new Error(`Invalid wearable.json (${wearableJsonPath})`);
235
257
  }
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);
258
+ const projectFiles = await (0, project_files_1.getProjectPublishableFilesWithHashes)(components, project.workingDirectory, project_files_1.b64HashingFunction);
259
+ const contentFiles = (0, project_files_1.projectFilesToContentMappings)(project.workingDirectory, projectFiles);
238
260
  const thumbnailFiltered = contentFiles.filter(($) => $.file === 'thumbnail.png');
239
261
  const thumbnail = thumbnailFiltered.length > 0 && thumbnailFiltered[0].hash && `${baseUrl}/${thumbnailFiltered[0].hash}`;
240
262
  const wearableId = 'urn:8dc2d7ad-97e3-44d0-ba89-e8305d795a6a';
@@ -267,10 +289,10 @@ async function serveWearable(components, wearableJsonPath, baseUrl) {
267
289
  }
268
290
  };
269
291
  }
270
- async function getSceneJson(components, projectRoots, pointers) {
292
+ async function getSceneJson(components, workspace, pointers) {
271
293
  const requestedPointers = new Set(pointers);
272
294
  const resultEntities = [];
273
- const allDeployments = await Promise.all(projectRoots.map(async (projectRoot) => fakeEntityV3FromFolder(components, projectRoot, project_files_1.b64HashingFunction)));
295
+ const allDeployments = await Promise.all(workspace.projects.map((project) => fakeEntityV3FromProject(components, project, project_files_1.b64HashingFunction)));
274
296
  for (const pointer of Array.from(requestedPointers)) {
275
297
  // get deployment by pointer
276
298
  const theDeployment = allDeployments.find(($) => $ && $.pointers.includes(pointer));
@@ -326,6 +348,9 @@ function serveStatic(components, workspace, router) {
326
348
  if (!(await components.fs.fileExists(fullPath))) {
327
349
  return next();
328
350
  }
351
+ if (await components.fs.directoryExists(fullPath)) {
352
+ return { status: 404 };
353
+ }
329
354
  const headers = {
330
355
  'x-timestamp': Date.now(),
331
356
  'x-sent': true,
@@ -354,44 +379,49 @@ function serveStatic(components, workspace, router) {
354
379
  };
355
380
  });
356
381
  }
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) {
382
+ async function fakeEntityV3FromProject(components, project, hashingFunction) {
383
+ const projectFiles = await (0, project_files_1.getProjectPublishableFilesWithHashes)(components, project.workingDirectory, hashingFunction);
384
+ const contentFiles = (0, project_files_1.projectFilesToContentMappings)(project.workingDirectory, projectFiles);
385
+ if (project.kind === 'scene') {
386
+ const sceneJsonPath = path.resolve(project.workingDirectory, 'scene.json');
379
387
  const sceneJson = JSON.parse(await components.fs.readFile(sceneJsonPath, 'utf-8'));
380
388
  const { base, parcels } = sceneJson.scene;
381
389
  const pointers = new Set();
382
390
  pointers.add(base);
383
391
  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);
386
392
  return {
387
393
  version: 'v3',
388
394
  type: schemas_1.EntityType.SCENE,
389
- id: await hashingFunction(projectRoot),
395
+ id: await hashingFunction(project.workingDirectory),
390
396
  pointers: Array.from(pointers),
391
397
  timestamp: Date.now(),
392
398
  metadata: sceneJson,
393
399
  content: contentFiles
394
400
  };
395
401
  }
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
+ }
396
426
  return null;
397
427
  }
@@ -7,7 +7,11 @@ export type SceneProject = {
7
7
  kind: 'scene';
8
8
  scene: Scene;
9
9
  } & BaseProject;
10
- export type ProjectUnion = SceneProject;
10
+ export type WearableProject = {
11
+ kind: 'wearable';
12
+ wearable: any;
13
+ } & BaseProject;
14
+ export type ProjectUnion = SceneProject | WearableProject;
11
15
  /**
12
16
  * Asserts that the workingDirectory is a valid project
13
17
  */
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.5-4704298040.commit-f6a337a",
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.5-4704298040.commit-f6a337a",
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": "3f2952c5e02d012a18b91605485925bc3dd6f756"
63
+ "commit": "f6a337a9f93f7738174df9448d5a735ebc9468a1"
64
64
  }