@dcl/sdk-commands 7.0.0-4294380152.commit-0d08b10 → 7.0.0-4295573637.commit-6d503ad

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.
@@ -53,7 +53,7 @@ async function main(options) {
53
53
  if (!watch) {
54
54
  watchingFuture.resolve(null);
55
55
  }
56
- const sceneJson = await (0, project_files_1.getSceneJson)(options.components, projectRoot);
56
+ const sceneJson = await (0, scene_validations_1.getValidSceneJson)(options.components, projectRoot);
57
57
  const coords = (0, scene_validations_1.getBaseCoords)(sceneJson);
58
58
  await options.components.analytics.track('Build scene', {
59
59
  projectHash: await (0, project_files_1.b64HashingFunction)(projectRoot),
@@ -0,0 +1,31 @@
1
+ import { CliComponents } from '../../components';
2
+ interface Options {
3
+ args: typeof args;
4
+ components: CliComponents;
5
+ }
6
+ export declare const args: import("arg").Result<{
7
+ '--help': BooleanConstructor;
8
+ '--json': BooleanConstructor;
9
+ '-h': string;
10
+ } & {
11
+ '--dir': StringConstructor;
12
+ '--help': BooleanConstructor;
13
+ '-h': string;
14
+ '--target': StringConstructor;
15
+ '-t': string;
16
+ '--target-content': StringConstructor;
17
+ '-tc': string;
18
+ '--skip-validations': BooleanConstructor;
19
+ '--skip-version-checks': BooleanConstructor;
20
+ '--skip-build': BooleanConstructor;
21
+ '--https': BooleanConstructor;
22
+ '--force-upload': BooleanConstructor;
23
+ '--yes': BooleanConstructor;
24
+ '--no-browser': BooleanConstructor;
25
+ '-b': string;
26
+ '--port': NumberConstructor;
27
+ '-p': string;
28
+ }>;
29
+ export declare function help(): string;
30
+ export declare function main(options: Options): Promise<void>;
31
+ export {};
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.main = exports.help = exports.args = void 0;
4
+ const path_1 = require("path");
5
+ const schemas_1 = require("@dcl/schemas");
6
+ const dcl_catalyst_client_1 = require("dcl-catalyst-client");
7
+ const crypto_1 = require("@dcl/crypto");
8
+ const eth_connect_1 = require("eth-connect");
9
+ const crypto_2 = require("@dcl/crypto/dist/crypto");
10
+ const build_1 = require("../build");
11
+ const scene_validations_1 = require("../../logic/scene-validations");
12
+ const args_1 = require("../../logic/args");
13
+ const project_validations_1 = require("../../logic/project-validations");
14
+ const api_1 = require("./linker-dapp/api");
15
+ const error_1 = require("../../logic/error");
16
+ const beautiful_logs_1 = require("../../logic/beautiful-logs");
17
+ const account_1 = require("../../logic/account");
18
+ exports.args = (0, args_1.getArgs)({
19
+ '--dir': String,
20
+ '--help': Boolean,
21
+ '-h': '--help',
22
+ '--target': String,
23
+ '-t': '--target',
24
+ '--target-content': String,
25
+ '-tc': '--target-content',
26
+ '--skip-validations': Boolean,
27
+ '--skip-version-checks': Boolean,
28
+ '--skip-build': Boolean,
29
+ '--https': Boolean,
30
+ '--force-upload': Boolean,
31
+ '--yes': Boolean,
32
+ '--no-browser': Boolean,
33
+ '-b': '--no-browser',
34
+ '--port': Number,
35
+ '-p': '--port'
36
+ });
37
+ function help() {
38
+ return `
39
+ Usage: 'sdk-commands build [options]'
40
+ Options:
41
+ -h, --help Displays complete help
42
+ -p, --port [port] Select a custom port for the development server
43
+ -t, --target Specifies the address and port for the target catalyst server. Defaults to peer.decentraland.org
44
+ -t, --target-content Specifies the address and port for the target content server. Example: 'peer.decentraland.org/content'. Can't be set together with --target
45
+ -b, --no-browser Do not open a new browser window
46
+ --skip-version-checks Skip the ECS and CLI version checks, avoid the warning message and launch anyway
47
+ --skip-build Skip build before deploy
48
+ --skip-validations Skip permissions verifications on the client side when deploying content
49
+
50
+ Example:
51
+ - Deploy your scene:
52
+ $ sdk-commands deploy
53
+ - Deploy your scene to a specific content server:
54
+ $ sdk-commands deploy --target my-favorite-catalyst-server.org:2323
55
+ `;
56
+ }
57
+ exports.help = help;
58
+ async function main(options) {
59
+ const dir = (0, path_1.resolve)(process.cwd(), options.args['--dir'] || '.');
60
+ const openBrowser = !options.args['--no-browser'];
61
+ const skipBuild = options.args['--skip-build'];
62
+ const linkerPort = options.args['--port'];
63
+ const { error } = options.components.logger;
64
+ const comps = { components: options.components };
65
+ if (!skipBuild) {
66
+ await (0, project_validations_1.npmRun)(dir, 'build');
67
+ }
68
+ await (0, build_1.main)({ args: { '--dir': dir }, ...comps });
69
+ if (options.args['--target'] && options.args['--target-content']) {
70
+ throw new error_1.CliError(`You can't set both the 'target' and 'target-content' arguments.`);
71
+ }
72
+ // Obtain list of files to deploy
73
+ const files = await (0, scene_validations_1.getFiles)(options.components, dir);
74
+ (0, scene_validations_1.validateFilesSizes)(files);
75
+ const contentFiles = new Map(files.map((file) => [file.path, file.content]));
76
+ const sceneJson = await (0, scene_validations_1.getValidSceneJson)(options.components, dir);
77
+ const { entityId, files: entityFiles } = await dcl_catalyst_client_1.DeploymentBuilder.buildEntity({
78
+ type: schemas_1.EntityType.SCENE,
79
+ pointers: sceneJson.scene.parcels,
80
+ files: contentFiles,
81
+ metadata: sceneJson
82
+ });
83
+ // Signing message
84
+ const messageToSign = entityId;
85
+ const { signature, address, chainId } = await getAddressAndSignature(options.components, messageToSign, sceneJson, files, {
86
+ openBrowser,
87
+ linkerPort,
88
+ isHttps: !!options.args['--https'],
89
+ skipValidations: !!options.args['--skip-validations'] || !!options.args['--target'] || !!options.args['--target-content']
90
+ });
91
+ const authChain = crypto_1.Authenticator.createSimpleAuthChain(entityId, address, signature);
92
+ // Uploading data
93
+ const catalyst = await getCatalyst(options.args['--target'], options.args['--target-content']);
94
+ (0, beautiful_logs_1.printProgressInfo)(options.components.logger, `Uploading data to: ${catalyst.getContentUrl()}...`);
95
+ const deployData = { entityId, files: entityFiles, authChain };
96
+ const position = sceneJson.scene.base;
97
+ const network = chainId === schemas_1.ChainId.ETHEREUM_GOERLI ? 'goerli' : 'mainnet';
98
+ const sceneUrl = `https://play.decentraland.org/?NETWORK=${network}&position=${position}`;
99
+ try {
100
+ const response = (await catalyst.deploy(deployData, {
101
+ timeout: '10m'
102
+ }));
103
+ if (response.message) {
104
+ (0, beautiful_logs_1.printProgressInfo)(options.components.logger, response.message);
105
+ }
106
+ (0, beautiful_logs_1.printSuccess)(options.components.logger, 'Content uploaded', sceneUrl);
107
+ }
108
+ catch (e) {
109
+ error('Could not upload content:');
110
+ console.log(e);
111
+ }
112
+ }
113
+ exports.main = main;
114
+ async function getCatalyst(target, targetContent) {
115
+ if (target) {
116
+ return new dcl_catalyst_client_1.CatalystClient({ catalystUrl: target.endsWith('/') ? target.slice(0, -1) : target });
117
+ }
118
+ if (targetContent) {
119
+ return new dcl_catalyst_client_1.ContentClient({ contentUrl: targetContent });
120
+ }
121
+ return dcl_catalyst_client_1.CatalystClient.connectedToCatalystIn({ network: 'mainnet' });
122
+ }
123
+ async function getAddressAndSignature(components, messageToSign, scene, files, linkOptions) {
124
+ if (process.env.DCL_PRIVATE_KEY) {
125
+ const wallet = (0, account_1.createWallet)(process.env.DCL_PRIVATE_KEY);
126
+ const signature = (0, crypto_2.ethSign)((0, eth_connect_1.hexToBytes)(wallet.privateKey), messageToSign);
127
+ return { signature, address: wallet.address };
128
+ }
129
+ const { linkerPort, ...opts } = linkOptions;
130
+ return (0, api_1.runLinkerApp)(components, scene, files, linkerPort, messageToSign, opts);
131
+ }
@@ -0,0 +1,24 @@
1
+ import { ChainId, Scene } from '@dcl/schemas';
2
+ import { IFile } from '../../../logic/scene-validations';
3
+ import { CliComponents } from '../../../components';
4
+ export interface LinkerResponse {
5
+ address: string;
6
+ signature: string;
7
+ chainId?: ChainId;
8
+ }
9
+ export interface SceneInfo {
10
+ baseParcel: string;
11
+ parcels: string[];
12
+ rootCID: string;
13
+ landRegistry?: string;
14
+ estateRegistry?: string;
15
+ debug: boolean;
16
+ title?: string;
17
+ description?: string;
18
+ skipValidations: boolean;
19
+ }
20
+ export declare function runLinkerApp(cliComponents: Pick<CliComponents, 'fs' | 'logger' | 'fetch'>, scene: Scene, files: IFile[], port: number, rootCID: string, { isHttps, skipValidations, openBrowser }: {
21
+ isHttps: boolean;
22
+ skipValidations: boolean;
23
+ openBrowser: boolean;
24
+ }): Promise<LinkerResponse>;
@@ -0,0 +1,92 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.runLinkerApp = void 0;
7
+ const http_server_1 = require("@well-known-components/http-server");
8
+ const interfaces_1 = require("@well-known-components/interfaces");
9
+ const env_config_provider_1 = require("@well-known-components/env-config-provider");
10
+ const logger_1 = require("@well-known-components/logger");
11
+ const path_1 = require("path");
12
+ const schemas_1 = require("@dcl/schemas");
13
+ const querystring_1 = __importDefault(require("querystring"));
14
+ const open_1 = __importDefault(require("open"));
15
+ const get_free_port_1 = require("../../../logic/get-free-port");
16
+ const dcl_info_1 = require("../../../logic/dcl-info");
17
+ const beautiful_logs_1 = require("../../../logic/beautiful-logs");
18
+ const routes_1 = require("./routes");
19
+ function runLinkerApp(cliComponents, scene, files, port, rootCID, { isHttps, skipValidations, openBrowser }) {
20
+ return new Promise(async (resolve) => {
21
+ const { logger } = cliComponents;
22
+ const resolvedPort = await (0, get_free_port_1.getPort)(port, 4044);
23
+ const sceneInfo = await getSceneInfo(scene, rootCID, skipValidations);
24
+ const protocol = isHttps ? 'https' : 'http';
25
+ const queryParams = querystring_1.default.stringify(sceneInfo);
26
+ const url = `${protocol}://localhost:${resolvedPort}`;
27
+ const program = await interfaces_1.Lifecycle.run({
28
+ async initComponents() {
29
+ const config = (0, env_config_provider_1.createRecordConfigComponent)({
30
+ HTTP_SERVER_PORT: resolvedPort.toString(),
31
+ HTTP_SERVER_HOST: '0.0.0.0',
32
+ ...process.env
33
+ });
34
+ const logs = await (0, logger_1.createConsoleLogComponent)({});
35
+ const components = { config, logs };
36
+ const https = isHttps ? await getCredentials(cliComponents) : undefined;
37
+ const server = await (0, http_server_1.createServerComponent)(components, { https });
38
+ return { config, logs, server };
39
+ },
40
+ async main({ components, startComponents }) {
41
+ const { router, futureSignature } = (0, routes_1.setRoutes)(cliComponents, files, sceneInfo);
42
+ components.server.setContext(components);
43
+ components.server.use(router.allowedMethods());
44
+ components.server.use(router.middleware());
45
+ console.log('\x1Bc');
46
+ await startComponents();
47
+ if (openBrowser)
48
+ await browse(cliComponents, url, queryParams);
49
+ const value = await futureSignature;
50
+ (0, beautiful_logs_1.printSuccess)(cliComponents.logger, `\nContent successfully signed.`, '');
51
+ logger.info(`Address: ${value.address}`);
52
+ logger.info(`Signature: ${value.signature}`);
53
+ logger.info(`Network: ${(0, schemas_1.getChainName)(value.chainId)}`);
54
+ resolve(value);
55
+ }
56
+ });
57
+ return program;
58
+ });
59
+ }
60
+ exports.runLinkerApp = runLinkerApp;
61
+ async function browse({ logger }, url, params) {
62
+ logger.info('You need to sign the content before the deployment:');
63
+ setTimeout(async () => {
64
+ try {
65
+ await (0, open_1.default)(`${url}?${params}`);
66
+ }
67
+ catch (e) {
68
+ logger.error(`Unable to open browser automatically`);
69
+ }
70
+ }, 5000);
71
+ logger.info(`Signing app ready at ${url}`);
72
+ }
73
+ async function getCredentials({ fs }) {
74
+ const privateKey = await fs.readFile((0, path_1.resolve)(__dirname, '../../../certs/localhost.key'), 'utf-8');
75
+ const certificate = await fs.readFile((0, path_1.resolve)(__dirname, '../../../certs/localhost.crt'), 'utf-8');
76
+ return { key: privateKey, cert: certificate };
77
+ }
78
+ async function getSceneInfo(scene, rootCID, skipValidations) {
79
+ const { LANDRegistry, EstateRegistry } = (0, dcl_info_1.getCustomConfig)();
80
+ const { scene: { parcels, base }, display } = scene;
81
+ return {
82
+ baseParcel: base,
83
+ parcels,
84
+ rootCID,
85
+ landRegistry: LANDRegistry,
86
+ estateRegistry: EstateRegistry,
87
+ debug: !!process.env.DEBUG,
88
+ title: display?.title,
89
+ description: display?.description,
90
+ skipValidations
91
+ };
92
+ }
@@ -0,0 +1,20 @@
1
+ import { Entity } from '@dcl/schemas';
2
+ import { CliComponents } from '../../../components';
3
+ export type DAOCatalyst = {
4
+ baseUrl: string;
5
+ owner: string;
6
+ id: string;
7
+ };
8
+ type CatalystInfo = {
9
+ url: string;
10
+ timestamp: number;
11
+ entityId: string;
12
+ };
13
+ export type Network = 'mainnet' | 'goerli';
14
+ export declare function daoCatalysts({ fetch }: Pick<CliComponents, 'fetch'>, network?: Network): Promise<Array<DAOCatalyst>>;
15
+ export declare function fetchEntityByPointer({ fetch }: Pick<CliComponents, 'fetch'>, baseUrl: string, pointers: string[]): Promise<{
16
+ baseUrl: string;
17
+ deployments: Entity[];
18
+ }>;
19
+ export declare function getPointers(components: Pick<CliComponents, 'fetch'>, pointer: string, network?: Network): Promise<CatalystInfo[]>;
20
+ export {};
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPointers = exports.fetchEntityByPointer = exports.daoCatalysts = void 0;
4
+ async function daoCatalysts({ fetch }, network = 'mainnet') {
5
+ const tld = network === 'mainnet' ? 'org' : 'zone';
6
+ const resp = await (await fetch.fetch(`https://peer.decentraland.${tld}/lambdas/contracts/servers`)).json();
7
+ return resp;
8
+ }
9
+ exports.daoCatalysts = daoCatalysts;
10
+ async function fetchEntityByPointer({ fetch }, baseUrl, pointers) {
11
+ if (pointers.length === 0)
12
+ return {
13
+ baseUrl,
14
+ deployments: []
15
+ };
16
+ const activeEntities = baseUrl + '/content/entities/active';
17
+ const response = await fetch.fetch(activeEntities, {
18
+ method: 'post',
19
+ headers: { 'content-type': 'application/json', connection: 'close' },
20
+ body: JSON.stringify({ pointers })
21
+ });
22
+ const deployments = response.ok ? (await response.json()) : [];
23
+ return {
24
+ baseUrl,
25
+ deployments
26
+ };
27
+ }
28
+ exports.fetchEntityByPointer = fetchEntityByPointer;
29
+ async function getPointers(components, pointer, network = 'mainnet') {
30
+ const catalysts = await daoCatalysts(components, network);
31
+ const catalystInfo = [];
32
+ for (const { baseUrl } of catalysts) {
33
+ try {
34
+ const result = await fetchEntityByPointer(components, baseUrl, [pointer]);
35
+ const timestamp = result.deployments[0]?.timestamp;
36
+ const entityId = result.deployments[0]?.id || '';
37
+ catalystInfo.push({ timestamp, entityId, url: baseUrl });
38
+ }
39
+ catch (err) {
40
+ console.log('Error fetching catalyst pointers', err);
41
+ }
42
+ }
43
+ return catalystInfo;
44
+ }
45
+ exports.getPointers = getPointers;
@@ -0,0 +1,8 @@
1
+ import { Router } from '@well-known-components/http-server';
2
+ import { CliComponents } from '../../../components';
3
+ import { IFile } from '../../../logic/scene-validations';
4
+ import { LinkerResponse, SceneInfo } from './api';
5
+ export declare function setRoutes(components: Pick<CliComponents, 'fs' | 'logger' | 'fetch'>, files: IFile[], sceneInfo: SceneInfo): {
6
+ router: Router<{}>;
7
+ futureSignature: import("fp-future").IFuture<LinkerResponse>;
8
+ };
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.setRoutes = void 0;
7
+ const path_1 = require("path");
8
+ const url_1 = __importDefault(require("url"));
9
+ const http_server_1 = require("@well-known-components/http-server");
10
+ const schemas_1 = require("@dcl/schemas");
11
+ const fp_future_1 = __importDefault(require("fp-future"));
12
+ const catalyst_pointers_1 = require("./catalyst-pointers");
13
+ const coordinates_1 = require("../../../logic/coordinates");
14
+ function getContentType(type) {
15
+ switch (type) {
16
+ case 'css':
17
+ return 'text/css';
18
+ case 'js':
19
+ return 'application/js';
20
+ case 'media':
21
+ default:
22
+ return 'text/plain';
23
+ }
24
+ }
25
+ function setRoutes(components, files, sceneInfo) {
26
+ const futureSignature = (0, fp_future_1.default)();
27
+ const { fs, logger } = components;
28
+ const router = new http_server_1.Router();
29
+ const linkerDapp = (0, path_1.dirname)(require.resolve('@dcl/linker-dapp/package.json'));
30
+ let deployInfo = {};
31
+ router.get('/', async () => ({
32
+ headers: { 'Content-Type': 'text/html' },
33
+ body: fs.createReadStream((0, path_1.resolve)(linkerDapp, 'index.html'))
34
+ }));
35
+ router.get('/static/:type/:path', async (ctx) => {
36
+ const contentType = getContentType(ctx.params.type);
37
+ return {
38
+ headers: { 'Content-Type': contentType },
39
+ body: fs.createReadStream((0, path_1.resolve)(linkerDapp, 'static', ctx.params.type, ctx.params.path))
40
+ };
41
+ });
42
+ router.get('/manifest.json', async () => ({
43
+ headers: { 'Content-Type': 'application/json' },
44
+ body: fs.createReadStream((0, path_1.resolve)(linkerDapp, 'manifest.json'))
45
+ }));
46
+ router.get('/api/info', async () => ({
47
+ body: sceneInfo
48
+ }));
49
+ router.get('/api/files', async () => ({
50
+ body: files.map((file) => ({
51
+ name: file.path,
52
+ size: file.size
53
+ }))
54
+ }));
55
+ router.get('/api/catalyst-pointers', async () => {
56
+ const { x, y } = (0, coordinates_1.getObject)(sceneInfo.baseParcel);
57
+ const pointer = `${x},${y}`;
58
+ const chainId = deployInfo.linkerResponse?.chainId || 1;
59
+ const network = chainId === schemas_1.ChainId.ETHEREUM_MAINNET ? 'mainnet' : 'goerli';
60
+ const value = await (0, catalyst_pointers_1.getPointers)(components, pointer, network);
61
+ return {
62
+ body: {
63
+ catalysts: value,
64
+ status: deployInfo.status ?? ''
65
+ }
66
+ };
67
+ });
68
+ router.get('/api/close', async (ctx) => {
69
+ const { ok, reason } = url_1.default.parse(ctx.url.toString(), true).query;
70
+ if (ok === 'true') {
71
+ const value = JSON.parse(reason?.toString() || '{}');
72
+ deployInfo = { ...deployInfo, linkerResponse: value };
73
+ futureSignature.resolve(value);
74
+ return {};
75
+ }
76
+ futureSignature.reject(new Error(`Failed to link: ${reason}`));
77
+ return {};
78
+ });
79
+ router.post('/api/deploy', async (ctx) => {
80
+ const value = (await ctx.request.json());
81
+ if (!value.address || !value.signature || !value.chainId) {
82
+ logger.error(`Invalid payload: ${Object.keys(value).join(' - ')}`);
83
+ return {};
84
+ }
85
+ deployInfo = { ...deployInfo, linkerResponse: value, status: 'deploying' };
86
+ futureSignature.resolve(value);
87
+ return {};
88
+ });
89
+ return { router, futureSignature };
90
+ }
91
+ exports.setRoutes = setRoutes;
@@ -115,7 +115,7 @@ async function main(options) {
115
115
  (0, beautiful_logs_1.printProgressInfo)(logger, `> ${realmName}/about -> [REALM FILE]`);
116
116
  }
117
117
  (0, beautiful_logs_1.printSuccess)(logger, `Export finished!`, `=> The entity URN is ${log_1.colors.bold(urn)}`);
118
- const sceneJson = await (0, project_files_1.getSceneJson)(options.components, projectRoot);
118
+ const sceneJson = await (0, scene_validations_1.getValidSceneJson)(options.components, projectRoot);
119
119
  const coords = (0, scene_validations_1.getBaseCoords)(sceneJson);
120
120
  await options.components.analytics.track('Export static', {
121
121
  projectHash: await (0, project_files_1.b64HashingFunction)(projectRoot),
@@ -113,14 +113,13 @@ async function main(options) {
113
113
  if (watch) {
114
114
  await (0, build_1.main)({ ...options, args: { '--dir': projectRoot, '--watch': watch } });
115
115
  }
116
- await (0, scene_validations_1.validateSceneJson)(options.components, projectRoot);
117
- const sceneJson = await (0, project_files_1.getSceneJson)(options.components, projectRoot);
116
+ const sceneJson = await (0, scene_validations_1.getValidSceneJson)(options.components, projectRoot);
118
117
  const baseCoords = (0, scene_validations_1.getBaseCoords)(sceneJson);
119
118
  if (await (0, project_validations_1.needsDependencies)(options.components, projectRoot)) {
120
119
  const npmModulesPath = path.resolve(projectRoot, 'node_modules');
121
120
  throw new error_1.CliError(`Couldn\'t find ${npmModulesPath}, please run: npm install`);
122
121
  }
123
- const port = options.args['--port'] || (await (0, get_free_port_1.previewPort)());
122
+ const port = await (0, get_free_port_1.getPort)(options.args['--port']);
124
123
  const program = await interfaces_1.Lifecycle.run({
125
124
  async initComponents() {
126
125
  const metrics = (0, metrics_1.createTestMetricsComponent)(rooms_1.roomsMetrics);
@@ -0,0 +1,6 @@
1
+ export interface Wallet {
2
+ address: string;
3
+ privateKey: string;
4
+ publicKey: string;
5
+ }
6
+ export declare function createWallet(privateKey: string): Wallet;
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createWallet = void 0;
4
+ const eth_connect_1 = require("eth-connect");
5
+ const crypto_1 = require("@dcl/crypto/dist/crypto");
6
+ const error_1 = require("./error");
7
+ function createWallet(privateKey) {
8
+ let length = 64;
9
+ if (privateKey.startsWith('0x')) {
10
+ length = 66;
11
+ }
12
+ if (privateKey.length !== length) {
13
+ throw new error_1.CliError('Addresses should be 64 characters length.');
14
+ }
15
+ const pk = (0, eth_connect_1.hexToBytes)(privateKey);
16
+ const msg = Math.random().toString();
17
+ const signature = (0, crypto_1.ethSign)(pk, msg);
18
+ const address = (0, crypto_1.recoverAddressFromEthSignature)(signature, msg);
19
+ return { address, privateKey, publicKey: '0x' };
20
+ }
21
+ exports.createWallet = createWallet;
@@ -0,0 +1,26 @@
1
+ import { CliComponents } from '../components';
2
+ /**
3
+ * Filter undefined keys from provided object
4
+ */
5
+ export declare function removeEmptyKeys(obj: Record<string, unknown>): Record<string, unknown>;
6
+ export type DCLInfo = {
7
+ fileExists?: boolean;
8
+ userId: string;
9
+ trackStats: boolean;
10
+ provider?: string;
11
+ MANAToken?: string;
12
+ LANDRegistry?: string;
13
+ EstateRegistry?: string;
14
+ catalystUrl?: string;
15
+ dclApiUrl?: string;
16
+ segmentKey?: string;
17
+ };
18
+ /**
19
+ * Reads `.dclinfo` file and loads it in-memory to be sync-obtained with `getDCLInfo()` function
20
+ */
21
+ export declare function loadConfig(components: CliComponents): Promise<DCLInfo>;
22
+ /**
23
+ * Returns the contents of the `.dclinfo` file. It needs to be loaded first with `loadConfig()` function
24
+ */
25
+ export declare function getDCLInfo(): DCLInfo;
26
+ export declare function getCustomConfig(): Partial<DCLInfo>;
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getCustomConfig = exports.getDCLInfo = exports.loadConfig = exports.removeEmptyKeys = void 0;
7
+ const path_1 = __importDefault(require("path"));
8
+ const os_1 = __importDefault(require("os"));
9
+ /**
10
+ * Filter undefined keys from provided object
11
+ */
12
+ function removeEmptyKeys(obj) {
13
+ const result = {};
14
+ Object.keys(obj)
15
+ .filter((k) => !!obj[k])
16
+ .forEach((k) => (result[k] = obj[k]));
17
+ return result;
18
+ }
19
+ exports.removeEmptyKeys = removeEmptyKeys;
20
+ let config;
21
+ /**
22
+ * Returns the path to the `.dclinfo` file located in the local HOME folder
23
+ */
24
+ function getDCLInfoPath() {
25
+ return path_1.default.resolve(os_1.default.homedir(), '.dclinfo');
26
+ }
27
+ /**
28
+ * Reads the contents of the `.dclinfo` file
29
+ */
30
+ async function readDCLInfo({ fs }) {
31
+ const filePath = getDCLInfoPath();
32
+ try {
33
+ const file = await fs.readFile(filePath, 'utf-8');
34
+ return JSON.parse(file);
35
+ }
36
+ catch (e) {
37
+ return null;
38
+ }
39
+ }
40
+ /**
41
+ * Reads `.dclinfo` file and loads it in-memory to be sync-obtained with `getDCLInfo()` function
42
+ */
43
+ async function loadConfig(components) {
44
+ config = (await readDCLInfo(components));
45
+ return config;
46
+ }
47
+ exports.loadConfig = loadConfig;
48
+ /**
49
+ * Returns the contents of the `.dclinfo` file. It needs to be loaded first with `loadConfig()` function
50
+ */
51
+ function getDCLInfo() {
52
+ return config;
53
+ }
54
+ exports.getDCLInfo = getDCLInfo;
55
+ function getCustomConfig() {
56
+ const envConfig = getEnvConfig();
57
+ const dclInfoConfig = getDclInfoConfig();
58
+ return { ...dclInfoConfig, ...envConfig };
59
+ }
60
+ exports.getCustomConfig = getCustomConfig;
61
+ function getDclInfoConfig() {
62
+ const dclInfo = getDCLInfo();
63
+ const fileExists = !!dclInfo;
64
+ if (!fileExists) {
65
+ return { fileExists };
66
+ }
67
+ const dclInfoConfig = {
68
+ fileExists,
69
+ userId: dclInfo.userId,
70
+ trackStats: !!dclInfo.trackStats,
71
+ MANAToken: dclInfo.MANAToken,
72
+ LANDRegistry: dclInfo.LANDRegistry,
73
+ EstateRegistry: dclInfo.EstateRegistry,
74
+ catalystUrl: dclInfo.catalystUrl,
75
+ segmentKey: dclInfo.segmentKey
76
+ };
77
+ return removeEmptyKeys(dclInfoConfig);
78
+ }
79
+ function getEnvConfig() {
80
+ const { RPC_URL, MANA_TOKEN, LAND_REGISTRY, ESTATE_REGISTRY, CONTENT_URL, SEGMENT_KEY } = process.env;
81
+ const envConfig = {
82
+ provider: RPC_URL,
83
+ MANAToken: MANA_TOKEN,
84
+ LANDRegistry: LAND_REGISTRY,
85
+ EstateRegistry: ESTATE_REGISTRY,
86
+ contentUrl: CONTENT_URL,
87
+ segmentKey: SEGMENT_KEY
88
+ };
89
+ return removeEmptyKeys(envConfig);
90
+ }
@@ -1 +1 @@
1
- export declare function previewPort(): Promise<number>;
1
+ export declare function getPort(port?: number, failoverPort?: number): Promise<number>;
@@ -3,18 +3,18 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.previewPort = void 0;
6
+ exports.getPort = void 0;
7
7
  const portfinder_1 = __importDefault(require("portfinder"));
8
- async function previewPort() {
9
- let resolvedPort = 0;
8
+ async function getPort(port = 0, failoverPort = 2044) {
9
+ let resolvedPort = port && Number.isInteger(port) ? port : 0;
10
10
  if (!resolvedPort) {
11
11
  try {
12
- resolvedPort = await portfinder_1.default.getPortPromise();
12
+ resolvedPort = await portfinder_1.default.getPortPromise({ port: resolvedPort });
13
13
  }
14
14
  catch (e) {
15
- resolvedPort = 2044;
15
+ resolvedPort = failoverPort;
16
16
  }
17
17
  }
18
18
  return resolvedPort;
19
19
  }
20
- exports.previewPort = previewPort;
20
+ exports.getPort = getPort;
@@ -1,6 +1,5 @@
1
1
  import { ContentMapping } from '@dcl/schemas/dist/misc/content-mapping';
2
2
  import { CliComponents } from '../components';
3
- import { Scene } from '@dcl/schemas';
4
3
  /**
5
4
  * Returns an array of the publishable files for a given folder.
6
5
  *
@@ -17,5 +16,4 @@ export declare function normalizeDecentralandFilename(filename: string): string;
17
16
  * Returns the content mappings for a specific project folder.
18
17
  */
19
18
  export declare function getProjectContentMappings(components: Pick<CliComponents, 'fs'>, projectRoot: string, hashingFunction: (filePath: string) => Promise<string>): Promise<ContentMapping[]>;
20
- export declare function getSceneJson(components: Pick<CliComponents, 'fs'>, projectRoot: string): Promise<Scene>;
21
19
  export declare const b64HashingFunction: (str: string) => Promise<string>;
@@ -3,13 +3,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.b64HashingFunction = exports.getSceneJson = exports.getProjectContentMappings = exports.normalizeDecentralandFilename = exports.getPublishableFiles = void 0;
6
+ exports.b64HashingFunction = exports.getProjectContentMappings = exports.normalizeDecentralandFilename = exports.getPublishableFiles = void 0;
7
7
  const dcl_ignore_1 = require("./dcl-ignore");
8
8
  const glob_1 = require("glob");
9
9
  const ignore_1 = __importDefault(require("ignore"));
10
10
  const path_1 = __importDefault(require("path"));
11
11
  const error_1 = require("./error");
12
- const scene_validations_1 = require("./scene-validations");
13
12
  /**
14
13
  * Returns an array of the publishable files for a given folder.
15
14
  *
@@ -60,6 +59,7 @@ hashingFunction) {
60
59
  if (usedFilenames.has(normalizedFile)) {
61
60
  throw new error_1.CliError(`DuplicatedFilenameError: the file ${file} exists with a different casing. Please manually remove one occurrence`);
62
61
  }
62
+ usedFilenames.add(normalizedFile);
63
63
  ret.push({
64
64
  file: normalizedFile,
65
65
  hash: await hashingFunction(absolutePath)
@@ -68,11 +68,5 @@ hashingFunction) {
68
68
  return ret;
69
69
  }
70
70
  exports.getProjectContentMappings = getProjectContentMappings;
71
- async function getSceneJson(components, projectRoot) {
72
- const sceneJsonContent = await components.fs.readFile((0, scene_validations_1.getSceneFilePath)(projectRoot), 'utf8');
73
- const sceneJson = JSON.parse(sceneJsonContent);
74
- return sceneJson;
75
- }
76
- exports.getSceneJson = getSceneJson;
77
71
  const b64HashingFunction = async (str) => 'b64-' + Buffer.from(str).toString('base64');
78
72
  exports.b64HashingFunction = b64HashingFunction;
@@ -16,7 +16,7 @@ async function assertValidProjectFolder(components, projectRoot) {
16
16
  switch (true) {
17
17
  // case wearable
18
18
  case await components.fs.fileExists((0, path_1.resolve)(projectRoot, 'scene.json')): {
19
- return { scene: await (0, scene_validations_1.validateSceneJson)(components, projectRoot) };
19
+ return { scene: await (0, scene_validations_1.getValidSceneJson)(components, projectRoot) };
20
20
  }
21
21
  default: {
22
22
  throw new error_1.CliError(`UnknownProjectKind: the kind of project of the folder ${projectRoot} cannot be identified`);
@@ -1,17 +1,32 @@
1
+ /// <reference types="node" />
1
2
  import { Scene } from '@dcl/schemas';
2
3
  import { CliComponents } from '../components';
4
+ export interface IFile {
5
+ path: string;
6
+ content: Buffer;
7
+ size: number;
8
+ }
3
9
  export declare const SCENE_FILE = "scene.json";
10
+ export declare const MAX_FILE_SIZE_BYTES: number;
4
11
  /**
5
12
  * Composes the path to the `scene.json` file based on the provided path.
6
13
  * @param projectRoot The path to the directory containing the scene file.
7
14
  */
8
15
  export declare function getSceneFilePath(projectRoot: string): string;
9
- export declare function assertValidScene(scene: Scene): Scene;
16
+ export declare function assertValidScene(scene: Scene): void;
10
17
  /**
11
- * Fails the execution if one of the parcel data is invalid
18
+ * Get valid Scene JSON
12
19
  */
13
- export declare function validateSceneJson(components: Pick<CliComponents, 'fs' | 'logger'>, projectRoot: string): Promise<Scene>;
20
+ export declare function getValidSceneJson(components: Pick<CliComponents, 'fs' | 'logger'>, projectRoot: string): Promise<Scene>;
14
21
  export declare function getBaseCoords(scene: Scene): {
15
22
  x: number;
16
23
  y: number;
17
24
  };
25
+ /**
26
+ * Returns a promise of an array of objects containing the path and the content for all the files in the project.
27
+ * All the paths added to the `.dclignore` file will be excluded from the results.
28
+ * Windows directory separators are replaced for POSIX separators.
29
+ * @param ignoreFile The contents of the .dclignore file
30
+ */
31
+ export declare function getFiles(components: Pick<CliComponents, 'fs' | 'logger'>, dir: string): Promise<IFile[]>;
32
+ export declare function validateFilesSizes(files: IFile[]): void;
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getBaseCoords = exports.validateSceneJson = exports.assertValidScene = exports.getSceneFilePath = exports.SCENE_FILE = void 0;
3
+ exports.validateFilesSizes = exports.getFiles = exports.getBaseCoords = exports.getValidSceneJson = exports.assertValidScene = exports.getSceneFilePath = exports.MAX_FILE_SIZE_BYTES = exports.SCENE_FILE = void 0;
4
4
  const path_1 = require("path");
5
5
  const schemas_1 = require("@dcl/schemas");
6
6
  const error_1 = require("./error");
7
7
  const coordinates_1 = require("./coordinates");
8
8
  const project_files_1 = require("./project-files");
9
9
  exports.SCENE_FILE = 'scene.json';
10
+ exports.MAX_FILE_SIZE_BYTES = 50 * 1e6; // 50mb
10
11
  /**
11
12
  * Composes the path to the `scene.json` file based on the provided path.
12
13
  * @param projectRoot The path to the directory containing the scene file.
@@ -46,22 +47,23 @@ function assertValidScene(scene) {
46
47
  if (!scene.main?.endsWith('.js')) {
47
48
  throw new error_1.CliError(`Main scene format file (${scene.main}) is not a supported format`);
48
49
  }
49
- return scene;
50
50
  }
51
51
  exports.assertValidScene = assertValidScene;
52
52
  /**
53
- * Fails the execution if one of the parcel data is invalid
53
+ * Get valid Scene JSON
54
54
  */
55
- async function validateSceneJson(components, projectRoot) {
55
+ async function getValidSceneJson(components, projectRoot) {
56
56
  try {
57
- const sceneJson = await (0, project_files_1.getSceneJson)(components, projectRoot);
58
- return assertValidScene(sceneJson);
57
+ const sceneJsonRaw = await components.fs.readFile(getSceneFilePath(projectRoot), 'utf8');
58
+ const sceneJson = JSON.parse(sceneJsonRaw);
59
+ assertValidScene(sceneJson);
60
+ return sceneJson;
59
61
  }
60
62
  catch (err) {
61
63
  throw new error_1.CliError(`Error reading the scene.json file: ${err.message}`);
62
64
  }
63
65
  }
64
- exports.validateSceneJson = validateSceneJson;
66
+ exports.getValidSceneJson = getValidSceneJson;
65
67
  function getBaseCoords(scene) {
66
68
  const [x, y] = scene.scene.base
67
69
  .replace(/\ /g, '')
@@ -70,3 +72,34 @@ function getBaseCoords(scene) {
70
72
  return { x, y };
71
73
  }
72
74
  exports.getBaseCoords = getBaseCoords;
75
+ /**
76
+ * Returns a promise of an array of objects containing the path and the content for all the files in the project.
77
+ * All the paths added to the `.dclignore` file will be excluded from the results.
78
+ * Windows directory separators are replaced for POSIX separators.
79
+ * @param ignoreFile The contents of the .dclignore file
80
+ */
81
+ async function getFiles(components, dir) {
82
+ const files = await (0, project_files_1.getPublishableFiles)(components, dir);
83
+ const data = [];
84
+ for (let i = 0; i < files.length; i++) {
85
+ const file = files[i];
86
+ const filePath = (0, path_1.resolve)(dir, file);
87
+ const stat = await components.fs.stat(filePath);
88
+ const content = await components.fs.readFile(filePath);
89
+ data.push({
90
+ path: file.replace(/\\/g, '/'),
91
+ content: Buffer.from(content),
92
+ size: stat.size
93
+ });
94
+ }
95
+ return data;
96
+ }
97
+ exports.getFiles = getFiles;
98
+ function validateFilesSizes(files) {
99
+ for (const { path, size } of files) {
100
+ if (size > exports.MAX_FILE_SIZE_BYTES) {
101
+ throw new error_1.CliError(`Maximum file size exceeded: '${path}' is larger than ${exports.MAX_FILE_SIZE_BYTES / 1e6}MB`);
102
+ }
103
+ }
104
+ }
105
+ exports.validateFilesSizes = validateFilesSizes;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dcl/sdk-commands",
3
- "version": "7.0.0-4294380152.commit-0d08b10",
3
+ "version": "7.0.0-4295573637.commit-6d503ad",
4
4
  "description": "",
5
5
  "scripts": {
6
6
  "build": "tsc -p tsconfig.json",
@@ -16,8 +16,9 @@
16
16
  "author": "Decentraland",
17
17
  "license": "Apache-2.0",
18
18
  "dependencies": {
19
- "@dcl/dcl-rollup": "7.0.6-4294380152.commit-0d08b10",
19
+ "@dcl/dcl-rollup": "7.0.6-4295573637.commit-6d503ad",
20
20
  "@dcl/hashing": "1.1.3",
21
+ "@dcl/linker-dapp": "0.7.0",
21
22
  "@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be",
22
23
  "@dcl/protocol": "1.0.0-4114477251.commit-ccb88d6",
23
24
  "@dcl/schemas": "6.10.0",
@@ -29,6 +30,7 @@
29
30
  "arg": "5.0.2",
30
31
  "chokidar": "^3.5.3",
31
32
  "colorette": "^2.0.19",
33
+ "dcl-catalyst-client": "^14.0.9",
32
34
  "extract-zip": "2.0.1",
33
35
  "ignore": "^5.2.4",
34
36
  "node-fetch": "^2.6.8",
@@ -52,5 +54,5 @@
52
54
  "files": [
53
55
  "dist"
54
56
  ],
55
- "commit": "0d08b10653a3c1b7ccac2fec26b0e3fdf2d6e98b"
57
+ "commit": "6d503ad455f1a93eca45772ca3ba698f7ad6e089"
56
58
  }