@slicemachine/manager 0.9.3-dev-next-release.1 → 0.9.3-dev-next-release.3

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.
@@ -124,6 +124,10 @@ Error Message: ${error2.message}`);
124
124
  const sliceMachinePackageJSONPath = require2.resolve(`${SLICE_MACHINE_NPM_PACKAGE_NAME.SLICE_MACHINE_NPM_PACKAGE_NAME}/package.json`);
125
125
  return path__namespace.dirname(sliceMachinePackageJSONPath);
126
126
  }
127
+ async getRepositoryName() {
128
+ const sliceMachineConfig = await this.getSliceMachineConfig();
129
+ return sliceMachineConfig.repositoryName;
130
+ }
127
131
  async getAdapterName() {
128
132
  const sliceMachineConfig = await this.getSliceMachineConfig();
129
133
  const adapterName = typeof sliceMachineConfig.adapter === "string" ? sliceMachineConfig.adapter : sliceMachineConfig.adapter.resolve;
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectManager.cjs","sources":["../../../../src/managers/project/ProjectManager.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { detect as niDetect } from \"@antfu/ni\";\nimport { ExecaChildProcess } from \"execa\";\n\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { decodeSliceMachineConfig } from \"../../lib/decodeSliceMachineConfig\";\nimport { format } from \"../../lib/format\";\nimport { installDependencies } from \"../../lib/installDependencies\";\nimport { locateFileUpward } from \"../../lib/locateFileUpward\";\n\nimport { PackageManager, SliceMachineConfig } from \"../../types\";\n\nimport { SliceMachineError, InternalError } from \"../../errors\";\n\nimport { SLICE_MACHINE_CONFIG_FILENAME } from \"../../constants/SLICE_MACHINE_CONFIG_FILENAME\";\nimport { TS_CONFIG_FILENAME } from \"../../constants/TS_CONFIG_FILENAME\";\nimport { SLICE_MACHINE_NPM_PACKAGE_NAME } from \"../../constants/SLICE_MACHINE_NPM_PACKAGE_NAME\";\n\nimport { BaseManager } from \"../BaseManager\";\n\ntype ProjectManagerGetSliceMachineConfigPathArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerGetRootArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerCheckIsTypeScriptArgs = {\n\trootOverride?: string;\n};\n\ntype ProjectManagerWriteSliceMachineConfigArgs = {\n\tconfig: SliceMachineConfig;\n\tpath?: string;\n};\n\ntype ProjectManagerInitProjectArgs = {\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerDetectPackageManager = {\n\troot?: string;\n};\n\ntype ProjectManagerInstallDependenciesArgs = {\n\tdependencies: Record<string, string>;\n\tdev?: boolean;\n\tpackageManager?: PackageManager;\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerInstallDependenciesReturnType = {\n\texecaProcess: ExecaChildProcess;\n};\n\nexport class ProjectManager extends BaseManager {\n\tprivate _cachedRoot: string | undefined;\n\tprivate _cachedSliceMachineConfigPath: string | undefined;\n\tprivate _cachedSliceMachineConfig: SliceMachineConfig | undefined;\n\n\tasync getSliceMachineConfigPath(\n\t\targs?: ProjectManagerGetSliceMachineConfigPathArgs,\n\t): Promise<string> {\n\t\tif (this._cachedSliceMachineConfigPath && !args?.ignoreCache) {\n\t\t\treturn this._cachedSliceMachineConfigPath;\n\t\t}\n\n\t\ttry {\n\t\t\tthis._cachedSliceMachineConfigPath = await locateFileUpward(\n\t\t\t\tSLICE_MACHINE_CONFIG_FILENAME,\n\t\t\t\t{ startDir: this.cwd },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find a ${SLICE_MACHINE_CONFIG_FILENAME} file. Please create a config file at the root of your project.`,\n\t\t\t);\n\t\t}\n\n\t\treturn this._cachedSliceMachineConfigPath;\n\t}\n\n\tasync getRoot(args?: ProjectManagerGetRootArgs): Promise<string> {\n\t\tif (this._cachedRoot && !args?.ignoreCache) {\n\t\t\treturn this._cachedRoot;\n\t\t}\n\n\t\tconst sliceMachineConfigFilePath = await this.getSliceMachineConfigPath({\n\t\t\tignoreCache: args?.ignoreCache,\n\t\t});\n\n\t\tthis._cachedRoot = path.dirname(sliceMachineConfigFilePath);\n\n\t\treturn this._cachedRoot;\n\t}\n\n\tasync suggestRoot(): Promise<string> {\n\t\tconst suggestedRootPackageJSON = await locateFileUpward(\"package.json\", {\n\t\t\tstartDir: this.cwd,\n\t\t});\n\n\t\treturn path.dirname(suggestedRootPackageJSON);\n\t}\n\n\tasync suggestSliceMachineConfigPath(): Promise<string> {\n\t\tconst suggestedRoot = await this.suggestRoot();\n\n\t\treturn path.resolve(suggestedRoot, SLICE_MACHINE_CONFIG_FILENAME);\n\t}\n\n\tasync checkIsTypeScript(\n\t\targs?: ProjectManagerCheckIsTypeScriptArgs,\n\t): Promise<boolean> {\n\t\tconst root = args?.rootOverride || (await this.getRoot());\n\t\tconst rootTSConfigPath = path.resolve(root, TS_CONFIG_FILENAME);\n\n\t\t// We just care if the file exists, we don't need access to it\n\t\treturn existsSync(rootTSConfigPath);\n\t}\n\n\tasync getSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\tif (this._cachedSliceMachineConfig) {\n\t\t\treturn this._cachedSliceMachineConfig;\n\t\t} else {\n\t\t\treturn await this.loadSliceMachineConfig();\n\t\t}\n\t}\n\n\tasync writeSliceMachineConfig(\n\t\targs: ProjectManagerWriteSliceMachineConfigArgs,\n\t): Promise<void> {\n\t\tconst configFilePath =\n\t\t\targs.path || (await this.getSliceMachineConfigPath());\n\n\t\tconst config = await format(\n\t\t\tJSON.stringify(args.config, null, 2),\n\t\t\tconfigFilePath,\n\t\t);\n\n\t\tawait fs.writeFile(configFilePath, config, \"utf-8\");\n\t\tdelete this._cachedSliceMachineConfig; // Clear config cache\n\t}\n\n\tasync loadSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\t// TODO: Reload plugins with a fresh plugin runner. Plugins may\n\t\t// have been added or removed.\n\t\tconst configFilePath = await this.getSliceMachineConfigPath();\n\n\t\tlet rawConfig: unknown | undefined;\n\t\ttry {\n\t\t\tconst contents = await fs.readFile(configFilePath, \"utf8\");\n\t\t\trawConfig = JSON.parse(contents);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) {\n\t\t\t\tthrow new SliceMachineError(\n\t\t\t\t\t`Could not parse config file at ${configFilePath}.\\n\\nError Message: ${error.message}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Noop, more specific error is thrown after\n\t\t}\n\n\t\tif (!rawConfig) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(\"No config found.\");\n\t\t}\n\n\t\tconst { value: sliceMachineConfig, error } =\n\t\t\tdecodeSliceMachineConfig(rawConfig);\n\n\t\tif (error) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(`Invalid config. ${error.errors.join(\", \")}`);\n\t\t}\n\n\t\t// Allow cached config reading using `SliceMachineManager.prototype.getProjectConfig()`.\n\t\tthis._cachedSliceMachineConfig = sliceMachineConfig;\n\n\t\treturn sliceMachineConfig;\n\t}\n\n\tasync locateSliceMachineUIDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst sliceMachinePackageJSONPath = require.resolve(\n\t\t\t`${SLICE_MACHINE_NPM_PACKAGE_NAME}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(sliceMachinePackageJSONPath);\n\t}\n\n\tasync getAdapterName(): Promise<string> {\n\t\tconst sliceMachineConfig = await this.getSliceMachineConfig();\n\t\tconst adapterName =\n\t\t\ttypeof sliceMachineConfig.adapter === \"string\"\n\t\t\t\t? sliceMachineConfig.adapter\n\t\t\t\t: sliceMachineConfig.adapter.resolve;\n\n\t\treturn adapterName;\n\t}\n\n\tasync locateAdapterDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\t\tconst adapterName = await this.getAdapterName();\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst adapterPackageJSONPath = require.resolve(\n\t\t\t`${adapterName}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(adapterPackageJSONPath);\n\t}\n\n\tasync initProject(args?: ProjectManagerInitProjectArgs): Promise<void> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args?.log || console.log.bind(this);\n\n\t\tconst { errors } = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"project:init\",\n\t\t\t{\n\t\t\t\tlog,\n\t\t\t\tinstallDependencies: async (args) => {\n\t\t\t\t\tconst { execaProcess } = await this.installDependencies({\n\t\t\t\t\t\tdependencies: args.dependencies,\n\t\t\t\t\t\tdev: args.dev,\n\t\t\t\t\t\tlog,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait execaProcess;\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (errors.length > 0) {\n\t\t\t// TODO: Provide better error message.\n\t\t\tthrow new SliceMachineError(\n\t\t\t\t`Failed to initialize project: ${errors.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync detectPackageManager(\n\t\targs?: ProjectManagerDetectPackageManager,\n\t): Promise<PackageManager> {\n\t\tconst projectRoot = args?.root || (await this.getRoot());\n\n\t\tconst packageManager = await niDetect({\n\t\t\tautoInstall: true,\n\t\t\tcwd: projectRoot,\n\t\t});\n\n\t\treturn packageManager || \"npm\";\n\t}\n\n\tasync installDependencies(\n\t\targs: ProjectManagerInstallDependenciesArgs,\n\t): Promise<ProjectManagerInstallDependenciesReturnType> {\n\t\tconst packageManager =\n\t\t\targs.packageManager || (await this.detectPackageManager());\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args.log || console.log.bind(this);\n\n\t\tconst wrappedLogger = (data: Buffer | string | null) => {\n\t\t\tif (data instanceof Buffer) {\n\t\t\t\tlog(data.toString());\n\t\t\t} else if (typeof data === \"string\") {\n\t\t\t\tlog(data);\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tconst { execaProcess } = await installDependencies({\n\t\t\t\tpackageManager,\n\t\t\t\tdependencies: args.dependencies,\n\t\t\t\tdev: args.dev,\n\t\t\t});\n\n\t\t\t// Don't clutter console with logs when process is non TTY (CI, etc.)\n\t\t\tif (process.stdout.isTTY || process.env.NODE_ENV === \"test\") {\n\t\t\t\texecaProcess.stdout?.on(\"data\", wrappedLogger);\n\t\t\t}\n\t\t\texecaProcess.stderr?.on(\"data\", wrappedLogger);\n\n\t\t\treturn {\n\t\t\t\texecaProcess,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t\"shortMessage\" in error &&\n\t\t\t\t\"stderr\" in error\n\t\t\t) {\n\t\t\t\tthrow new InternalError(\"Package installation failed\", {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"],"names":["BaseManager","locateFileUpward","SLICE_MACHINE_CONFIG_FILENAME","path","TS_CONFIG_FILENAME","existsSync","format","fs","error","SliceMachineError","decodeSliceMachineConfig","require","createRequire","SLICE_MACHINE_NPM_PACKAGE_NAME","assertPluginsInitialized","errors","args","niDetect","installDependencies","InternalError"],"mappings":"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"}
1
+ {"version":3,"file":"ProjectManager.cjs","sources":["../../../../src/managers/project/ProjectManager.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { detect as niDetect } from \"@antfu/ni\";\nimport { ExecaChildProcess } from \"execa\";\n\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { decodeSliceMachineConfig } from \"../../lib/decodeSliceMachineConfig\";\nimport { format } from \"../../lib/format\";\nimport { installDependencies } from \"../../lib/installDependencies\";\nimport { locateFileUpward } from \"../../lib/locateFileUpward\";\n\nimport { PackageManager, SliceMachineConfig } from \"../../types\";\n\nimport { SliceMachineError, InternalError } from \"../../errors\";\n\nimport { SLICE_MACHINE_CONFIG_FILENAME } from \"../../constants/SLICE_MACHINE_CONFIG_FILENAME\";\nimport { TS_CONFIG_FILENAME } from \"../../constants/TS_CONFIG_FILENAME\";\nimport { SLICE_MACHINE_NPM_PACKAGE_NAME } from \"../../constants/SLICE_MACHINE_NPM_PACKAGE_NAME\";\n\nimport { BaseManager } from \"../BaseManager\";\n\ntype ProjectManagerGetSliceMachineConfigPathArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerGetRootArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerCheckIsTypeScriptArgs = {\n\trootOverride?: string;\n};\n\ntype ProjectManagerWriteSliceMachineConfigArgs = {\n\tconfig: SliceMachineConfig;\n\tpath?: string;\n};\n\ntype ProjectManagerInitProjectArgs = {\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerDetectPackageManager = {\n\troot?: string;\n};\n\ntype ProjectManagerInstallDependenciesArgs = {\n\tdependencies: Record<string, string>;\n\tdev?: boolean;\n\tpackageManager?: PackageManager;\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerInstallDependenciesReturnType = {\n\texecaProcess: ExecaChildProcess;\n};\n\nexport class ProjectManager extends BaseManager {\n\tprivate _cachedRoot: string | undefined;\n\tprivate _cachedSliceMachineConfigPath: string | undefined;\n\tprivate _cachedSliceMachineConfig: SliceMachineConfig | undefined;\n\n\tasync getSliceMachineConfigPath(\n\t\targs?: ProjectManagerGetSliceMachineConfigPathArgs,\n\t): Promise<string> {\n\t\tif (this._cachedSliceMachineConfigPath && !args?.ignoreCache) {\n\t\t\treturn this._cachedSliceMachineConfigPath;\n\t\t}\n\n\t\ttry {\n\t\t\tthis._cachedSliceMachineConfigPath = await locateFileUpward(\n\t\t\t\tSLICE_MACHINE_CONFIG_FILENAME,\n\t\t\t\t{ startDir: this.cwd },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find a ${SLICE_MACHINE_CONFIG_FILENAME} file. Please create a config file at the root of your project.`,\n\t\t\t);\n\t\t}\n\n\t\treturn this._cachedSliceMachineConfigPath;\n\t}\n\n\tasync getRoot(args?: ProjectManagerGetRootArgs): Promise<string> {\n\t\tif (this._cachedRoot && !args?.ignoreCache) {\n\t\t\treturn this._cachedRoot;\n\t\t}\n\n\t\tconst sliceMachineConfigFilePath = await this.getSliceMachineConfigPath({\n\t\t\tignoreCache: args?.ignoreCache,\n\t\t});\n\n\t\tthis._cachedRoot = path.dirname(sliceMachineConfigFilePath);\n\n\t\treturn this._cachedRoot;\n\t}\n\n\tasync suggestRoot(): Promise<string> {\n\t\tconst suggestedRootPackageJSON = await locateFileUpward(\"package.json\", {\n\t\t\tstartDir: this.cwd,\n\t\t});\n\n\t\treturn path.dirname(suggestedRootPackageJSON);\n\t}\n\n\tasync suggestSliceMachineConfigPath(): Promise<string> {\n\t\tconst suggestedRoot = await this.suggestRoot();\n\n\t\treturn path.resolve(suggestedRoot, SLICE_MACHINE_CONFIG_FILENAME);\n\t}\n\n\tasync checkIsTypeScript(\n\t\targs?: ProjectManagerCheckIsTypeScriptArgs,\n\t): Promise<boolean> {\n\t\tconst root = args?.rootOverride || (await this.getRoot());\n\t\tconst rootTSConfigPath = path.resolve(root, TS_CONFIG_FILENAME);\n\n\t\t// We just care if the file exists, we don't need access to it\n\t\treturn existsSync(rootTSConfigPath);\n\t}\n\n\tasync getSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\tif (this._cachedSliceMachineConfig) {\n\t\t\treturn this._cachedSliceMachineConfig;\n\t\t} else {\n\t\t\treturn await this.loadSliceMachineConfig();\n\t\t}\n\t}\n\n\tasync writeSliceMachineConfig(\n\t\targs: ProjectManagerWriteSliceMachineConfigArgs,\n\t): Promise<void> {\n\t\tconst configFilePath =\n\t\t\targs.path || (await this.getSliceMachineConfigPath());\n\n\t\tconst config = await format(\n\t\t\tJSON.stringify(args.config, null, 2),\n\t\t\tconfigFilePath,\n\t\t);\n\n\t\tawait fs.writeFile(configFilePath, config, \"utf-8\");\n\t\tdelete this._cachedSliceMachineConfig; // Clear config cache\n\t}\n\n\tasync loadSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\t// TODO: Reload plugins with a fresh plugin runner. Plugins may\n\t\t// have been added or removed.\n\t\tconst configFilePath = await this.getSliceMachineConfigPath();\n\n\t\tlet rawConfig: unknown | undefined;\n\t\ttry {\n\t\t\tconst contents = await fs.readFile(configFilePath, \"utf8\");\n\t\t\trawConfig = JSON.parse(contents);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) {\n\t\t\t\tthrow new SliceMachineError(\n\t\t\t\t\t`Could not parse config file at ${configFilePath}.\\n\\nError Message: ${error.message}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Noop, more specific error is thrown after\n\t\t}\n\n\t\tif (!rawConfig) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(\"No config found.\");\n\t\t}\n\n\t\tconst { value: sliceMachineConfig, error } =\n\t\t\tdecodeSliceMachineConfig(rawConfig);\n\n\t\tif (error) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(`Invalid config. ${error.errors.join(\", \")}`);\n\t\t}\n\n\t\t// Allow cached config reading using `SliceMachineManager.prototype.getProjectConfig()`.\n\t\tthis._cachedSliceMachineConfig = sliceMachineConfig;\n\n\t\treturn sliceMachineConfig;\n\t}\n\n\tasync locateSliceMachineUIDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst sliceMachinePackageJSONPath = require.resolve(\n\t\t\t`${SLICE_MACHINE_NPM_PACKAGE_NAME}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(sliceMachinePackageJSONPath);\n\t}\n\n\tasync getRepositoryName(): Promise<string> {\n\t\tconst sliceMachineConfig = await this.getSliceMachineConfig();\n\n\t\treturn sliceMachineConfig.repositoryName;\n\t}\n\n\tasync getAdapterName(): Promise<string> {\n\t\tconst sliceMachineConfig = await this.getSliceMachineConfig();\n\t\tconst adapterName =\n\t\t\ttypeof sliceMachineConfig.adapter === \"string\"\n\t\t\t\t? sliceMachineConfig.adapter\n\t\t\t\t: sliceMachineConfig.adapter.resolve;\n\n\t\treturn adapterName;\n\t}\n\n\tasync locateAdapterDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\t\tconst adapterName = await this.getAdapterName();\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst adapterPackageJSONPath = require.resolve(\n\t\t\t`${adapterName}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(adapterPackageJSONPath);\n\t}\n\n\tasync initProject(args?: ProjectManagerInitProjectArgs): Promise<void> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args?.log || console.log.bind(this);\n\n\t\tconst { errors } = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"project:init\",\n\t\t\t{\n\t\t\t\tlog,\n\t\t\t\tinstallDependencies: async (args) => {\n\t\t\t\t\tconst { execaProcess } = await this.installDependencies({\n\t\t\t\t\t\tdependencies: args.dependencies,\n\t\t\t\t\t\tdev: args.dev,\n\t\t\t\t\t\tlog,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait execaProcess;\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (errors.length > 0) {\n\t\t\t// TODO: Provide better error message.\n\t\t\tthrow new SliceMachineError(\n\t\t\t\t`Failed to initialize project: ${errors.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync detectPackageManager(\n\t\targs?: ProjectManagerDetectPackageManager,\n\t): Promise<PackageManager> {\n\t\tconst projectRoot = args?.root || (await this.getRoot());\n\n\t\tconst packageManager = await niDetect({\n\t\t\tautoInstall: true,\n\t\t\tcwd: projectRoot,\n\t\t});\n\n\t\treturn packageManager || \"npm\";\n\t}\n\n\tasync installDependencies(\n\t\targs: ProjectManagerInstallDependenciesArgs,\n\t): Promise<ProjectManagerInstallDependenciesReturnType> {\n\t\tconst packageManager =\n\t\t\targs.packageManager || (await this.detectPackageManager());\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args.log || console.log.bind(this);\n\n\t\tconst wrappedLogger = (data: Buffer | string | null) => {\n\t\t\tif (data instanceof Buffer) {\n\t\t\t\tlog(data.toString());\n\t\t\t} else if (typeof data === \"string\") {\n\t\t\t\tlog(data);\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tconst { execaProcess } = await installDependencies({\n\t\t\t\tpackageManager,\n\t\t\t\tdependencies: args.dependencies,\n\t\t\t\tdev: args.dev,\n\t\t\t});\n\n\t\t\t// Don't clutter console with logs when process is non TTY (CI, etc.)\n\t\t\tif (process.stdout.isTTY || process.env.NODE_ENV === \"test\") {\n\t\t\t\texecaProcess.stdout?.on(\"data\", wrappedLogger);\n\t\t\t}\n\t\t\texecaProcess.stderr?.on(\"data\", wrappedLogger);\n\n\t\t\treturn {\n\t\t\t\texecaProcess,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t\"shortMessage\" in error &&\n\t\t\t\t\"stderr\" in error\n\t\t\t) {\n\t\t\t\tthrow new InternalError(\"Package installation failed\", {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"],"names":["BaseManager","locateFileUpward","SLICE_MACHINE_CONFIG_FILENAME","path","TS_CONFIG_FILENAME","existsSync","format","fs","error","SliceMachineError","decodeSliceMachineConfig","require","createRequire","SLICE_MACHINE_NPM_PACKAGE_NAME","assertPluginsInitialized","errors","args","niDetect","installDependencies","InternalError"],"mappings":"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"}
@@ -42,6 +42,7 @@ export declare class ProjectManager extends BaseManager {
42
42
  writeSliceMachineConfig(args: ProjectManagerWriteSliceMachineConfigArgs): Promise<void>;
43
43
  loadSliceMachineConfig(): Promise<SliceMachineConfig>;
44
44
  locateSliceMachineUIDir(): Promise<string>;
45
+ getRepositoryName(): Promise<string>;
45
46
  getAdapterName(): Promise<string>;
46
47
  locateAdapterDir(): Promise<string>;
47
48
  initProject(args?: ProjectManagerInitProjectArgs): Promise<void>;
@@ -104,6 +104,10 @@ Error Message: ${error2.message}`);
104
104
  const sliceMachinePackageJSONPath = require2.resolve(`${SLICE_MACHINE_NPM_PACKAGE_NAME}/package.json`);
105
105
  return path.dirname(sliceMachinePackageJSONPath);
106
106
  }
107
+ async getRepositoryName() {
108
+ const sliceMachineConfig = await this.getSliceMachineConfig();
109
+ return sliceMachineConfig.repositoryName;
110
+ }
107
111
  async getAdapterName() {
108
112
  const sliceMachineConfig = await this.getSliceMachineConfig();
109
113
  const adapterName = typeof sliceMachineConfig.adapter === "string" ? sliceMachineConfig.adapter : sliceMachineConfig.adapter.resolve;
@@ -1 +1 @@
1
- {"version":3,"file":"ProjectManager.js","sources":["../../../../src/managers/project/ProjectManager.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { detect as niDetect } from \"@antfu/ni\";\nimport { ExecaChildProcess } from \"execa\";\n\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { decodeSliceMachineConfig } from \"../../lib/decodeSliceMachineConfig\";\nimport { format } from \"../../lib/format\";\nimport { installDependencies } from \"../../lib/installDependencies\";\nimport { locateFileUpward } from \"../../lib/locateFileUpward\";\n\nimport { PackageManager, SliceMachineConfig } from \"../../types\";\n\nimport { SliceMachineError, InternalError } from \"../../errors\";\n\nimport { SLICE_MACHINE_CONFIG_FILENAME } from \"../../constants/SLICE_MACHINE_CONFIG_FILENAME\";\nimport { TS_CONFIG_FILENAME } from \"../../constants/TS_CONFIG_FILENAME\";\nimport { SLICE_MACHINE_NPM_PACKAGE_NAME } from \"../../constants/SLICE_MACHINE_NPM_PACKAGE_NAME\";\n\nimport { BaseManager } from \"../BaseManager\";\n\ntype ProjectManagerGetSliceMachineConfigPathArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerGetRootArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerCheckIsTypeScriptArgs = {\n\trootOverride?: string;\n};\n\ntype ProjectManagerWriteSliceMachineConfigArgs = {\n\tconfig: SliceMachineConfig;\n\tpath?: string;\n};\n\ntype ProjectManagerInitProjectArgs = {\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerDetectPackageManager = {\n\troot?: string;\n};\n\ntype ProjectManagerInstallDependenciesArgs = {\n\tdependencies: Record<string, string>;\n\tdev?: boolean;\n\tpackageManager?: PackageManager;\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerInstallDependenciesReturnType = {\n\texecaProcess: ExecaChildProcess;\n};\n\nexport class ProjectManager extends BaseManager {\n\tprivate _cachedRoot: string | undefined;\n\tprivate _cachedSliceMachineConfigPath: string | undefined;\n\tprivate _cachedSliceMachineConfig: SliceMachineConfig | undefined;\n\n\tasync getSliceMachineConfigPath(\n\t\targs?: ProjectManagerGetSliceMachineConfigPathArgs,\n\t): Promise<string> {\n\t\tif (this._cachedSliceMachineConfigPath && !args?.ignoreCache) {\n\t\t\treturn this._cachedSliceMachineConfigPath;\n\t\t}\n\n\t\ttry {\n\t\t\tthis._cachedSliceMachineConfigPath = await locateFileUpward(\n\t\t\t\tSLICE_MACHINE_CONFIG_FILENAME,\n\t\t\t\t{ startDir: this.cwd },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find a ${SLICE_MACHINE_CONFIG_FILENAME} file. Please create a config file at the root of your project.`,\n\t\t\t);\n\t\t}\n\n\t\treturn this._cachedSliceMachineConfigPath;\n\t}\n\n\tasync getRoot(args?: ProjectManagerGetRootArgs): Promise<string> {\n\t\tif (this._cachedRoot && !args?.ignoreCache) {\n\t\t\treturn this._cachedRoot;\n\t\t}\n\n\t\tconst sliceMachineConfigFilePath = await this.getSliceMachineConfigPath({\n\t\t\tignoreCache: args?.ignoreCache,\n\t\t});\n\n\t\tthis._cachedRoot = path.dirname(sliceMachineConfigFilePath);\n\n\t\treturn this._cachedRoot;\n\t}\n\n\tasync suggestRoot(): Promise<string> {\n\t\tconst suggestedRootPackageJSON = await locateFileUpward(\"package.json\", {\n\t\t\tstartDir: this.cwd,\n\t\t});\n\n\t\treturn path.dirname(suggestedRootPackageJSON);\n\t}\n\n\tasync suggestSliceMachineConfigPath(): Promise<string> {\n\t\tconst suggestedRoot = await this.suggestRoot();\n\n\t\treturn path.resolve(suggestedRoot, SLICE_MACHINE_CONFIG_FILENAME);\n\t}\n\n\tasync checkIsTypeScript(\n\t\targs?: ProjectManagerCheckIsTypeScriptArgs,\n\t): Promise<boolean> {\n\t\tconst root = args?.rootOverride || (await this.getRoot());\n\t\tconst rootTSConfigPath = path.resolve(root, TS_CONFIG_FILENAME);\n\n\t\t// We just care if the file exists, we don't need access to it\n\t\treturn existsSync(rootTSConfigPath);\n\t}\n\n\tasync getSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\tif (this._cachedSliceMachineConfig) {\n\t\t\treturn this._cachedSliceMachineConfig;\n\t\t} else {\n\t\t\treturn await this.loadSliceMachineConfig();\n\t\t}\n\t}\n\n\tasync writeSliceMachineConfig(\n\t\targs: ProjectManagerWriteSliceMachineConfigArgs,\n\t): Promise<void> {\n\t\tconst configFilePath =\n\t\t\targs.path || (await this.getSliceMachineConfigPath());\n\n\t\tconst config = await format(\n\t\t\tJSON.stringify(args.config, null, 2),\n\t\t\tconfigFilePath,\n\t\t);\n\n\t\tawait fs.writeFile(configFilePath, config, \"utf-8\");\n\t\tdelete this._cachedSliceMachineConfig; // Clear config cache\n\t}\n\n\tasync loadSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\t// TODO: Reload plugins with a fresh plugin runner. Plugins may\n\t\t// have been added or removed.\n\t\tconst configFilePath = await this.getSliceMachineConfigPath();\n\n\t\tlet rawConfig: unknown | undefined;\n\t\ttry {\n\t\t\tconst contents = await fs.readFile(configFilePath, \"utf8\");\n\t\t\trawConfig = JSON.parse(contents);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) {\n\t\t\t\tthrow new SliceMachineError(\n\t\t\t\t\t`Could not parse config file at ${configFilePath}.\\n\\nError Message: ${error.message}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Noop, more specific error is thrown after\n\t\t}\n\n\t\tif (!rawConfig) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(\"No config found.\");\n\t\t}\n\n\t\tconst { value: sliceMachineConfig, error } =\n\t\t\tdecodeSliceMachineConfig(rawConfig);\n\n\t\tif (error) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(`Invalid config. ${error.errors.join(\", \")}`);\n\t\t}\n\n\t\t// Allow cached config reading using `SliceMachineManager.prototype.getProjectConfig()`.\n\t\tthis._cachedSliceMachineConfig = sliceMachineConfig;\n\n\t\treturn sliceMachineConfig;\n\t}\n\n\tasync locateSliceMachineUIDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst sliceMachinePackageJSONPath = require.resolve(\n\t\t\t`${SLICE_MACHINE_NPM_PACKAGE_NAME}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(sliceMachinePackageJSONPath);\n\t}\n\n\tasync getAdapterName(): Promise<string> {\n\t\tconst sliceMachineConfig = await this.getSliceMachineConfig();\n\t\tconst adapterName =\n\t\t\ttypeof sliceMachineConfig.adapter === \"string\"\n\t\t\t\t? sliceMachineConfig.adapter\n\t\t\t\t: sliceMachineConfig.adapter.resolve;\n\n\t\treturn adapterName;\n\t}\n\n\tasync locateAdapterDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\t\tconst adapterName = await this.getAdapterName();\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst adapterPackageJSONPath = require.resolve(\n\t\t\t`${adapterName}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(adapterPackageJSONPath);\n\t}\n\n\tasync initProject(args?: ProjectManagerInitProjectArgs): Promise<void> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args?.log || console.log.bind(this);\n\n\t\tconst { errors } = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"project:init\",\n\t\t\t{\n\t\t\t\tlog,\n\t\t\t\tinstallDependencies: async (args) => {\n\t\t\t\t\tconst { execaProcess } = await this.installDependencies({\n\t\t\t\t\t\tdependencies: args.dependencies,\n\t\t\t\t\t\tdev: args.dev,\n\t\t\t\t\t\tlog,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait execaProcess;\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (errors.length > 0) {\n\t\t\t// TODO: Provide better error message.\n\t\t\tthrow new SliceMachineError(\n\t\t\t\t`Failed to initialize project: ${errors.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync detectPackageManager(\n\t\targs?: ProjectManagerDetectPackageManager,\n\t): Promise<PackageManager> {\n\t\tconst projectRoot = args?.root || (await this.getRoot());\n\n\t\tconst packageManager = await niDetect({\n\t\t\tautoInstall: true,\n\t\t\tcwd: projectRoot,\n\t\t});\n\n\t\treturn packageManager || \"npm\";\n\t}\n\n\tasync installDependencies(\n\t\targs: ProjectManagerInstallDependenciesArgs,\n\t): Promise<ProjectManagerInstallDependenciesReturnType> {\n\t\tconst packageManager =\n\t\t\targs.packageManager || (await this.detectPackageManager());\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args.log || console.log.bind(this);\n\n\t\tconst wrappedLogger = (data: Buffer | string | null) => {\n\t\t\tif (data instanceof Buffer) {\n\t\t\t\tlog(data.toString());\n\t\t\t} else if (typeof data === \"string\") {\n\t\t\t\tlog(data);\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tconst { execaProcess } = await installDependencies({\n\t\t\t\tpackageManager,\n\t\t\t\tdependencies: args.dependencies,\n\t\t\t\tdev: args.dev,\n\t\t\t});\n\n\t\t\t// Don't clutter console with logs when process is non TTY (CI, etc.)\n\t\t\tif (process.stdout.isTTY || process.env.NODE_ENV === \"test\") {\n\t\t\t\texecaProcess.stdout?.on(\"data\", wrappedLogger);\n\t\t\t}\n\t\t\texecaProcess.stderr?.on(\"data\", wrappedLogger);\n\n\t\t\treturn {\n\t\t\t\texecaProcess,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t\"shortMessage\" in error &&\n\t\t\t\t\"stderr\" in error\n\t\t\t) {\n\t\t\t\tthrow new InternalError(\"Package installation failed\", {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"],"names":["error","require","args","niDetect"],"mappings":"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"}
1
+ {"version":3,"file":"ProjectManager.js","sources":["../../../../src/managers/project/ProjectManager.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { detect as niDetect } from \"@antfu/ni\";\nimport { ExecaChildProcess } from \"execa\";\n\nimport { assertPluginsInitialized } from \"../../lib/assertPluginsInitialized\";\nimport { decodeSliceMachineConfig } from \"../../lib/decodeSliceMachineConfig\";\nimport { format } from \"../../lib/format\";\nimport { installDependencies } from \"../../lib/installDependencies\";\nimport { locateFileUpward } from \"../../lib/locateFileUpward\";\n\nimport { PackageManager, SliceMachineConfig } from \"../../types\";\n\nimport { SliceMachineError, InternalError } from \"../../errors\";\n\nimport { SLICE_MACHINE_CONFIG_FILENAME } from \"../../constants/SLICE_MACHINE_CONFIG_FILENAME\";\nimport { TS_CONFIG_FILENAME } from \"../../constants/TS_CONFIG_FILENAME\";\nimport { SLICE_MACHINE_NPM_PACKAGE_NAME } from \"../../constants/SLICE_MACHINE_NPM_PACKAGE_NAME\";\n\nimport { BaseManager } from \"../BaseManager\";\n\ntype ProjectManagerGetSliceMachineConfigPathArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerGetRootArgs = {\n\tignoreCache?: boolean;\n};\n\ntype ProjectManagerCheckIsTypeScriptArgs = {\n\trootOverride?: string;\n};\n\ntype ProjectManagerWriteSliceMachineConfigArgs = {\n\tconfig: SliceMachineConfig;\n\tpath?: string;\n};\n\ntype ProjectManagerInitProjectArgs = {\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerDetectPackageManager = {\n\troot?: string;\n};\n\ntype ProjectManagerInstallDependenciesArgs = {\n\tdependencies: Record<string, string>;\n\tdev?: boolean;\n\tpackageManager?: PackageManager;\n\tlog?: (message: string) => void;\n};\n\ntype ProjectManagerInstallDependenciesReturnType = {\n\texecaProcess: ExecaChildProcess;\n};\n\nexport class ProjectManager extends BaseManager {\n\tprivate _cachedRoot: string | undefined;\n\tprivate _cachedSliceMachineConfigPath: string | undefined;\n\tprivate _cachedSliceMachineConfig: SliceMachineConfig | undefined;\n\n\tasync getSliceMachineConfigPath(\n\t\targs?: ProjectManagerGetSliceMachineConfigPathArgs,\n\t): Promise<string> {\n\t\tif (this._cachedSliceMachineConfigPath && !args?.ignoreCache) {\n\t\t\treturn this._cachedSliceMachineConfigPath;\n\t\t}\n\n\t\ttry {\n\t\t\tthis._cachedSliceMachineConfigPath = await locateFileUpward(\n\t\t\t\tSLICE_MACHINE_CONFIG_FILENAME,\n\t\t\t\t{ startDir: this.cwd },\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new Error(\n\t\t\t\t`Could not find a ${SLICE_MACHINE_CONFIG_FILENAME} file. Please create a config file at the root of your project.`,\n\t\t\t);\n\t\t}\n\n\t\treturn this._cachedSliceMachineConfigPath;\n\t}\n\n\tasync getRoot(args?: ProjectManagerGetRootArgs): Promise<string> {\n\t\tif (this._cachedRoot && !args?.ignoreCache) {\n\t\t\treturn this._cachedRoot;\n\t\t}\n\n\t\tconst sliceMachineConfigFilePath = await this.getSliceMachineConfigPath({\n\t\t\tignoreCache: args?.ignoreCache,\n\t\t});\n\n\t\tthis._cachedRoot = path.dirname(sliceMachineConfigFilePath);\n\n\t\treturn this._cachedRoot;\n\t}\n\n\tasync suggestRoot(): Promise<string> {\n\t\tconst suggestedRootPackageJSON = await locateFileUpward(\"package.json\", {\n\t\t\tstartDir: this.cwd,\n\t\t});\n\n\t\treturn path.dirname(suggestedRootPackageJSON);\n\t}\n\n\tasync suggestSliceMachineConfigPath(): Promise<string> {\n\t\tconst suggestedRoot = await this.suggestRoot();\n\n\t\treturn path.resolve(suggestedRoot, SLICE_MACHINE_CONFIG_FILENAME);\n\t}\n\n\tasync checkIsTypeScript(\n\t\targs?: ProjectManagerCheckIsTypeScriptArgs,\n\t): Promise<boolean> {\n\t\tconst root = args?.rootOverride || (await this.getRoot());\n\t\tconst rootTSConfigPath = path.resolve(root, TS_CONFIG_FILENAME);\n\n\t\t// We just care if the file exists, we don't need access to it\n\t\treturn existsSync(rootTSConfigPath);\n\t}\n\n\tasync getSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\tif (this._cachedSliceMachineConfig) {\n\t\t\treturn this._cachedSliceMachineConfig;\n\t\t} else {\n\t\t\treturn await this.loadSliceMachineConfig();\n\t\t}\n\t}\n\n\tasync writeSliceMachineConfig(\n\t\targs: ProjectManagerWriteSliceMachineConfigArgs,\n\t): Promise<void> {\n\t\tconst configFilePath =\n\t\t\targs.path || (await this.getSliceMachineConfigPath());\n\n\t\tconst config = await format(\n\t\t\tJSON.stringify(args.config, null, 2),\n\t\t\tconfigFilePath,\n\t\t);\n\n\t\tawait fs.writeFile(configFilePath, config, \"utf-8\");\n\t\tdelete this._cachedSliceMachineConfig; // Clear config cache\n\t}\n\n\tasync loadSliceMachineConfig(): Promise<SliceMachineConfig> {\n\t\t// TODO: Reload plugins with a fresh plugin runner. Plugins may\n\t\t// have been added or removed.\n\t\tconst configFilePath = await this.getSliceMachineConfigPath();\n\n\t\tlet rawConfig: unknown | undefined;\n\t\ttry {\n\t\t\tconst contents = await fs.readFile(configFilePath, \"utf8\");\n\t\t\trawConfig = JSON.parse(contents);\n\t\t} catch (error) {\n\t\t\tif (error instanceof SyntaxError) {\n\t\t\t\tthrow new SliceMachineError(\n\t\t\t\t\t`Could not parse config file at ${configFilePath}.\\n\\nError Message: ${error.message}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Noop, more specific error is thrown after\n\t\t}\n\n\t\tif (!rawConfig) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(\"No config found.\");\n\t\t}\n\n\t\tconst { value: sliceMachineConfig, error } =\n\t\t\tdecodeSliceMachineConfig(rawConfig);\n\n\t\tif (error) {\n\t\t\t// TODO: Write a more friendly and useful message.\n\t\t\tthrow new Error(`Invalid config. ${error.errors.join(\", \")}`);\n\t\t}\n\n\t\t// Allow cached config reading using `SliceMachineManager.prototype.getProjectConfig()`.\n\t\tthis._cachedSliceMachineConfig = sliceMachineConfig;\n\n\t\treturn sliceMachineConfig;\n\t}\n\n\tasync locateSliceMachineUIDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst sliceMachinePackageJSONPath = require.resolve(\n\t\t\t`${SLICE_MACHINE_NPM_PACKAGE_NAME}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(sliceMachinePackageJSONPath);\n\t}\n\n\tasync getRepositoryName(): Promise<string> {\n\t\tconst sliceMachineConfig = await this.getSliceMachineConfig();\n\n\t\treturn sliceMachineConfig.repositoryName;\n\t}\n\n\tasync getAdapterName(): Promise<string> {\n\t\tconst sliceMachineConfig = await this.getSliceMachineConfig();\n\t\tconst adapterName =\n\t\t\ttypeof sliceMachineConfig.adapter === \"string\"\n\t\t\t\t? sliceMachineConfig.adapter\n\t\t\t\t: sliceMachineConfig.adapter.resolve;\n\n\t\treturn adapterName;\n\t}\n\n\tasync locateAdapterDir(): Promise<string> {\n\t\tconst projectRoot = await this.getRoot();\n\t\tconst adapterName = await this.getAdapterName();\n\t\tconst require = createRequire(path.join(projectRoot, \"index.js\"));\n\t\tconst adapterPackageJSONPath = require.resolve(\n\t\t\t`${adapterName}/package.json`,\n\t\t);\n\n\t\treturn path.dirname(adapterPackageJSONPath);\n\t}\n\n\tasync initProject(args?: ProjectManagerInitProjectArgs): Promise<void> {\n\t\tassertPluginsInitialized(this.sliceMachinePluginRunner);\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args?.log || console.log.bind(this);\n\n\t\tconst { errors } = await this.sliceMachinePluginRunner.callHook(\n\t\t\t\"project:init\",\n\t\t\t{\n\t\t\t\tlog,\n\t\t\t\tinstallDependencies: async (args) => {\n\t\t\t\t\tconst { execaProcess } = await this.installDependencies({\n\t\t\t\t\t\tdependencies: args.dependencies,\n\t\t\t\t\t\tdev: args.dev,\n\t\t\t\t\t\tlog,\n\t\t\t\t\t});\n\n\t\t\t\t\tawait execaProcess;\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\tif (errors.length > 0) {\n\t\t\t// TODO: Provide better error message.\n\t\t\tthrow new SliceMachineError(\n\t\t\t\t`Failed to initialize project: ${errors.join(\", \")}`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync detectPackageManager(\n\t\targs?: ProjectManagerDetectPackageManager,\n\t): Promise<PackageManager> {\n\t\tconst projectRoot = args?.root || (await this.getRoot());\n\n\t\tconst packageManager = await niDetect({\n\t\t\tautoInstall: true,\n\t\t\tcwd: projectRoot,\n\t\t});\n\n\t\treturn packageManager || \"npm\";\n\t}\n\n\tasync installDependencies(\n\t\targs: ProjectManagerInstallDependenciesArgs,\n\t): Promise<ProjectManagerInstallDependenciesReturnType> {\n\t\tconst packageManager =\n\t\t\targs.packageManager || (await this.detectPackageManager());\n\n\t\t// eslint-disable-next-line no-console\n\t\tconst log = args.log || console.log.bind(this);\n\n\t\tconst wrappedLogger = (data: Buffer | string | null) => {\n\t\t\tif (data instanceof Buffer) {\n\t\t\t\tlog(data.toString());\n\t\t\t} else if (typeof data === \"string\") {\n\t\t\t\tlog(data);\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\tconst { execaProcess } = await installDependencies({\n\t\t\t\tpackageManager,\n\t\t\t\tdependencies: args.dependencies,\n\t\t\t\tdev: args.dev,\n\t\t\t});\n\n\t\t\t// Don't clutter console with logs when process is non TTY (CI, etc.)\n\t\t\tif (process.stdout.isTTY || process.env.NODE_ENV === \"test\") {\n\t\t\t\texecaProcess.stdout?.on(\"data\", wrappedLogger);\n\t\t\t}\n\t\t\texecaProcess.stderr?.on(\"data\", wrappedLogger);\n\n\t\t\treturn {\n\t\t\t\texecaProcess,\n\t\t\t};\n\t\t} catch (error) {\n\t\t\tif (\n\t\t\t\terror instanceof Error &&\n\t\t\t\t\"shortMessage\" in error &&\n\t\t\t\t\"stderr\" in error\n\t\t\t) {\n\t\t\t\tthrow new InternalError(\"Package installation failed\", {\n\t\t\t\t\tcause: error,\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n}\n"],"names":["error","require","args","niDetect"],"mappings":"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"}
@@ -42,14 +42,20 @@ class TelemetryManager extends BaseManager.BaseManager {
42
42
  }
43
43
  // TODO: Should `userId` be automatically populated by the logged in
44
44
  // user? We already have their info via UserRepository.
45
- track(args) {
45
+ async track(args) {
46
46
  var _a;
47
47
  const { event, repository, ...properties } = args;
48
+ let repositoryName = repository;
49
+ if (repositoryName === void 0) {
50
+ try {
51
+ repositoryName = await this.project.getRepositoryName();
52
+ } catch (error) {
53
+ }
54
+ }
48
55
  const payload = {
49
56
  event: types.HumanSegmentEventType[event],
50
57
  properties: {
51
58
  nodeVersion: process.versions.node,
52
- repo: repository,
53
59
  ...properties
54
60
  },
55
61
  context: { ...this._context }
@@ -59,10 +65,10 @@ class TelemetryManager extends BaseManager.BaseManager {
59
65
  } else {
60
66
  payload.anonymousId = this._anonymousID;
61
67
  }
62
- if (args.repository) {
68
+ if (repositoryName) {
63
69
  payload.context || (payload.context = {});
64
70
  (_a = payload.context).groupId || (_a.groupId = {});
65
- payload.context.groupId.Repository = repository;
71
+ payload.context.groupId.Repository = repositoryName;
66
72
  }
67
73
  return new Promise((resolve) => {
68
74
  assertTelemetryInitialized(this._segmentClient);
@@ -99,11 +105,15 @@ class TelemetryManager extends BaseManager.BaseManager {
99
105
  });
100
106
  });
101
107
  }
102
- group(args) {
103
- const { repositoryName, ...traits } = args;
108
+ async group(args) {
109
+ var _a;
110
+ let repositoryName;
111
+ try {
112
+ repositoryName = await this.project.getRepositoryName();
113
+ } catch (error) {
114
+ }
104
115
  const payload = {
105
- groupId: repositoryName,
106
- traits,
116
+ traits: args,
107
117
  context: { ...this._context }
108
118
  };
109
119
  if (this._userID) {
@@ -111,6 +121,12 @@ class TelemetryManager extends BaseManager.BaseManager {
111
121
  } else {
112
122
  payload.anonymousId = this._anonymousID;
113
123
  }
124
+ if (repositoryName) {
125
+ payload.groupId = repositoryName;
126
+ payload.context || (payload.context = {});
127
+ (_a = payload.context).groupId || (_a.groupId = {});
128
+ payload.context.groupId.Repository = repositoryName;
129
+ }
114
130
  return new Promise((resolve) => {
115
131
  assertTelemetryInitialized(this._segmentClient);
116
132
  this._segmentClient.group(payload, (maybeError) => {
@@ -1 +1 @@
1
- {"version":3,"file":"TelemetryManager.cjs","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerInitTelemetryArgs = {\n\tappName: string;\n\tappVersion: string;\n};\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\ntype TelemetryManagerGroupArgs = {\n\trepositoryName: string;\n\tmanualLibsCount: number;\n\tdownloadedLibsCount: number;\n\tnpmLibsCount: number;\n\tdownloadedLibs: string[];\n};\n\ntype TelemetryManagerContext = {\n\tapp: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\tprivate _context: TelemetryManagerContext | undefined = undefined;\n\n\tasync initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t\tthis._context = { app: { name: args.appName, version: args.appVersion } };\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\ttrack(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\tnodeVersion: process.versions.node,\n\t\t\t\trepo: repository,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (args.repository) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repository;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\tconst payload = {\n\t\t\tuserId: args.userID,\n\t\t\tanonymousId: this._anonymousID,\n\t\t\tintegrations: {\n\t\t\t\tIntercom: {\n\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t},\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tthis._userID = args.userID;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tgroup(args: TelemetryManagerGroupArgs): Promise<void> {\n\t\tconst { repositoryName, ...traits } = args;\n\n\t\tconst payload: {\n\t\t\tgroupId: string;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\ttraits?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext>;\n\t\t} = {\n\t\t\tgroupId: repositoryName,\n\t\t\ttraits,\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tthis._segmentClient.group(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.group>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(`An error occurred during Segment group`, maybeError);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":["BaseManager","API_TOKENS","randomUUID","HumanSegmentEventType","readPrismicrc"],"mappings":"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"}
1
+ {"version":3,"file":"TelemetryManager.cjs","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerInitTelemetryArgs = {\n\tappName: string;\n\tappVersion: string;\n};\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\ntype TelemetryManagerGroupArgs = {\n\tmanualLibsCount: number;\n\tdownloadedLibsCount: number;\n\tnpmLibsCount: number;\n\tdownloadedLibs: string[];\n};\n\ntype TelemetryManagerContext = {\n\tapp: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\tprivate _context: TelemetryManagerContext | undefined = undefined;\n\n\tasync initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t\tthis._context = { app: { name: args.appName, version: args.appVersion } };\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\tasync track(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\t\tlet repositoryName = repository;\n\n\t\tif (repositoryName === undefined) {\n\t\t\ttry {\n\t\t\t\trepositoryName = await this.project.getRepositoryName();\n\t\t\t} catch (error) {\n\t\t\t\t// noop, happen only when the user is not in a project\n\t\t\t}\n\t\t}\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\tnodeVersion: process.versions.node,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (repositoryName) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repositoryName;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\tconst payload = {\n\t\t\tuserId: args.userID,\n\t\t\tanonymousId: this._anonymousID,\n\t\t\tintegrations: {\n\t\t\t\tIntercom: {\n\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t},\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tthis._userID = args.userID;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync group(args: TelemetryManagerGroupArgs): Promise<void> {\n\t\tlet repositoryName;\n\n\t\ttry {\n\t\t\trepositoryName = await this.project.getRepositoryName();\n\t\t} catch (error) {\n\t\t\t// noop, happen only when the user is not in a project\n\t\t}\n\n\t\tconst payload: {\n\t\t\tgroupId?: string;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\ttraits?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\ttraits: args,\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (repositoryName) {\n\t\t\tpayload.groupId = repositoryName;\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repositoryName;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tthis._segmentClient.group(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.group>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(`An error occurred during Segment group`, maybeError);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":["BaseManager","API_TOKENS","randomUUID","HumanSegmentEventType","readPrismicrc"],"mappings":"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"}
@@ -10,7 +10,6 @@ type TelemetryManagerIdentifyArgs = {
10
10
  intercomHash: string;
11
11
  };
12
12
  type TelemetryManagerGroupArgs = {
13
- repositoryName: string;
14
13
  manualLibsCount: number;
15
14
  downloadedLibsCount: number;
16
15
  npmLibsCount: number;
@@ -40,14 +40,20 @@ class TelemetryManager extends BaseManager {
40
40
  }
41
41
  // TODO: Should `userId` be automatically populated by the logged in
42
42
  // user? We already have their info via UserRepository.
43
- track(args) {
43
+ async track(args) {
44
44
  var _a;
45
45
  const { event, repository, ...properties } = args;
46
+ let repositoryName = repository;
47
+ if (repositoryName === void 0) {
48
+ try {
49
+ repositoryName = await this.project.getRepositoryName();
50
+ } catch (error) {
51
+ }
52
+ }
46
53
  const payload = {
47
54
  event: HumanSegmentEventType[event],
48
55
  properties: {
49
56
  nodeVersion: process.versions.node,
50
- repo: repository,
51
57
  ...properties
52
58
  },
53
59
  context: { ...this._context }
@@ -57,10 +63,10 @@ class TelemetryManager extends BaseManager {
57
63
  } else {
58
64
  payload.anonymousId = this._anonymousID;
59
65
  }
60
- if (args.repository) {
66
+ if (repositoryName) {
61
67
  payload.context || (payload.context = {});
62
68
  (_a = payload.context).groupId || (_a.groupId = {});
63
- payload.context.groupId.Repository = repository;
69
+ payload.context.groupId.Repository = repositoryName;
64
70
  }
65
71
  return new Promise((resolve) => {
66
72
  assertTelemetryInitialized(this._segmentClient);
@@ -97,11 +103,15 @@ class TelemetryManager extends BaseManager {
97
103
  });
98
104
  });
99
105
  }
100
- group(args) {
101
- const { repositoryName, ...traits } = args;
106
+ async group(args) {
107
+ var _a;
108
+ let repositoryName;
109
+ try {
110
+ repositoryName = await this.project.getRepositoryName();
111
+ } catch (error) {
112
+ }
102
113
  const payload = {
103
- groupId: repositoryName,
104
- traits,
114
+ traits: args,
105
115
  context: { ...this._context }
106
116
  };
107
117
  if (this._userID) {
@@ -109,6 +119,12 @@ class TelemetryManager extends BaseManager {
109
119
  } else {
110
120
  payload.anonymousId = this._anonymousID;
111
121
  }
122
+ if (repositoryName) {
123
+ payload.groupId = repositoryName;
124
+ payload.context || (payload.context = {});
125
+ (_a = payload.context).groupId || (_a.groupId = {});
126
+ payload.context.groupId.Repository = repositoryName;
127
+ }
112
128
  return new Promise((resolve) => {
113
129
  assertTelemetryInitialized(this._segmentClient);
114
130
  this._segmentClient.group(payload, (maybeError) => {
@@ -1 +1 @@
1
- {"version":3,"file":"TelemetryManager.js","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerInitTelemetryArgs = {\n\tappName: string;\n\tappVersion: string;\n};\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\ntype TelemetryManagerGroupArgs = {\n\trepositoryName: string;\n\tmanualLibsCount: number;\n\tdownloadedLibsCount: number;\n\tnpmLibsCount: number;\n\tdownloadedLibs: string[];\n};\n\ntype TelemetryManagerContext = {\n\tapp: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\tprivate _context: TelemetryManagerContext | undefined = undefined;\n\n\tasync initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t\tthis._context = { app: { name: args.appName, version: args.appVersion } };\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\ttrack(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\tnodeVersion: process.versions.node,\n\t\t\t\trepo: repository,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (args.repository) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repository;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\tconst payload = {\n\t\t\tuserId: args.userID,\n\t\t\tanonymousId: this._anonymousID,\n\t\t\tintegrations: {\n\t\t\t\tIntercom: {\n\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t},\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tthis._userID = args.userID;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tgroup(args: TelemetryManagerGroupArgs): Promise<void> {\n\t\tconst { repositoryName, ...traits } = args;\n\n\t\tconst payload: {\n\t\t\tgroupId: string;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\ttraits?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext>;\n\t\t} = {\n\t\t\tgroupId: repositoryName,\n\t\t\ttraits,\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tthis._segmentClient.group(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.group>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(`An error occurred during Segment group`, maybeError);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TelemetryManager.js","sources":["../../../../src/managers/telemetry/TelemetryManager.ts"],"sourcesContent":["import { randomUUID } from \"node:crypto\";\n\nimport SegmentClient from \"analytics-node\";\n\nimport { readPrismicrc } from \"../../lib/prismicrc\";\n\nimport { API_TOKENS } from \"../../constants/API_TOKENS\";\n\nimport { BaseManager } from \"../BaseManager\";\n\nimport {\n\tHumanSegmentEventType,\n\tHumanSegmentEventTypes,\n\tSegmentEvents,\n} from \"./types\";\n\ntype TelemetryManagerInitTelemetryArgs = {\n\tappName: string;\n\tappVersion: string;\n};\n\ntype TelemetryManagerTrackArgs = SegmentEvents;\n\ntype TelemetryManagerIdentifyArgs = {\n\tuserID: string;\n\tintercomHash: string;\n};\n\ntype TelemetryManagerGroupArgs = {\n\tmanualLibsCount: number;\n\tdownloadedLibsCount: number;\n\tnpmLibsCount: number;\n\tdownloadedLibs: string[];\n};\n\ntype TelemetryManagerContext = {\n\tapp: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n};\n\nfunction assertTelemetryInitialized(\n\tsegmentClient: SegmentClient | undefined,\n): asserts segmentClient is NonNullable<typeof segmentClient> {\n\tif (segmentClient == undefined) {\n\t\tthrow new Error(\n\t\t\t\"Telemetry has not been initialized. Run `SliceMachineManager.telemetry.prototype.initTelemetry()` before re-calling this method.\",\n\t\t);\n\t}\n}\n\nexport class TelemetryManager extends BaseManager {\n\tprivate _segmentClient: SegmentClient | undefined = undefined;\n\tprivate _anonymousID: string | undefined = undefined;\n\tprivate _userID: string | undefined = undefined;\n\tprivate _context: TelemetryManagerContext | undefined = undefined;\n\n\tasync initTelemetry(args: TelemetryManagerInitTelemetryArgs): Promise<void> {\n\t\tif (this._segmentClient) {\n\t\t\t// Prevent subsequent initializations.\n\t\t\treturn;\n\t\t}\n\n\t\tthis._segmentClient = new SegmentClient(API_TOKENS.SegmentKey, {\n\t\t\t// Since it's a local app, we do not benefit from event batching the way a server would normally do, all tracking event will be awaited.\n\t\t\tflushAt: 1,\n\t\t\t// TODO: Verify that this actually does not send data to Segment when false.\n\t\t\tenable: await this.checkIsTelemetryEnabled(),\n\t\t\terrorHandler: () => {\n\t\t\t\t// noop - We don't care if the tracking event\n\t\t\t\t// failed. Some users or networks intentionally\n\t\t\t\t// block Segment, so we can't block the app if\n\t\t\t\t// a tracking event is unsuccessful.\n\t\t\t},\n\t\t});\n\t\tthis._anonymousID = randomUUID();\n\t\tthis._context = { app: { name: args.appName, version: args.appVersion } };\n\t}\n\n\t// TODO: Should `userId` be automatically populated by the logged in\n\t// user? We already have their info via UserRepository.\n\tasync track(args: TelemetryManagerTrackArgs): Promise<void> {\n\t\tconst { event, repository, ...properties } = args;\n\t\tlet repositoryName = repository;\n\n\t\tif (repositoryName === undefined) {\n\t\t\ttry {\n\t\t\t\trepositoryName = await this.project.getRepositoryName();\n\t\t\t} catch (error) {\n\t\t\t\t// noop, happen only when the user is not in a project\n\t\t\t}\n\t\t}\n\n\t\tconst payload: {\n\t\t\tevent: HumanSegmentEventTypes;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\tproperties?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\tevent: HumanSegmentEventType[event],\n\t\t\tproperties: {\n\t\t\t\tnodeVersion: process.versions.node,\n\t\t\t\t...properties,\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (repositoryName) {\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repositoryName;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.track(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.track>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(\n\t\t\t\t\t\t\t`An error occurred during Segment tracking`,\n\t\t\t\t\t\t\tmaybeError,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\t// TODO: Should `userID` and `intercomHash` be automatically populated\n\t// by the logged in user? We already have their info via\n\t// UserRepository.\n\tidentify(args: TelemetryManagerIdentifyArgs): Promise<void> {\n\t\tconst payload = {\n\t\t\tuserId: args.userID,\n\t\t\tanonymousId: this._anonymousID,\n\t\t\tintegrations: {\n\t\t\t\tIntercom: {\n\t\t\t\t\tuser_hash: args.intercomHash,\n\t\t\t\t},\n\t\t\t},\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tthis._userID = args.userID;\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\t// TODO: Make sure client fails gracefully when no internet connection\n\t\t\tthis._segmentClient.identify(payload, (maybeError?: Error) => {\n\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\tconsole.warn(`An error occurred during Segment identify`, maybeError);\n\t\t\t\t}\n\n\t\t\t\tresolve();\n\t\t\t});\n\t\t});\n\t}\n\n\tasync group(args: TelemetryManagerGroupArgs): Promise<void> {\n\t\tlet repositoryName;\n\n\t\ttry {\n\t\t\trepositoryName = await this.project.getRepositoryName();\n\t\t} catch (error) {\n\t\t\t// noop, happen only when the user is not in a project\n\t\t}\n\n\t\tconst payload: {\n\t\t\tgroupId?: string;\n\t\t\tuserId?: string;\n\t\t\tanonymousId?: string;\n\t\t\ttraits?: Record<string, unknown>;\n\t\t\tcontext?: Partial<TelemetryManagerContext> & {\n\t\t\t\tgroupId?: {\n\t\t\t\t\tRepository?: string;\n\t\t\t\t};\n\t\t\t};\n\t\t} = {\n\t\t\ttraits: args,\n\t\t\tcontext: { ...this._context },\n\t\t};\n\n\t\tif (this._userID) {\n\t\t\tpayload.userId = this._userID;\n\t\t} else {\n\t\t\tpayload.anonymousId = this._anonymousID;\n\t\t}\n\n\t\tif (repositoryName) {\n\t\t\tpayload.groupId = repositoryName;\n\t\t\tpayload.context ||= {};\n\t\t\tpayload.context.groupId ||= {};\n\t\t\tpayload.context.groupId.Repository = repositoryName;\n\t\t}\n\n\t\treturn new Promise((resolve) => {\n\t\t\tassertTelemetryInitialized(this._segmentClient);\n\n\t\t\tthis._segmentClient.group(\n\t\t\t\tpayload as Parameters<typeof this._segmentClient.group>[0],\n\t\t\t\t(maybeError?: Error) => {\n\t\t\t\t\tif (maybeError && import.meta.env.DEV) {\n\t\t\t\t\t\t// TODO: Not sure how we want to deal with that\n\t\t\t\t\t\tconsole.warn(`An error occurred during Segment group`, maybeError);\n\t\t\t\t\t}\n\n\t\t\t\t\tresolve();\n\t\t\t\t},\n\t\t\t);\n\t\t});\n\t}\n\n\tasync checkIsTelemetryEnabled(): Promise<boolean> {\n\t\tlet root: string;\n\t\ttry {\n\t\t\troot = await this.project.getRoot();\n\t\t} catch {\n\t\t\troot = await this.project.suggestRoot();\n\t\t}\n\n\t\treturn readPrismicrc(root).telemetry !== false;\n\t}\n}\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@slicemachine/manager",
3
- "version": "0.9.3-dev-next-release.1",
3
+ "version": "0.9.3-dev-next-release.3",
4
4
  "description": "Manage all aspects of a Slice Machine project.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -65,7 +65,7 @@
65
65
  "@prismicio/custom-types-client": "^1.2.0-alpha.0",
66
66
  "@prismicio/mocks": "^2.0.0-alpha.2",
67
67
  "@prismicio/types-internal": "^2.0.0",
68
- "@slicemachine/plugin-kit": "^0.4.13-dev-next-release.1",
68
+ "@slicemachine/plugin-kit": "^0.4.13-dev-next-release.3",
69
69
  "@wooorm/starry-night": "^1.6.0",
70
70
  "analytics-node": "^6.2.0",
71
71
  "cookie": "^0.5.0",
@@ -131,5 +131,5 @@
131
131
  "engines": {
132
132
  "node": ">=14.15.0"
133
133
  },
134
- "gitHead": "7d282965455eb4123e6c418bcd3633109424a42b"
134
+ "gitHead": "f6b7bb438e7478cbdc15468d4baabfc03971fb95"
135
135
  }
@@ -193,6 +193,12 @@ export class ProjectManager extends BaseManager {
193
193
  return path.dirname(sliceMachinePackageJSONPath);
194
194
  }
195
195
 
196
+ async getRepositoryName(): Promise<string> {
197
+ const sliceMachineConfig = await this.getSliceMachineConfig();
198
+
199
+ return sliceMachineConfig.repositoryName;
200
+ }
201
+
196
202
  async getAdapterName(): Promise<string> {
197
203
  const sliceMachineConfig = await this.getSliceMachineConfig();
198
204
  const adapterName =
@@ -27,7 +27,6 @@ type TelemetryManagerIdentifyArgs = {
27
27
  };
28
28
 
29
29
  type TelemetryManagerGroupArgs = {
30
- repositoryName: string;
31
30
  manualLibsCount: number;
32
31
  downloadedLibsCount: number;
33
32
  npmLibsCount: number;
@@ -81,8 +80,17 @@ export class TelemetryManager extends BaseManager {
81
80
 
82
81
  // TODO: Should `userId` be automatically populated by the logged in
83
82
  // user? We already have their info via UserRepository.
84
- track(args: TelemetryManagerTrackArgs): Promise<void> {
83
+ async track(args: TelemetryManagerTrackArgs): Promise<void> {
85
84
  const { event, repository, ...properties } = args;
85
+ let repositoryName = repository;
86
+
87
+ if (repositoryName === undefined) {
88
+ try {
89
+ repositoryName = await this.project.getRepositoryName();
90
+ } catch (error) {
91
+ // noop, happen only when the user is not in a project
92
+ }
93
+ }
86
94
 
87
95
  const payload: {
88
96
  event: HumanSegmentEventTypes;
@@ -98,7 +106,6 @@ export class TelemetryManager extends BaseManager {
98
106
  event: HumanSegmentEventType[event],
99
107
  properties: {
100
108
  nodeVersion: process.versions.node,
101
- repo: repository,
102
109
  ...properties,
103
110
  },
104
111
  context: { ...this._context },
@@ -110,10 +117,10 @@ export class TelemetryManager extends BaseManager {
110
117
  payload.anonymousId = this._anonymousID;
111
118
  }
112
119
 
113
- if (args.repository) {
120
+ if (repositoryName) {
114
121
  payload.context ||= {};
115
122
  payload.context.groupId ||= {};
116
- payload.context.groupId.Repository = repository;
123
+ payload.context.groupId.Repository = repositoryName;
117
124
  }
118
125
 
119
126
  return new Promise((resolve) => {
@@ -169,18 +176,27 @@ export class TelemetryManager extends BaseManager {
169
176
  });
170
177
  }
171
178
 
172
- group(args: TelemetryManagerGroupArgs): Promise<void> {
173
- const { repositoryName, ...traits } = args;
179
+ async group(args: TelemetryManagerGroupArgs): Promise<void> {
180
+ let repositoryName;
181
+
182
+ try {
183
+ repositoryName = await this.project.getRepositoryName();
184
+ } catch (error) {
185
+ // noop, happen only when the user is not in a project
186
+ }
174
187
 
175
188
  const payload: {
176
- groupId: string;
189
+ groupId?: string;
177
190
  userId?: string;
178
191
  anonymousId?: string;
179
192
  traits?: Record<string, unknown>;
180
- context?: Partial<TelemetryManagerContext>;
193
+ context?: Partial<TelemetryManagerContext> & {
194
+ groupId?: {
195
+ Repository?: string;
196
+ };
197
+ };
181
198
  } = {
182
- groupId: repositoryName,
183
- traits,
199
+ traits: args,
184
200
  context: { ...this._context },
185
201
  };
186
202
 
@@ -190,6 +206,13 @@ export class TelemetryManager extends BaseManager {
190
206
  payload.anonymousId = this._anonymousID;
191
207
  }
192
208
 
209
+ if (repositoryName) {
210
+ payload.groupId = repositoryName;
211
+ payload.context ||= {};
212
+ payload.context.groupId ||= {};
213
+ payload.context.groupId.Repository = repositoryName;
214
+ }
215
+
193
216
  return new Promise((resolve) => {
194
217
  assertTelemetryInitialized(this._segmentClient);
195
218