diff --git a/package-lock.json b/package-lock.json index d7323e5..94faccf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "@dcl/mini-rpc": "^1.0.7", "@dcl/schemas": "^11.10.4", - "@dcl/sdk": "^7.6.2", + "@dcl/sdk": "^7.6.4", "@segment/analytics-node": "^2.1.2", "cmd-shim": "^6.0.3", "decentraland-connect": "^7.1.0", @@ -1693,9 +1693,9 @@ } }, "node_modules/@dcl/ecs": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.6.2.tgz", - "integrity": "sha512-b7oEVQyYZbj84lLO8An97vPN0ZiAC9OquH/Z6eQCVBbtl3xMJMgRoVNPKfp5I3B1B0zoZiX5hGTK+Cju4RG6oQ==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@dcl/ecs/-/ecs-7.6.4.tgz", + "integrity": "sha512-XCxBn9CgXo6+7me1ty/zcN8oDDVXGOt1JTB/pSsJvX6fnjuRHXvGheTu6AMc2Vx6SZNaOqrk1U3/MDDYX5okwA==", "license": "Apache-2.0" }, "node_modules/@dcl/ecs-math": { @@ -1720,18 +1720,18 @@ } }, "node_modules/@dcl/inspector": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.6.2.tgz", - "integrity": "sha512-mBmOg2CP5xaHeoriWWpYHnRmg8NHcwDErVsA5H8gS/gV6y4knbh9ifoDOS8iWXjPlyugQFtYhV+L9T+CK4MU/Q==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@dcl/inspector/-/inspector-7.6.4.tgz", + "integrity": "sha512-+zq3X8LbJLi6VlRKoioGQ8gPemf7dMRBNY91hHTAyyprdUaFTfQ8eFiKhpt7xuzuOD32tyb/kNWHxYKbT7Lh3Q==", "dependencies": { "@dcl/asset-packs": "1.20.2", "ts-deepmerge": "^7.0.0" } }, "node_modules/@dcl/js-runtime": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.6.2.tgz", - "integrity": "sha512-Zsw9xZLU+lAU+Tr6o/9YAHxj3Nr8yU8yJkp4ZuIpZQ1kUX1LFarMb3eiMx4sfrd50tCJPvAt8yJg6mYbmJJlBw==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@dcl/js-runtime/-/js-runtime-7.6.4.tgz", + "integrity": "sha512-SVTZXhmE+jK551Yl5ofOgmvuhUBlYc5yTj4+Iqt3tCeNcQVE2kX93vOhlo6lJRHhjTc7wC92fQB5FrYIFOO+iQ==", "license": "Apache-2.0" }, "node_modules/@dcl/linker-dapp": { @@ -1780,9 +1780,9 @@ } }, "node_modules/@dcl/protocol": { - "version": "1.0.0-10955038136.commit-7fe9554", - "resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-10955038136.commit-7fe9554.tgz", - "integrity": "sha512-0BcRTJxFhxpX1k4oN8ErL+HiJYDmd98aDh6Kti54zoCph3SlJqkq0r1KshHAeMaXLSKNRtljjgkf4KkB8MriKA==", + "version": "1.0.0-11406954347.commit-ba19c4f", + "resolved": "https://registry.npmjs.org/@dcl/protocol/-/protocol-1.0.0-11406954347.commit-ba19c4f.tgz", + "integrity": "sha512-oMoq5IKAe1gout5SbP2w3Jq3Im+tbUiREW70BC+aVwwOly0YDtTWTZG9FyjeF36RDhyCg7z6jwtHL/rbWp0skw==", "license": "Apache-2.0", "dependencies": { "@dcl/ts-proto": "1.154.0" @@ -1807,12 +1807,12 @@ "license": "Apache-2.0" }, "node_modules/@dcl/react-ecs": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.6.2.tgz", - "integrity": "sha512-p9I/CIWldRNhJSSEfOw/cXQHUuEuJsIvZnPPlPxN2QhWJOhYOU6tPEf5Wt6aVGWonIz4xISUaH5fOkqnW1eIIQ==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@dcl/react-ecs/-/react-ecs-7.6.4.tgz", + "integrity": "sha512-U/9h4M76zuKu+3gowa7XNYGDLAEVbuShe7WuNn5YCM1xG7T6diCtVMm/Y9mJkQZv1zQQmZWRq/gCSTQ96/hjwg==", "license": "Apache-2.0", "dependencies": { - "@dcl/ecs": "7.6.2", + "@dcl/ecs": "7.6.4", "react": "^18.2.0", "react-reconciler": "^0.29.0" } @@ -1839,33 +1839,33 @@ } }, "node_modules/@dcl/sdk": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.6.2.tgz", - "integrity": "sha512-ddyF33zjGGcFV6o35o0Mhup/9tq6Akb1NtNzrQpZImVQZq1eRsk8DSsA17LjrQZNfNFGucmbvrCcwStO3p4hHQ==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@dcl/sdk/-/sdk-7.6.4.tgz", + "integrity": "sha512-AeScYmNChQLclNSCo9LMBqia4EeT/Ny7cfApHtZj+0bg1oAEZHFXbttQjymTtyou6wO42gnUVgCVufKqVGaDKA==", "license": "Apache-2.0", "dependencies": { - "@dcl/ecs": "7.6.2", + "@dcl/ecs": "7.6.4", "@dcl/ecs-math": "2.0.2", "@dcl/explorer": "1.0.164509-20240802172549.commit-fb95b9b", - "@dcl/js-runtime": "7.6.2", - "@dcl/react-ecs": "7.6.2", - "@dcl/sdk-commands": "7.6.2", + "@dcl/js-runtime": "7.6.4", + "@dcl/react-ecs": "7.6.4", + "@dcl/sdk-commands": "7.6.4", "text-encoding": "0.7.0" } }, "node_modules/@dcl/sdk-commands": { - "version": "7.6.2", - "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.6.2.tgz", - "integrity": "sha512-ILDrLjQ2gB+oevj8fKscTtv93EWxPF0cx+6n7GJpVqCYR1/dYmiTmsCh2NqrUPtrXQObaJzqmeFH3jJfk2k5VA==", + "version": "7.6.4", + "resolved": "https://registry.npmjs.org/@dcl/sdk-commands/-/sdk-commands-7.6.4.tgz", + "integrity": "sha512-dwz2Ev3j2Wc8h9QDJoth5aDH3Irj+CeZXI/owBqAWK0R0t6NJ/TUvP5JFTKyFUFQEx8aSmW99im1c/egXFrsnA==", "license": "Apache-2.0", "dependencies": { "@dcl/crypto": "^3.4.4", - "@dcl/ecs": "7.6.2", + "@dcl/ecs": "7.6.4", "@dcl/hashing": "1.1.3", - "@dcl/inspector": "7.6.2", + "@dcl/inspector": "7.6.4", "@dcl/linker-dapp": "^0.14.2", "@dcl/mini-comms": "1.0.1-20230216163137.commit-a4c75be", - "@dcl/protocol": "1.0.0-10955038136.commit-7fe9554", + "@dcl/protocol": "1.0.0-11406954347.commit-ba19c4f", "@dcl/quests-client": "^1.0.3", "@dcl/quests-manager": "^0.1.4", "@dcl/rpc": "^1.1.1", diff --git a/package.json b/package.json index 87b29f9..69cd79f 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "dependencies": { "@dcl/mini-rpc": "^1.0.7", "@dcl/schemas": "^11.10.4", - "@dcl/sdk": "^7.6.2", + "@dcl/sdk": "^7.6.4", "@segment/analytics-node": "^2.1.2", "cmd-shim": "^6.0.3", "decentraland-connect": "^7.1.0", diff --git a/packages/main/src/modules/analytics.ts b/packages/main/src/modules/analytics.ts index 59c203b..c4d7eb8 100644 --- a/packages/main/src/modules/analytics.ts +++ b/packages/main/src/modules/analytics.ts @@ -1,7 +1,10 @@ import { Analytics, type TrackParams } from '@segment/analytics-node'; +import path from 'node:path'; import log from 'electron-log'; -import { randomUUID } from 'node:crypto'; +import { randomUUID, type UUID } from 'node:crypto'; +import { FileSystemStorage } from '/shared/types/storage'; import { config } from './config'; +import { getWorkspaceConfigPath } from './electron'; let analytics: Analytics | null = null; const sessionId = randomUUID(); @@ -76,3 +79,15 @@ export async function identify(userId: string, traits: Record = {}) // do nothing } } + +export async function getProjectId(_path: string): Promise { + const projectInfoPath = path.join(await getWorkspaceConfigPath(_path), 'project.json'); + const projectInfo = new FileSystemStorage(projectInfoPath); + const hasId = await projectInfo.has('id'); + if (!hasId) { + const projectId = randomUUID(); + await projectInfo.set('id', projectId); + return projectId; + } + return projectInfo.get('id'); +} diff --git a/packages/main/src/modules/cli.ts b/packages/main/src/modules/cli.ts index 1d49c13..35ceb29 100644 --- a/packages/main/src/modules/cli.ts +++ b/packages/main/src/modules/cli.ts @@ -2,11 +2,21 @@ import type { DeployOptions } from '/shared/types/ipc'; import { run, type Child } from './bin'; import { getAvailablePort } from './port'; import { install } from './npm'; +import { getProjectId } from './analytics'; + +async function getEnv(path: string) { + const projectId = await getProjectId(path); + return { + ANALYTICS_PROJECT_ID: projectId, + ANALYTICS_APP_ID: 'creator-hub', + }; +} export async function init(path: string, repo?: string) { const initCommand = run('@dcl/sdk-commands', 'sdk-commands', { args: ['init', '--yes', '--skip-install', ...(repo ? ['--github-repo', repo] : [])], cwd: path, + env: await getEnv(path), }); await initCommand.wait(); } @@ -20,6 +30,7 @@ export async function start(path: string) { previewServer = run('@dcl/sdk-commands', 'sdk-commands', { args: ['start', '--explorer-alpha', '--hub'], cwd: path, + env: await getEnv(path), }); await previewServer.waitFor(/decentraland:\/\//i); } @@ -39,6 +50,7 @@ export async function deploy({ path, target, targetContent }: DeployOptions) { ...(targetContent ? ['--target-content', targetContent] : []), ], cwd: path, + env: await getEnv(path), }); // App ready at diff --git a/packages/main/src/modules/electron.ts b/packages/main/src/modules/electron.ts index 162dc45..17a767d 100644 --- a/packages/main/src/modules/electron.ts +++ b/packages/main/src/modules/electron.ts @@ -1,4 +1,5 @@ import path from 'path'; +import fs from 'fs/promises'; import { app, BrowserWindow, dialog, type OpenDialogOptions, shell } from 'electron'; export function getHome() { @@ -9,6 +10,16 @@ export function getAppHome() { return path.join(getHome(), '.decentraland'); } +export async function getWorkspaceConfigPath(_path: string) { + const editorHomePath = path.join(_path, '.editor'); + try { + await fs.stat(_path); + } catch (error) { + await fs.mkdir(editorHomePath, { recursive: true }); + } + return editorHomePath; +} + export async function showOpenDialog(opts: Partial): Promise { const window = BrowserWindow.getFocusedWindow(); if (!window) return []; diff --git a/packages/main/src/modules/ipc.ts b/packages/main/src/modules/ipc.ts index 711d0fe..6aaf6c9 100644 --- a/packages/main/src/modules/ipc.ts +++ b/packages/main/src/modules/ipc.ts @@ -10,6 +10,9 @@ export function initIpc() { // electron handle('electron.getAppVersion', () => electron.getAppVersion()); handle('electron.getAppHome', () => electron.getAppHome()); + handle('electron.getWorkspaceConfigPath', (_event, path) => + electron.getWorkspaceConfigPath(path), + ); handle('electron.showOpenDialog', (_event, opts) => electron.showOpenDialog(opts)); handle('electron.openExternal', (_event, url) => electron.openExternal(url)); @@ -29,6 +32,7 @@ export function initIpc() { handle('analytics.track', (_event, eventName, data) => analytics.track(eventName, data)); handle('analytics.identify', (_event, userId, traits) => analytics.identify(userId, traits)); handle('analytics.getAnonymousId', () => analytics.getAnonymousId()); + handle('analytics.getProjectId', (_event, path) => analytics.getProjectId(path)); // npm handle('npm.install', (_event, path, packages) => npm.install(path, packages)); diff --git a/packages/preload/src/modules/analytics.ts b/packages/preload/src/modules/analytics.ts index 3c2afd0..f7bbfae 100644 --- a/packages/preload/src/modules/analytics.ts +++ b/packages/preload/src/modules/analytics.ts @@ -11,3 +11,7 @@ export async function identify(userId: string, traits?: Record) { export async function getAnonymousId() { return invoke('analytics.getAnonymousId'); } + +export async function getProjectId(path: string) { + return invoke('analytics.getProjectId', path); +} diff --git a/packages/preload/src/modules/editor.ts b/packages/preload/src/modules/editor.ts index 423cab6..670ddf6 100644 --- a/packages/preload/src/modules/editor.ts +++ b/packages/preload/src/modules/editor.ts @@ -1,14 +1,9 @@ -import path from 'path'; - import type { DeployOptions } from '/shared/types/ipc'; import { invoke } from './invoke'; -import * as fs from './fs'; -export async function getEditorHome(_path: string) { - const editorHomePath = path.join(_path, '.editor'); - if (!(await fs.exists(editorHomePath))) await fs.mkdir(editorHomePath); - return editorHomePath; +export async function getWorkspaceConfigPath(_path: string) { + return invoke('electron.getWorkspaceConfigPath', _path); } export async function getVersion() { diff --git a/packages/preload/src/modules/workspace.ts b/packages/preload/src/modules/workspace.ts index 6828e72..07e7c0f 100644 --- a/packages/preload/src/modules/workspace.ts +++ b/packages/preload/src/modules/workspace.ts @@ -1,6 +1,5 @@ import fs from 'node:fs/promises'; import path from 'node:path'; -import { randomUUID, type UUID } from 'node:crypto'; import type { Scene } from '@dcl/schemas'; import { shell } from 'electron'; import equal from 'fast-deep-equal'; @@ -8,19 +7,19 @@ import equal from 'fast-deep-equal'; import { type DependencyState, SortBy, type Project } from '/shared/types/projects'; import { PACKAGES_LIST } from '/shared/types/pkg'; import { DEFAULT_DEPENDENCY_UPDATE_STRATEGY } from '/shared/types/settings'; -import { FileSystemStorage } from '/shared/types/storage'; import type { Template, Workspace } from '/shared/types/workspace'; import { getConfig, setConfig } from './config'; import { exists, writeFile as deepWriteFile } from './fs'; import { hasDependency } from './pkg'; import { getRowsAndCols, parseCoords } from './scene'; -import { getEditorHome } from './editor'; import { invoke } from './invoke'; import { getOudatedDeps } from './npm'; import { getDefaultScenesPath, getScenesPath } from './settings'; import { DEFAULT_THUMBNAIL, NEW_SCENE_NAME, EMPTY_SCENE_TEMPLATE_REPO } from './constants'; +import { getWorkspaceConfigPath } from './editor'; +import { getProjectId } from './analytics'; /** * Get scene json @@ -34,18 +33,6 @@ export async function getScene(_path: string): Promise { return JSON.parse(scene); } -export async function getProjectId(_path: string): Promise { - const projectInfoPath = path.join(await getEditorHome(_path), 'project.json'); - const projectInfo = new FileSystemStorage(projectInfoPath); - const hasId = await projectInfo.has('id'); - if (!hasId) { - const projectId = randomUUID(); - await projectInfo.set('id', projectId); - return projectId; - } - return projectInfo.get('id'); -} - /** * Returns whether or not the provided directory is a decentraland project or not */ @@ -79,8 +66,8 @@ export async function hasNodeModules(_path: string) { } export async function getProjectThumbnailPath(_path: string) { - const editorHomePath = await getEditorHome(_path); - return path.join(editorHomePath, 'images', 'project-thumbnail.png'); + const workspaceConfigPath = await getWorkspaceConfigPath(_path); + return path.join(workspaceConfigPath, 'images', 'project-thumbnail.png'); } export async function getProjectThumbnailAsBase64( diff --git a/packages/shared/types/ipc.ts b/packages/shared/types/ipc.ts index 20c8683..ce56b8b 100644 --- a/packages/shared/types/ipc.ts +++ b/packages/shared/types/ipc.ts @@ -7,6 +7,7 @@ export type DeployOptions = { path: string; target?: string; targetContent?: str export interface Ipc { 'electron.getAppHome': () => string; 'electron.getAppVersion': () => Promise; + 'electron.getWorkspaceConfigPath': (path: string) => Promise; 'electron.showOpenDialog': (opts: Partial) => Promise; 'electron.openExternal': (url: string) => Promise; 'inspector.start': () => Promise; @@ -18,6 +19,7 @@ export interface Ipc { 'analytics.track': (event: string, data?: Record) => void; 'analytics.identify': (userId: string, traits?: Record) => void; 'analytics.getAnonymousId': () => Promise; + 'analytics.getProjectId': (path: string) => Promise; 'npm.install': (path: string, packages?: string[]) => Promise; 'npm.getOutdatedDeps': (path: string, packages?: string[]) => Promise; }