@dcl/sdk 7.0.6-4006744889.commit-c6aff5f → 7.0.6-4009020955.commit-08722f5
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/cli/commands/build/helpers.d.ts +25 -0
- package/cli/commands/build/helpers.js +50 -0
- package/cli/commands/build/helpers.ts +95 -0
- package/cli/commands/build/index.d.ts +19 -0
- package/cli/commands/build/index.js +64 -0
- package/cli/commands/build/index.ts +91 -0
- package/cli/commands/init/index.d.ts +1 -1
- package/cli/commands/init/index.js +8 -14
- package/cli/commands/init/index.ts +8 -18
- package/cli/commands/init/repos.js +1 -1
- package/cli/commands/init/repos.ts +1 -2
- package/cli/commands/preview/bff.d.ts +3 -0
- package/cli/commands/preview/bff.js +50 -0
- package/cli/commands/preview/bff.ts +59 -0
- package/cli/commands/preview/catalyst.d.ts +5 -0
- package/cli/commands/preview/catalyst.js +24 -0
- package/cli/commands/preview/catalyst.ts +31 -0
- package/cli/commands/preview/coordinates.d.ts +20 -0
- package/cli/commands/preview/coordinates.js +90 -0
- package/cli/commands/preview/coordinates.ts +146 -0
- package/cli/commands/preview/endpoints.d.ts +10 -0
- package/cli/commands/preview/endpoints.js +500 -0
- package/cli/commands/preview/endpoints.ts +594 -0
- package/cli/commands/preview/eth.d.ts +2 -0
- package/cli/commands/preview/eth.js +6 -0
- package/cli/commands/preview/eth.ts +3 -0
- package/cli/commands/preview/index.d.ts +18 -0
- package/cli/commands/preview/index.js +75 -0
- package/cli/commands/preview/index.ts +88 -0
- package/cli/commands/preview/port.d.ts +1 -0
- package/cli/commands/preview/port.js +21 -0
- package/cli/commands/preview/port.ts +15 -0
- package/cli/commands/preview/project.d.ts +14 -0
- package/cli/commands/preview/project.js +77 -0
- package/cli/commands/preview/project.ts +112 -0
- package/cli/commands/preview/types.d.ts +13 -0
- package/cli/commands/preview/types.js +3 -0
- package/cli/commands/preview/types.ts +19 -0
- package/cli/commands/preview/wire.d.ts +14 -0
- package/cli/commands/preview/wire.js +28 -0
- package/cli/commands/preview/wire.ts +48 -0
- package/cli/commands/preview/ws.d.ts +7 -0
- package/cli/commands/preview/ws.js +16 -0
- package/cli/commands/preview/ws.ts +24 -0
- package/cli/commands/start/index.d.ts +29 -0
- package/cli/commands/start/index.js +121 -0
- package/cli/commands/start/index.ts +132 -0
- package/cli/components/fs.d.ts +2 -1
- package/cli/components/fs.js +1 -1
- package/cli/components/fs.ts +2 -11
- package/cli/index.js +4 -6
- package/cli/index.ts +9 -10
- package/cli/utils/args.js +2 -2
- package/cli/utils/args.ts +2 -8
- package/cli/utils/commands.js +2 -2
- package/cli/utils/commands.ts +3 -7
- package/cli/utils/exec.d.ts +8 -0
- package/cli/utils/exec.js +33 -0
- package/cli/utils/exec.ts +38 -0
- package/cli/utils/fs.js +1 -1
- package/cli/utils/fs.ts +1 -4
- package/cli/utils/handler.d.ts +6 -0
- package/cli/utils/handler.js +19 -0
- package/cli/utils/handler.ts +23 -0
- package/cli/utils/object.d.ts +9 -0
- package/cli/utils/object.js +45 -0
- package/cli/utils/object.ts +62 -0
- package/cli/utils/out-messages.d.ts +1 -0
- package/cli/utils/out-messages.js +8 -0
- package/cli/utils/out-messages.ts +3 -0
- package/internal/Observable.js +3 -7
- package/internal/provider.js +1 -1
- package/internal/transports/rendererTransport.js +2 -3
- package/messageBus.js +1 -1
- package/observables.js +1 -1
- package/package.json +18 -7
- package/src/internal/Observable.ts +9 -44
- package/src/internal/provider.ts +3 -11
- package/src/internal/transports/rendererTransport.ts +4 -12
- package/src/messageBus.ts +1 -4
- package/src/observables.ts +27 -63
- package/tsconfig.cli.json +10 -1
- package/cli/utils/spinner.d.ts +0 -15
- package/cli/utils/spinner.js +0 -41
- package/cli/utils/spinner.ts +0 -44
@@ -0,0 +1,594 @@
|
|
1
|
+
import { Router } from '@well-known-components/http-server'
|
2
|
+
import { PreviewComponents } from './types'
|
3
|
+
import * as path from 'path'
|
4
|
+
import * as fs from 'fs'
|
5
|
+
import { sync as globSync } from 'glob'
|
6
|
+
import { WearableJson } from '@dcl/schemas/dist/sdk'
|
7
|
+
import { ContentMapping, Entity, EntityType } from '@dcl/schemas'
|
8
|
+
import ignore from 'ignore'
|
9
|
+
import fetch, { Headers } from 'node-fetch'
|
10
|
+
import { fetchEntityByPointer } from './catalyst'
|
11
|
+
|
12
|
+
function getCatalystUrl(): URL {
|
13
|
+
return new URL('https://peer.decentraland.org')
|
14
|
+
}
|
15
|
+
|
16
|
+
function smartWearableNameToId(name: string) {
|
17
|
+
return name.toLocaleLowerCase().replace(/ /g, '-')
|
18
|
+
}
|
19
|
+
|
20
|
+
export function setupEcs6Endpoints(dir: string, router: Router<PreviewComponents>) {
|
21
|
+
const baseFolders = [dir]
|
22
|
+
// handle old preview scene.json
|
23
|
+
router.get('/scene.json', async () => {
|
24
|
+
return {
|
25
|
+
headers: { 'content-type': 'application/json' },
|
26
|
+
body: fs.createReadStream(path.join(dir, 'scene.json'))
|
27
|
+
}
|
28
|
+
})
|
29
|
+
|
30
|
+
router.get('/lambdas/explore/realms', async (ctx) => {
|
31
|
+
return {
|
32
|
+
body: [
|
33
|
+
{
|
34
|
+
serverName: 'localhost',
|
35
|
+
url: `http://${ctx.url.host}`,
|
36
|
+
layer: 'stub',
|
37
|
+
usersCount: 0,
|
38
|
+
maxUsers: 100,
|
39
|
+
userParcels: []
|
40
|
+
}
|
41
|
+
]
|
42
|
+
}
|
43
|
+
})
|
44
|
+
|
45
|
+
router.get('/lambdas/contracts/servers', async (ctx) => {
|
46
|
+
return {
|
47
|
+
body: [
|
48
|
+
{
|
49
|
+
address: `http://${ctx.url.host}`,
|
50
|
+
owner: '0x0000000000000000000000000000000000000000',
|
51
|
+
id: '0x0000000000000000000000000000000000000000000000000000000000000000'
|
52
|
+
}
|
53
|
+
]
|
54
|
+
}
|
55
|
+
})
|
56
|
+
|
57
|
+
router.get('/lambdas/profiles', async (ctx, next) => {
|
58
|
+
const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`
|
59
|
+
|
60
|
+
try {
|
61
|
+
const previewWearables = getAllPreviewWearables({
|
62
|
+
baseFolders,
|
63
|
+
baseUrl
|
64
|
+
}).map((wearable) => wearable.id)
|
65
|
+
|
66
|
+
if (previewWearables.length === 1) {
|
67
|
+
const catalystUrl = getCatalystUrl()
|
68
|
+
|
69
|
+
const u = new URL(ctx.url.toString())
|
70
|
+
u.host = catalystUrl.host
|
71
|
+
u.protocol = catalystUrl.protocol
|
72
|
+
u.port = catalystUrl.port
|
73
|
+
const req = await fetch(u.toString(), {
|
74
|
+
headers: {
|
75
|
+
connection: 'close'
|
76
|
+
},
|
77
|
+
method: ctx.request.method,
|
78
|
+
body: ctx.request.method === 'get' ? undefined : ctx.request.body
|
79
|
+
})
|
80
|
+
|
81
|
+
const deployedProfile = (await req.json()) as any[]
|
82
|
+
|
83
|
+
if (deployedProfile?.length === 1) {
|
84
|
+
deployedProfile[0].avatars[0].avatar.wearables.push(...previewWearables)
|
85
|
+
return {
|
86
|
+
headers: {
|
87
|
+
'content-type': req.headers.get('content-type') || 'application/binary'
|
88
|
+
},
|
89
|
+
body: deployedProfile
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
} catch (err) {
|
94
|
+
console.warn(`Failed to catch profile and fill with preview wearables.`, err)
|
95
|
+
}
|
96
|
+
|
97
|
+
return next()
|
98
|
+
})
|
99
|
+
|
100
|
+
router.all('/lambdas/:path+', async (ctx) => {
|
101
|
+
const catalystUrl = getCatalystUrl()
|
102
|
+
const u = new URL(ctx.url.toString())
|
103
|
+
u.host = catalystUrl.host
|
104
|
+
u.protocol = catalystUrl.protocol
|
105
|
+
u.port = catalystUrl.port
|
106
|
+
const req = await fetch(u.toString(), {
|
107
|
+
headers: {
|
108
|
+
connection: 'close'
|
109
|
+
},
|
110
|
+
method: ctx.request.method,
|
111
|
+
body: ctx.request.method === 'get' ? undefined : ctx.request.body
|
112
|
+
})
|
113
|
+
|
114
|
+
return {
|
115
|
+
headers: {
|
116
|
+
'content-type': req.headers.get('content-type') || 'application/binary'
|
117
|
+
},
|
118
|
+
body: req.body
|
119
|
+
}
|
120
|
+
})
|
121
|
+
|
122
|
+
router.post('/content/entities', async (ctx) => {
|
123
|
+
const catalystUrl = getCatalystUrl()
|
124
|
+
const headers = new Headers()
|
125
|
+
console.log(ctx.request.headers)
|
126
|
+
const res = await fetch(`${catalystUrl.toString()}/content/entities`, {
|
127
|
+
method: 'post',
|
128
|
+
headers,
|
129
|
+
body: ctx.request.body
|
130
|
+
})
|
131
|
+
|
132
|
+
return res
|
133
|
+
})
|
134
|
+
|
135
|
+
serveStatic(dir, router)
|
136
|
+
|
137
|
+
// TODO: get workspace scenes & wearables...
|
138
|
+
|
139
|
+
serveFolders(router, baseFolders)
|
140
|
+
}
|
141
|
+
|
142
|
+
function serveFolders(router: Router<PreviewComponents>, baseFolders: string[]) {
|
143
|
+
router.get('/content/contents/:hash', async (ctx: any, next: any) => {
|
144
|
+
if (ctx.params.hash && ctx.params.hash.startsWith('b64-')) {
|
145
|
+
const fullPath = path.resolve(Buffer.from(ctx.params.hash.replace(/^b64-/, ''), 'base64').toString('utf8'))
|
146
|
+
|
147
|
+
// only return files IF the file is within a baseFolder
|
148
|
+
if (!baseFolders.find((folder: string) => fullPath.startsWith(folder))) {
|
149
|
+
return next()
|
150
|
+
}
|
151
|
+
|
152
|
+
return {
|
153
|
+
headers: {
|
154
|
+
'x-timestamp': Date.now(),
|
155
|
+
'x-sent': true,
|
156
|
+
'cache-control': 'no-cache,private,max-age=1'
|
157
|
+
},
|
158
|
+
body: fs.createReadStream(fullPath)
|
159
|
+
}
|
160
|
+
}
|
161
|
+
|
162
|
+
return next()
|
163
|
+
})
|
164
|
+
|
165
|
+
async function pointerRequestHandler(pointers: string[]) {
|
166
|
+
if (!pointers || pointers.length === 0) {
|
167
|
+
return []
|
168
|
+
}
|
169
|
+
|
170
|
+
const requestedPointers = new Set<string>(
|
171
|
+
pointers && typeof pointers === 'string' ? [pointers as string] : (pointers as string[])
|
172
|
+
)
|
173
|
+
|
174
|
+
const resultEntities = getSceneJson({
|
175
|
+
baseFolders,
|
176
|
+
pointers: Array.from(requestedPointers)
|
177
|
+
})
|
178
|
+
const catalystUrl = getCatalystUrl()
|
179
|
+
const remote = fetchEntityByPointer(
|
180
|
+
catalystUrl.toString(),
|
181
|
+
pointers.filter(($: string) => !$.match(/-?\d+,-?\d+/))
|
182
|
+
)
|
183
|
+
|
184
|
+
const serverEntities = Array.isArray(remote) ? remote : []
|
185
|
+
|
186
|
+
return [...resultEntities, ...serverEntities]
|
187
|
+
}
|
188
|
+
|
189
|
+
// REVIEW RESPONSE FORMAT
|
190
|
+
router.get('/content/entities/scene', async (ctx) => {
|
191
|
+
return {
|
192
|
+
body: await pointerRequestHandler(ctx.url.searchParams.getAll('pointer'))
|
193
|
+
}
|
194
|
+
})
|
195
|
+
|
196
|
+
// REVIEW RESPONSE FORMAT
|
197
|
+
router.post('/content/entities/active', async (ctx) => {
|
198
|
+
const body = await ctx.request.json()
|
199
|
+
return {
|
200
|
+
body: await pointerRequestHandler(body.pointers)
|
201
|
+
}
|
202
|
+
})
|
203
|
+
|
204
|
+
router.get('/preview-wearables/:id', async (ctx) => {
|
205
|
+
const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`
|
206
|
+
const wearables = getAllPreviewWearables({
|
207
|
+
baseUrl,
|
208
|
+
baseFolders
|
209
|
+
})
|
210
|
+
const wearableId = ctx.params.id
|
211
|
+
return {
|
212
|
+
body: {
|
213
|
+
ok: true,
|
214
|
+
data: wearables.filter((wearable) => smartWearableNameToId(wearable?.name) === wearableId)
|
215
|
+
}
|
216
|
+
}
|
217
|
+
})
|
218
|
+
|
219
|
+
router.get('/preview-wearables', async (ctx) => {
|
220
|
+
const baseUrl = `${ctx.url.protocol}//${ctx.url.host}/content/contents`
|
221
|
+
return {
|
222
|
+
body: {
|
223
|
+
ok: true,
|
224
|
+
data: getAllPreviewWearables({ baseUrl, baseFolders })
|
225
|
+
}
|
226
|
+
}
|
227
|
+
})
|
228
|
+
}
|
229
|
+
|
230
|
+
const defaultHashMaker = (str: string) => 'b64-' + Buffer.from(str).toString('base64')
|
231
|
+
|
232
|
+
function getAllPreviewWearables({ baseFolders, baseUrl }: { baseFolders: string[]; baseUrl: string }) {
|
233
|
+
const wearablePathArray: string[] = []
|
234
|
+
for (const wearableDir of baseFolders) {
|
235
|
+
const wearableJsonPath = path.resolve(wearableDir, 'wearable.json')
|
236
|
+
if (fs.existsSync(wearableJsonPath)) {
|
237
|
+
wearablePathArray.push(wearableJsonPath)
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
const ret: ReturnType<typeof serveWearable>[] = []
|
242
|
+
for (const wearableJsonPath of wearablePathArray) {
|
243
|
+
try {
|
244
|
+
ret.push(serveWearable({ wearableJsonPath, baseUrl }))
|
245
|
+
} catch (err) {
|
246
|
+
console.error(`Couldn't mock the wearable ${wearableJsonPath}. Please verify the correct format and scheme.`, err)
|
247
|
+
}
|
248
|
+
}
|
249
|
+
return ret
|
250
|
+
}
|
251
|
+
|
252
|
+
function serveWearable({ wearableJsonPath, baseUrl }: { wearableJsonPath: string; baseUrl: string }) {
|
253
|
+
const wearableDir = path.dirname(wearableJsonPath)
|
254
|
+
const wearableJson = JSON.parse(fs.readFileSync(wearableJsonPath).toString())
|
255
|
+
|
256
|
+
if (!WearableJson.validate(wearableJson)) {
|
257
|
+
const errors = (WearableJson.validate.errors || []).map((a) => `${a.data} ${a.message}`).join('')
|
258
|
+
|
259
|
+
console.error(`Unable to validate wearable.json properly, please check it.`, errors)
|
260
|
+
throw new Error(`Invalid wearable.json (${wearableJsonPath})`)
|
261
|
+
}
|
262
|
+
|
263
|
+
const dclIgnorePath = path.resolve(wearableDir, '.dclignore')
|
264
|
+
let ignoreFileContent = ''
|
265
|
+
if (fs.existsSync(dclIgnorePath)) {
|
266
|
+
ignoreFileContent = fs.readFileSync(path.resolve(wearableDir, '.dclignore'), 'utf-8')
|
267
|
+
}
|
268
|
+
|
269
|
+
const hashedFiles = getFilesFromFolder({
|
270
|
+
folder: wearableDir,
|
271
|
+
addOriginalPath: false,
|
272
|
+
ignorePattern: ignoreFileContent
|
273
|
+
})
|
274
|
+
|
275
|
+
const thumbnailFiltered = hashedFiles.filter(($) => $?.file === 'thumbnail.png')
|
276
|
+
const thumbnail =
|
277
|
+
thumbnailFiltered.length > 0 && thumbnailFiltered[0]?.hash && `${baseUrl}/${thumbnailFiltered[0].hash}`
|
278
|
+
|
279
|
+
const wearableId = 'urn:8dc2d7ad-97e3-44d0-ba89-e8305d795a6a'
|
280
|
+
|
281
|
+
const representations = wearableJson.data.representations.map((representation) => ({
|
282
|
+
...representation,
|
283
|
+
mainFile: `male/${representation.mainFile}`,
|
284
|
+
contents: hashedFiles.map(($) => ({
|
285
|
+
key: `male/${$?.file}`,
|
286
|
+
url: `${baseUrl}/${$?.hash}`,
|
287
|
+
hash: $?.hash
|
288
|
+
}))
|
289
|
+
}))
|
290
|
+
|
291
|
+
return {
|
292
|
+
id: wearableId,
|
293
|
+
rarity: wearableJson.rarity,
|
294
|
+
i18n: [{ code: 'en', text: wearableJson.name }],
|
295
|
+
description: wearableJson.description,
|
296
|
+
thumbnail: thumbnail || '',
|
297
|
+
baseUrl: `${baseUrl}/`,
|
298
|
+
name: wearableJson.name || '',
|
299
|
+
data: {
|
300
|
+
category: wearableJson.data.category,
|
301
|
+
replaces: [],
|
302
|
+
hides: [],
|
303
|
+
tags: [],
|
304
|
+
scene: hashedFiles,
|
305
|
+
representations: representations as any
|
306
|
+
}
|
307
|
+
}
|
308
|
+
}
|
309
|
+
|
310
|
+
function getSceneJson({
|
311
|
+
baseFolders,
|
312
|
+
pointers,
|
313
|
+
customHashMaker
|
314
|
+
}: {
|
315
|
+
baseFolders: string[]
|
316
|
+
pointers: string[]
|
317
|
+
customHashMaker?: (str: string) => string
|
318
|
+
}): Entity[] {
|
319
|
+
const requestedPointers = new Set<string>(pointers)
|
320
|
+
const resultEntities: Entity[] = []
|
321
|
+
|
322
|
+
const allDeployments = baseFolders.map((folder) => {
|
323
|
+
const dclIgnorePath = path.resolve(folder, '.dclignore')
|
324
|
+
let ignoreFileContent = ''
|
325
|
+
if (fs.existsSync(dclIgnorePath)) {
|
326
|
+
ignoreFileContent = fs.readFileSync(path.resolve(folder, '.dclignore'), 'utf-8')
|
327
|
+
}
|
328
|
+
|
329
|
+
return entityV3FromFolder({
|
330
|
+
folder,
|
331
|
+
addOriginalPath: false,
|
332
|
+
ignorePattern: ignoreFileContent,
|
333
|
+
customHashMaker
|
334
|
+
})
|
335
|
+
})
|
336
|
+
|
337
|
+
for (const pointer of Array.from(requestedPointers)) {
|
338
|
+
// get deployment by pointer
|
339
|
+
const theDeployment = allDeployments.find(($) => $ && $.pointers.includes(pointer))
|
340
|
+
if (theDeployment) {
|
341
|
+
// remove all the required pointers from the requestedPointers set
|
342
|
+
// to prevent sending duplicated entities
|
343
|
+
theDeployment.pointers.forEach(($) => requestedPointers.delete($))
|
344
|
+
|
345
|
+
// add the deployment to the results
|
346
|
+
resultEntities.push(theDeployment)
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
return resultEntities
|
351
|
+
}
|
352
|
+
|
353
|
+
function getEcsPath(workingDir: string) {
|
354
|
+
try {
|
355
|
+
return require.resolve('decentraland-ecs/package.json', {
|
356
|
+
paths: [workingDir]
|
357
|
+
})
|
358
|
+
} catch (e) {
|
359
|
+
return require.resolve('@dcl/sdk/package.json', {
|
360
|
+
paths: [workingDir]
|
361
|
+
})
|
362
|
+
}
|
363
|
+
}
|
364
|
+
|
365
|
+
function serveStatic(dir: string, router: Router<PreviewComponents>) {
|
366
|
+
const ecsPath = path.dirname(getEcsPath(dir))
|
367
|
+
const dclKernelPath = path.dirname(
|
368
|
+
require.resolve('@dcl/kernel/package.json', {
|
369
|
+
paths: [dir, ecsPath]
|
370
|
+
})
|
371
|
+
)
|
372
|
+
const dclKernelDefaultProfilePath = path.resolve(dclKernelPath, 'default-profile')
|
373
|
+
const dclKernelImagesDecentralandConnect = path.resolve(dclKernelPath, 'images', 'decentraland-connect')
|
374
|
+
const dclKernelLoaderPath = path.resolve(dclKernelPath, 'loader')
|
375
|
+
const dclUnityRenderer = path.dirname(
|
376
|
+
require.resolve('@dcl/unity-renderer/package.json', {
|
377
|
+
paths: [dir, ecsPath]
|
378
|
+
})
|
379
|
+
)
|
380
|
+
|
381
|
+
const routes = [
|
382
|
+
{
|
383
|
+
route: '/',
|
384
|
+
path: path.resolve(dclKernelPath, 'preview.html'),
|
385
|
+
type: 'text/html'
|
386
|
+
},
|
387
|
+
{
|
388
|
+
route: '/favicon.ico',
|
389
|
+
path: path.resolve(dclKernelPath, 'favicon.ico'),
|
390
|
+
type: 'text/html'
|
391
|
+
},
|
392
|
+
{
|
393
|
+
route: '/@/artifacts/index.js',
|
394
|
+
path: path.resolve(dclKernelPath, 'index.js'),
|
395
|
+
type: 'text/javascript'
|
396
|
+
}
|
397
|
+
]
|
398
|
+
|
399
|
+
for (const route of routes) {
|
400
|
+
router.get(route.route, async (_ctx) => {
|
401
|
+
return {
|
402
|
+
headers: { 'Content-Type': route.type },
|
403
|
+
body: fs.createReadStream(route.path)
|
404
|
+
}
|
405
|
+
})
|
406
|
+
}
|
407
|
+
|
408
|
+
function createStaticRoutes(route: string, folder: string, transform = (str: string) => str) {
|
409
|
+
router.get(route, async (ctx, next) => {
|
410
|
+
const file = ctx.params.path
|
411
|
+
const fullPath = path.resolve(folder, transform(file))
|
412
|
+
|
413
|
+
// only return files IF the file is within a baseFolder
|
414
|
+
if (!fs.existsSync(fullPath)) {
|
415
|
+
return next()
|
416
|
+
}
|
417
|
+
|
418
|
+
const headers: Record<string, any> = {
|
419
|
+
'x-timestamp': Date.now(),
|
420
|
+
'x-sent': true,
|
421
|
+
'cache-control': 'no-cache,private,max-age=1'
|
422
|
+
}
|
423
|
+
|
424
|
+
if (fullPath.endsWith('.wasm')) {
|
425
|
+
headers['content-type'] = 'application/wasm'
|
426
|
+
}
|
427
|
+
|
428
|
+
return {
|
429
|
+
headers,
|
430
|
+
body: fs.createReadStream(fullPath)
|
431
|
+
}
|
432
|
+
})
|
433
|
+
}
|
434
|
+
|
435
|
+
createStaticRoutes('/images/decentraland-connect/:path+', dclKernelImagesDecentralandConnect)
|
436
|
+
createStaticRoutes('/@/artifacts/unity-renderer/:path+', dclUnityRenderer, (filePath) =>
|
437
|
+
filePath.replace(/.br+$/, '')
|
438
|
+
)
|
439
|
+
createStaticRoutes('/@/artifacts/loader/:path+', dclKernelLoaderPath)
|
440
|
+
createStaticRoutes('/default-profile/:path+', dclKernelDefaultProfilePath)
|
441
|
+
|
442
|
+
router.get('/feature-flags/:file', async (ctx) => {
|
443
|
+
const res = await fetch(`https://feature-flags.decentraland.zone/${ctx.params.file}`, {
|
444
|
+
headers: {
|
445
|
+
connection: 'close'
|
446
|
+
}
|
447
|
+
})
|
448
|
+
return {
|
449
|
+
body: await res.arrayBuffer()
|
450
|
+
}
|
451
|
+
})
|
452
|
+
}
|
453
|
+
|
454
|
+
function entityV3FromFolder({
|
455
|
+
folder,
|
456
|
+
addOriginalPath,
|
457
|
+
ignorePattern,
|
458
|
+
customHashMaker
|
459
|
+
}: {
|
460
|
+
folder: string
|
461
|
+
addOriginalPath?: boolean
|
462
|
+
ignorePattern?: string
|
463
|
+
customHashMaker?: (str: string) => string
|
464
|
+
}): Entity | null {
|
465
|
+
const sceneJsonPath = path.resolve(folder, './scene.json')
|
466
|
+
let isParcelScene = true
|
467
|
+
|
468
|
+
const wearableJsonPath = path.resolve(folder, './wearable.json')
|
469
|
+
if (fs.existsSync(wearableJsonPath)) {
|
470
|
+
try {
|
471
|
+
const wearableJson = JSON.parse(fs.readFileSync(wearableJsonPath).toString())
|
472
|
+
if (!WearableJson.validate(wearableJson)) {
|
473
|
+
const errors = (WearableJson.validate.errors || []).map((a) => `${a.data} ${a.message}`).join('')
|
474
|
+
|
475
|
+
console.error(`Unable to validate wearable.json properly, please check it.`, errors)
|
476
|
+
console.error(`Invalid wearable.json (${wearableJsonPath})`)
|
477
|
+
} else {
|
478
|
+
isParcelScene = false
|
479
|
+
}
|
480
|
+
} catch (err) {
|
481
|
+
console.error(`Unable to load wearable.json properly`, err)
|
482
|
+
}
|
483
|
+
}
|
484
|
+
|
485
|
+
const hashMaker = customHashMaker ? customHashMaker : defaultHashMaker
|
486
|
+
|
487
|
+
if (fs.existsSync(sceneJsonPath) && isParcelScene) {
|
488
|
+
const sceneJson = JSON.parse(fs.readFileSync(sceneJsonPath).toString())
|
489
|
+
const { base, parcels }: { base: string; parcels: string[] } = sceneJson.scene
|
490
|
+
const pointers = new Set<string>()
|
491
|
+
pointers.add(base)
|
492
|
+
parcels.forEach(($) => pointers.add($))
|
493
|
+
|
494
|
+
const mappedFiles = getFilesFromFolder({
|
495
|
+
folder,
|
496
|
+
addOriginalPath,
|
497
|
+
ignorePattern,
|
498
|
+
customHashMaker
|
499
|
+
})
|
500
|
+
|
501
|
+
return {
|
502
|
+
version: 'v3',
|
503
|
+
type: EntityType.SCENE,
|
504
|
+
id: hashMaker(folder),
|
505
|
+
pointers: Array.from(pointers),
|
506
|
+
timestamp: Date.now(),
|
507
|
+
metadata: sceneJson,
|
508
|
+
content: mappedFiles
|
509
|
+
}
|
510
|
+
}
|
511
|
+
|
512
|
+
return null
|
513
|
+
}
|
514
|
+
|
515
|
+
const defaultDclIgnore = () =>
|
516
|
+
[
|
517
|
+
'.*',
|
518
|
+
'package.json',
|
519
|
+
'package-lock.json',
|
520
|
+
'yarn-lock.json',
|
521
|
+
'build.json',
|
522
|
+
'export',
|
523
|
+
'tsconfig.json',
|
524
|
+
'tslint.json',
|
525
|
+
'node_modules',
|
526
|
+
'*.ts',
|
527
|
+
'*.tsx',
|
528
|
+
'Dockerfile',
|
529
|
+
'dist',
|
530
|
+
'README.md',
|
531
|
+
'*.blend',
|
532
|
+
'*.fbx',
|
533
|
+
'*.zip',
|
534
|
+
'*.rar'
|
535
|
+
].join('\n')
|
536
|
+
|
537
|
+
export function getFilesFromFolder({
|
538
|
+
folder,
|
539
|
+
addOriginalPath,
|
540
|
+
ignorePattern,
|
541
|
+
customHashMaker
|
542
|
+
}: {
|
543
|
+
folder: string
|
544
|
+
addOriginalPath?: boolean
|
545
|
+
ignorePattern?: string
|
546
|
+
customHashMaker?: (str: string) => string
|
547
|
+
}): ContentMapping[] {
|
548
|
+
const hashMaker = customHashMaker ? customHashMaker : defaultHashMaker
|
549
|
+
|
550
|
+
const allFiles = globSync('**/*', {
|
551
|
+
cwd: folder,
|
552
|
+
dot: false,
|
553
|
+
absolute: true
|
554
|
+
})
|
555
|
+
.map((file) => {
|
556
|
+
try {
|
557
|
+
if (!fs.statSync(file).isFile()) return
|
558
|
+
} catch (err) {
|
559
|
+
return
|
560
|
+
}
|
561
|
+
const _folder = folder.replace(/\\/gi, '/')
|
562
|
+
const key = file.replace(_folder, '').replace(/^\/+/, '')
|
563
|
+
return key
|
564
|
+
})
|
565
|
+
.filter(($) => !!$) as string[]
|
566
|
+
|
567
|
+
const ensureIgnorePattern = ignorePattern && ignorePattern !== '' ? ignorePattern : defaultDclIgnore()
|
568
|
+
const ig = ignore().add(ensureIgnorePattern)
|
569
|
+
const filteredFiles = ig.filter(allFiles)
|
570
|
+
|
571
|
+
const ret: (ContentMapping & { original_path: string | undefined })[] = []
|
572
|
+
|
573
|
+
for (const file of filteredFiles) {
|
574
|
+
const absolutePath = path.resolve(folder, file)
|
575
|
+
try {
|
576
|
+
if (!fs.statSync(absolutePath).isFile()) continue
|
577
|
+
} catch (err) {
|
578
|
+
console.log(err)
|
579
|
+
continue
|
580
|
+
}
|
581
|
+
|
582
|
+
const absoluteFolder = folder.replace(/\\/gi, '/')
|
583
|
+
|
584
|
+
const relativeFilePathToFolder = file.replace(absoluteFolder, '').replace(/^\/+/, '')
|
585
|
+
|
586
|
+
ret.push({
|
587
|
+
file: relativeFilePathToFolder.toLowerCase(),
|
588
|
+
original_path: addOriginalPath ? absolutePath : undefined,
|
589
|
+
hash: hashMaker(absolutePath)
|
590
|
+
})
|
591
|
+
}
|
592
|
+
|
593
|
+
return ret
|
594
|
+
}
|
@@ -0,0 +1,6 @@
|
|
1
|
+
"use strict";
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
3
|
+
exports.providerInstance = void 0;
|
4
|
+
const eth_connect_1 = require("eth-connect");
|
5
|
+
exports.providerInstance = new eth_connect_1.HTTPProvider('https://goerli.infura.io/');
|
6
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXRoLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiZXRoLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDZDQUEwQztBQUU3QixRQUFBLGdCQUFnQixHQUFHLElBQUksMEJBQVksQ0FBQywyQkFBMkIsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSFRUUFByb3ZpZGVyIH0gZnJvbSAnZXRoLWNvbm5lY3QnXG5cbmV4cG9ydCBjb25zdCBwcm92aWRlckluc3RhbmNlID0gbmV3IEhUVFBQcm92aWRlcignaHR0cHM6Ly9nb2VybGkuaW5mdXJhLmlvLycpXG4iXX0=
|
@@ -0,0 +1,18 @@
|
|
1
|
+
import { CliComponents } from '../../components';
|
2
|
+
export declare function help(): string;
|
3
|
+
interface Options {
|
4
|
+
args: Omit<typeof args, '_'>;
|
5
|
+
components: Pick<CliComponents, 'fetch' | 'fs'>;
|
6
|
+
}
|
7
|
+
export declare const args: import("arg").Result<{
|
8
|
+
'--help': BooleanConstructor;
|
9
|
+
'-h': string;
|
10
|
+
} & {
|
11
|
+
'--watch': BooleanConstructor;
|
12
|
+
'-w': string;
|
13
|
+
'--dir': StringConstructor;
|
14
|
+
'--port': NumberConstructor;
|
15
|
+
'-p': string;
|
16
|
+
}>;
|
17
|
+
export declare const main: (args: Options) => Promise<void>;
|
18
|
+
export {};
|